[API/Mobidziennik] Fix too much clearing grades from DB. Add performance debugging to Data and ApiService.

This commit is contained in:
Kuba Szczodrzyński 2020-02-19 16:38:11 +01:00
parent 626bbfa7a4
commit f0447dc455
5 changed files with 50 additions and 21 deletions

View File

@ -54,6 +54,7 @@ class ApiService : Service() {
private var taskIsRunning = false private var taskIsRunning = false
private var taskRunning: IApiTask? = null // for debug purposes private var taskRunning: IApiTask? = null // for debug purposes
private var taskRunningId = -1 private var taskRunningId = -1
private var taskStartTime = 0L
private var taskMaximumId = 0 private var taskMaximumId = 0
private var taskProfileId = -1 private var taskProfileId = -1
@ -74,7 +75,7 @@ class ApiService : Service() {
private val taskCallback = object : EdziennikCallback { private val taskCallback = object : EdziennikCallback {
override fun onCompleted() { override fun onCompleted() {
lastEventTime = System.currentTimeMillis() lastEventTime = System.currentTimeMillis()
d(TAG, "Task $taskRunningId (profile $taskProfileId) - $taskProgressText - finished") d(TAG, "Task $taskRunningId (profile $taskProfileId) finished in ${System.currentTimeMillis()-taskStartTime}")
EventBus.getDefault().postSticky(ApiTaskFinishedEvent(taskProfileId)) EventBus.getDefault().postSticky(ApiTaskFinishedEvent(taskProfileId))
clearTask() clearTask()
@ -162,7 +163,7 @@ class ApiService : Service() {
taskProgress = -1f taskProgress = -1f
taskProgressText = task.taskName taskProgressText = task.taskName
d(TAG, "Executing task $taskRunningId ($taskProgressText) - $task") d(TAG, "Executing task $taskRunningId - ${task::class.java.name}")
// update the notification // update the notification
notification.setCurrentTask(taskRunningId, taskProgressText).post() notification.setCurrentTask(taskRunningId, taskProgressText).post()
@ -172,6 +173,7 @@ class ApiService : Service() {
task.profile?.let { syncingProfiles.add(it) } task.profile?.let { syncingProfiles.add(it) }
taskStartTime = System.currentTimeMillis()
try { try {
when (task) { when (task) {
is EdziennikTask -> task.run(app, taskCallback) is EdziennikTask -> task.run(app, taskCallback)

View File

@ -74,17 +74,6 @@ class MobidziennikApiGrades(val data: DataMobidziennik, rows: List<String>) {
subjectId) subjectId)
gradeObject.type = type gradeObject.type = type
data.toRemove.addAll(listOf(
TYPE_NORMAL,
TYPE_SEMESTER1_FINAL,
TYPE_SEMESTER2_FINAL,
TYPE_SEMESTER1_PROPOSED,
TYPE_SEMESTER2_PROPOSED,
TYPE_YEAR_FINAL,
TYPE_YEAR_PROPOSED
).map {
DataRemoveModel.Grades.semesterWithType(profile.currentSemester, it)
})
data.gradeList.add(gradeObject) data.gradeList.add(gradeObject)
data.metadataList.add( data.metadataList.add(
Metadata( Metadata(
@ -97,5 +86,16 @@ class MobidziennikApiGrades(val data: DataMobidziennik, rows: List<String>) {
)) ))
addedDate++ addedDate++
} }
data.toRemove.addAll(listOf(
TYPE_NORMAL,
TYPE_SEMESTER1_FINAL,
TYPE_SEMESTER2_FINAL,
TYPE_SEMESTER1_PROPOSED,
TYPE_SEMESTER2_PROPOSED,
TYPE_YEAR_FINAL,
TYPE_YEAR_PROPOSED
).map {
DataRemoveModel.Grades.semesterWithType(profile.currentSemester, it)
})
}}} }}}
} }

View File

@ -10,7 +10,6 @@ import pl.szczodrzynski.edziennik.data.api.Regexes
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.ENDPOINT_MOBIDZIENNIK_WEB_GRADES import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.ENDPOINT_MOBIDZIENNIK_WEB_GRADES
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
import pl.szczodrzynski.edziennik.data.db.entity.Grade import pl.szczodrzynski.edziennik.data.db.entity.Grade
import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
@ -148,7 +147,6 @@ class MobidziennikWebGrades(override val data: DataMobidziennik,
} }
} }
data.toRemove.add(DataRemoveModel.Grades.semesterWithType(currentSemester, Grade.TYPE_NORMAL))
data.setSyncNext(ENDPOINT_MOBIDZIENNIK_WEB_GRADES, SYNC_ALWAYS) data.setSyncNext(ENDPOINT_MOBIDZIENNIK_WEB_GRADES, SYNC_ALWAYS)
onSuccess(ENDPOINT_MOBIDZIENNIK_WEB_GRADES) onSuccess(ENDPOINT_MOBIDZIENNIK_WEB_GRADES)
} }

