perf(teacher): lower sync memory footprint

- Reduce sync parallelism 5 -> 2 to cap peak heap while bulk-fetching
  all departments for a period
- Replace per-write rows (insert schedule/days/lessons separately) with a
  single @Transaction replaceSchedule() so Room invalidates observers once
  per department instead of ~4x each, cutting main-thread recompositions
  and intermediate allocations during the 38-department sync
This commit is contained in:
2026-09-20 02:43:54 +03:00
parent 1d55e84e96
commit 6189540acf
2 changed files with 27 additions and 24 deletions
@@ -156,33 +156,15 @@ class TeacherScheduleRepositoryImpl(
val html = VyatsuHttpClient.getBytes(url).toString(Charsets.UTF_8)
val parsed = TeacherScheduleParser.parse(html)
val scheduleId = scheduleDao.insertSchedule(
TeacherScheduleEntity(
departmentId = target.departmentId,
season = season,
weekStart = target.weekStart,
weekEnd = target.weekEnd,
lastSyncedAt = now()
)
)
replaceDays(scheduleId, parsed.days)
}
private suspend fun replaceDays(scheduleId: Long, days: List<Day>) {
scheduleDao.deleteDaysForSchedule(scheduleId)
val dayEntities = days.map {
TeacherDayEntity(scheduleId = scheduleId, date = it.date.toEpochDay())
val dayEntities = parsed.days.map {
TeacherDayEntity(scheduleId = 0, date = it.date.toEpochDay())
}
val dayIds = scheduleDao.insertDays(dayEntities)
val dayIdByDate = dayEntities.zip(dayIds).associate { (day, id) ->
LocalDate.ofEpochDay(day.date) to id
}
val lessons = days.flatMap { day ->
val lessonEntities = parsed.days.flatMap { day ->
day.intervals.flatMapIndexed { slotIndex, slot ->
slot.lessons.mapIndexedNotNull { lessonIndex, lesson ->
val teacher = lesson.teacher ?: return@mapIndexedNotNull null
TeacherLessonEntity(
dayId = dayIdByDate.getValue(day.date),
dayId = 0,
date = day.date.toEpochDay(),
slotIndex = slotIndex,
start = slot.start.toMinutesOfDay(),
@@ -199,7 +181,17 @@ class TeacherScheduleRepositoryImpl(
}
}
}
scheduleDao.insertLessons(lessons)
scheduleDao.replaceSchedule(
TeacherScheduleEntity(
departmentId = target.departmentId,
season = season,
weekStart = target.weekStart,
weekEnd = target.weekEnd,
lastSyncedAt = now()
),
dayEntities,
lessonEntities
)
}
private suspend fun trimToRecent(keepDistinctPeriods: Int) {
@@ -262,7 +254,7 @@ class TeacherScheduleRepositoryImpl(
companion object {
private const val STALE_WINDOW_MS = 12 * 60 * 60 * 1000L
private const val PARALLELISM = 5
private const val PARALLELISM = 2
private const val TAG = "TeacherScheduleRepo"
private val RANGE_FMT = java.time.format.DateTimeFormatter.ofPattern("ddMMyyyy")
}