Войти Регистрация
Конкурентность

31. Предзагрузка превью в VK Клипах

Средняя

Kotlin · 37 строк

При каждой остановке ленты preload получает 30 следующих клипов. Кэш — LinkedHashMap на 300 превью, общий для экрана. Если пользователь листает дальше, корутину предзагрузки отменяют. cdn.preview — suspend-функция, cdn.fallbackPreview — обычная блокирующая: читает заглушку с диска.

Отметьте строки с ошибками.

В работе: Android-приложение VK, экран ленты клипов.

Как проверяем Нажмите на строку с ошибкой и коротко напишите, что не так. Баг засчитан, если отмечена хотя бы одна его строка. Зачёт — найдено не меньше 60 % багов с учётом серьёзности (критичный весит 3, обычный 2, мелкий 1), а лишних отметок не больше, чем багов в коде. Пустые строки, скобки и комментарии лишними не считаем. Плюс 1 вопрос про поведение программы — на зачёт не влияют. Ответ один на подход: после него показываем разбор.
корутиныMutexповторный захватCancellationExceptionгонка

Источник: наша задача на данных VK: лента VK Клипов. Условие пересказано своими словами.

  1. import kotlinx.coroutines.*
  2. import kotlinx.coroutines.sync.Mutex
  3. import kotlinx.coroutines.sync.withLock
  4. class PreviewPreloader(
  5. private val cdn: Cdn,
  6. private val cache: MutableMap<Long, ByteArray>,
  7. private val log: Logger,
  8. ) {
  9. private val mutex = Mutex()
  10. var loaded = 0
  11. private set
  12. // Предзагрузка превью следующих 30 клипов.
  13. suspend fun preload(clipIds: List<Long>) = coroutineScope {
  14. clipIds.forEach { id ->
  15. launch(Dispatchers.IO) {
  16. val bytes = runCatching { cdn.preview(id) }.getOrElse { e ->
  17. log.warn("превью $id не загрузилось", e)
  18. cdn.fallbackPreview(id)
  19. }
  20. put(id, bytes)
  21. loaded++
  22. }
  23. }
  24. }
  25. private suspend fun put(id: Long, bytes: ByteArray) = mutex.withLock {
  26. cache[id] = bytes
  27. if (cache.size > 300) evictOldest()
  28. }
  29. private suspend fun evictOldest() = mutex.withLock {
  30. val oldest = cache.keys.first()
  31. cache.remove(oldest)
  32. }
  33. }