package jp.juggler.subwaytooter.util import android.content.Context import android.os.SystemClock import jp.juggler.subwaytooter.api.ApiTask import jp.juggler.subwaytooter.api.TootParser import jp.juggler.subwaytooter.api.auth.authRepo import jp.juggler.subwaytooter.api.entity.TootAccount import jp.juggler.subwaytooter.api.runApiTask2 import jp.juggler.subwaytooter.table.SavedAccount import jp.juggler.util.coroutine.AppDispatchers import jp.juggler.util.log.LogCategory import jp.juggler.util.network.toPostRequestBuilder import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.withContext object AccountCache { private val log = LogCategory("AccountCache") private class CacheItem(val timeCached: Long, val result: TootAccount?) private val cacheMutex = Mutex() private val map = HashMap() private const val CACHE_EXPIRE_SUCCESS = 300_000L private const val CACHE_EXPIRE_ERROR = 120_000L suspend fun load(context: Context, src: SavedAccount?): TootAccount? { src ?: return null return withContext(AppDispatchers.IO) { cacheMutex.withLock { val key = src.acct.ascii try { val cached = map[key] if (cached != null) { val now = SystemClock.elapsedRealtime() val expire = if (cached.result != null) CACHE_EXPIRE_SUCCESS else CACHE_EXPIRE_ERROR if (cached.timeCached >= now - expire) return@withLock cached.result } val newAccount = context.runApiTask2( src, progressStyle = ApiTask.PROGRESS_NONE, ) { client -> val json = if (src.isMisskey) { val result = client.request( "/api/i", src.putMisskeyApiToken().toPostRequestBuilder() ) ?: return@runApiTask2 null result.error?.let { error(it) } result.jsonObject } else { // 承認待ち状態のチェック authRepo.checkConfirmed(src, client) val result = client.request( "/api/v1/accounts/verify_credentials" ) ?: return@runApiTask2 null result.error?.let { error(it) } result.jsonObject } TootParser(this, src).account(json) ?: error("parse error.") } map[key] = CacheItem(SystemClock.elapsedRealtime(), newAccount) return@withLock newAccount } catch (ex: Throwable) { log.e(ex, "failed.") map[key] = CacheItem(SystemClock.elapsedRealtime(), null) return@withLock null } } } } }