View File

@ -11,12 +11,13 @@ import pl.szczodrzynski.edziennik.data.api.ERROR_REQUEST_FAILURE
import pl.szczodrzynski.edziennik.data.api.interfaces.EndpointCallback import pl.szczodrzynski.edziennik.data.api.interfaces.EndpointCallback
import pl.szczodrzynski.edziennik.data.db.AppDb import pl.szczodrzynski.edziennik.data.db.AppDb
import pl.szczodrzynski.edziennik.data.db.entity.* import pl.szczodrzynski.edziennik.data.db.entity.*
import pl.szczodrzynski.edziennik.utils.Utils.d import pl.szczodrzynski.edziennik.utils.Utils
import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.edziennik.utils.models.Date
abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginStore) { abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginStore) {
companion object { companion object {
private const val TAG = "Data" private const val TAG = "Data"
private val DEBUG = true && BuildConfig.DEBUG
} }
var fakeLogin = false var fakeLogin = false
@ -148,6 +149,11 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
} }
} }
private fun d(message: String) {
if (DEBUG)
Utils.d(TAG, message)
}
fun clear() { fun clear() {
loginMethods.clear() loginMethods.clear()
@ -185,13 +191,16 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
open fun saveData() { open fun saveData() {
if (profile == null) if (profile == null)
return // return on first login return // return on first login
val totalStart = System.currentTimeMillis()
var startTime = System.currentTimeMillis()
d("Saving data to DB")
profile.userCode = generateUserCode() profile.userCode = generateUserCode()
db.profileDao().add(profile) db.profileDao().add(profile)
db.loginStoreDao().add(loginStore) db.loginStoreDao().add(loginStore)
if (profile.id == app.profile?.id) { if (profile.id == app.profile.id) {
app.profile.apply { app.profile.apply {
name = profile.name name = profile.name
subname = profile.subname subname = profile.subname
@ -209,6 +218,9 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
} }
} }
d("Profiles saved in ${System.currentTimeMillis()-startTime} ms")
startTime = System.currentTimeMillis()
// always present and not empty, during every sync // always present and not empty, during every sync
db.endpointTimerDao().addAll(endpointTimers) db.endpointTimerDao().addAll(endpointTimers)
if (teacherOnConflictStrategy == OnConflictStrategy.IGNORE) if (teacherOnConflictStrategy == OnConflictStrategy.IGNORE)
@ -223,6 +235,9 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
db.gradeCategoryDao().clear(profileId) db.gradeCategoryDao().clear(profileId)
db.gradeCategoryDao().addAll(gradeCategories.values()) db.gradeCategoryDao().addAll(gradeCategories.values())
d("Maps saved in ${System.currentTimeMillis()-startTime} ms")
startTime = System.currentTimeMillis()
// may be empty - extracted from DB on demand, by an endpoint // may be empty - extracted from DB on demand, by an endpoint
if (classrooms.size > 0) if (classrooms.size > 0)
db.classroomDao().addAll(classrooms.values()) db.classroomDao().addAll(classrooms.values())
@ -237,8 +252,12 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
if (librusLessons.size > 0) if (librusLessons.size > 0)
db.librusLessonDao().addAll(librusLessons.values()) db.librusLessonDao().addAll(librusLessons.values())
d("On-demand maps saved in ${System.currentTimeMillis()-startTime} ms")
startTime = System.currentTimeMillis()
// clear DB with DataRemoveModels added by endpoints // clear DB with DataRemoveModels added by endpoints
for (model in toRemove) { for (model in toRemove) {
d("Clearing DB with $model")
when (model) { when (model) {
is DataRemoveModel.Timetable -> model.commit(profileId, db.timetableDao()) is DataRemoveModel.Timetable -> model.commit(profileId, db.timetableDao())
is DataRemoveModel.Grades -> model.commit(profileId, db.gradeDao()) is DataRemoveModel.Grades -> model.commit(profileId, db.gradeDao())
@ -246,11 +265,17 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
} }
} }
d("DB cleared in ${System.currentTimeMillis()-startTime} ms")
startTime = System.currentTimeMillis()
if (metadataList.isNotEmpty()) if (metadataList.isNotEmpty())
db.metadataDao().addAllIgnore(metadataList) db.metadataDao().addAllIgnore(metadataList)
if (setSeenMetadataList.isNotEmpty()) if (setSeenMetadataList.isNotEmpty())
db.metadataDao().setSeen(setSeenMetadataList) db.metadataDao().setSeen(setSeenMetadataList)
d("Metadata saved in ${System.currentTimeMillis()-startTime} ms")
startTime = System.currentTimeMillis()
if (lessonList.isNotEmpty()) { if (lessonList.isNotEmpty()) {
db.timetableDao() += lessonList db.timetableDao() += lessonList
} }
@ -283,6 +308,10 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
db.messageRecipientDao().addAll(messageRecipientList) db.messageRecipientDao().addAll(messageRecipientList)
if (messageRecipientIgnoreList.isNotEmpty()) if (messageRecipientIgnoreList.isNotEmpty())
db.messageRecipientDao().addAllIgnore(messageRecipientIgnoreList) db.messageRecipientDao().addAllIgnore(messageRecipientIgnoreList)
d("Other data saved in ${System.currentTimeMillis()-startTime} ms")
d("Total save time: ${System.currentTimeMillis()-totalStart} ms")
} }
fun setSyncNext(endpointId: Int, syncIn: Long? = null, viewId: Int? = null, syncAt: Long? = null) { fun setSyncNext(endpointId: Int, syncIn: Long? = null, viewId: Int? = null, syncAt: Long? = null) {
@ -309,7 +338,7 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
abstract fun generateUserCode(): String abstract fun generateUserCode(): String
fun cancel() { fun cancel() {
d("Data", "Cancelled") d("Cancelled")
cancelled = true cancelled = true
saveData() saveData()
} }

View File

@ -10,7 +10,7 @@ import pl.szczodrzynski.edziennik.data.db.dao.TimetableDao
import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.edziennik.utils.models.Date
open class DataRemoveModel { open class DataRemoveModel {
class Timetable(private val dateFrom: Date?, private val dateTo: Date?) : DataRemoveModel() { data class Timetable(private val dateFrom: Date?, private val dateTo: Date?) : DataRemoveModel() {
companion object { companion object {
fun from(dateFrom: Date) = Timetable(dateFrom, null) fun from(dateFrom: Date) = Timetable(dateFrom, null)
fun to(dateTo: Date) = Timetable(null, dateTo) fun to(dateTo: Date) = Timetable(null, dateTo)
@ -27,7 +27,7 @@ open class DataRemoveModel {
} }
} }
class Grades(private val all: Boolean, private val semester: Int?, private val type: Int?) : DataRemoveModel() { data class Grades(private val all: Boolean, private val semester: Int?, private val type: Int?) : DataRemoveModel() {
companion object { companion object {
fun all() = Grades(true, null, null) fun all() = Grades(true, null, null)
fun allWithType(type: Int) = Grades(true, null, type) fun allWithType(type: Int) = Grades(true, null, type)
@ -47,7 +47,7 @@ open class DataRemoveModel {
} }
} }
class Events(private val type: Long?, private val exceptType: Long?, private val exceptTypes: List<Long>?) : DataRemoveModel() { data class Events(private val type: Long?, private val exceptType: Long?, private val exceptTypes: List<Long>?) : DataRemoveModel() {
companion object { companion object {
fun futureExceptType(exceptType: Long) = Events(null, exceptType, null) fun futureExceptType(exceptType: Long) = Events(null, exceptType, null)
fun futureExceptTypes(exceptTypes: List<Long>) = Events(null, null, exceptTypes) fun futureExceptTypes(exceptTypes: List<Long>) = Events(null, null, exceptTypes)