Donor cache¶
При customize-импорте нам надо качать отдельные компоненты из чужих редаксов. Если юзер экспериментирует — берёт минимапу из X, потом меняет на Y, потом снова на X — мы не хотим качать тот же файл по 4 раза.
Где живёт¶
%LocalAppData%\MiamiGraphics\cache\donors\
├── <reduxId>_<versionId>_minimap.bin
├── <reduxId>_<versionId>_crosshair.bin
├── <reduxId>_<versionId>_tracers.bin
├── <reduxId>_<versionId>_armor.zip
└── ...
<versionId> это GUID конкретной version row, или 00000000-0000-0000-0000-000000000000 для legacy donor'ов без версий.
Логика¶
private async Task<string> EnsureDonorCachedAsync(
string donorReduxId,
string componentType,
HttpClient http,
Action<string, int>? emitDetail,
Guid? donorVersionId)
{
var cacheKey = $"{donorReduxId}_{donorVersionId ?? Guid.Empty}_{componentType}";
var cachePath = Path.Combine(_donorCacheDir, cacheKey + ".bin");
if (File.Exists(cachePath))
{
emitDetail?.Invoke($"донор-кэш hit: {componentType}", 0);
return cachePath;
}
// Resolve URL для конкретной версии
var resolved = await ResolveVersionAsync(donorReduxId, donorVersionId);
if (!resolved.Urls.Components.TryGetValue(componentType, out var url))
throw new InvalidOperationException($"У донора нет компонента {componentType}");
emitDetail?.Invoke($"качаем донор: {componentType}", 0);
await DownloadFileAsync(http, url, cachePath, ct);
return cachePath;
}
Cache не проверяет SHA при hit — мы доверяем что то что лежит на диске это то что мы скачали раньше. Если кто-то руками подменил файл — это его проблема.
Cache invalidation¶
Не делаем автоматическую. Cache накапливается пока пользователь активно делает customize. Если ему надоел и он удалил cache/donors/ руками — следующий customize заново качает.
Альтернативы которые отвергнуты:
- TTL (например удалять файлы старше 30 дней). Сложно, не нужно — диск 5 ГБ под весь backup, donor-cache редко больше 1 ГБ.
- LRU eviction (как AssetCache). Бессмысленно — donor-файлы маленькие (10-50 МБ каждый), редко.
- Версионирование с server-side ETag. Перерendant работа — donor-файлы immutable в R2 (мы загружаем
<id>/<version>/<component>.binи не перезаписываем).
Когда donor обновился¶
Edge case: админ заменил <reduxId>/v1/minimap.gfx на R2 (например исправил баг в моде). У юзера в cache лежит старая версия.
Сейчас юзер получит старую при customize. Это ограничение текущего дизайна — мы не отслеживаем когда donor обновился.
В будущем планируем добавить <reduxId>/v1/minimap.gfx.sha256 файл рядом — если SHA отличается от закешированного → re-download. Сейчас не реализовано потому что:
- админы редко перезаливают существующие redux'ы (обычно создают новую версию V2);
- юзеры могут вручную clean cache через Settings → Reset cache.
Cleanup при uninstall¶
Inno uninstaller удаляет всю %LocalAppData%\MiamiGraphics\ целиком, включая cache/donors/. Никаких специальных cleanup-стадий.