Update TouchTokenManager to not cache the tokens

This commit is contained in:
Ming Ming 2022-07-22 16:48:16 +08:00
parent 423d7aa364
commit e5fa14943c
6 changed files with 32 additions and 24 deletions

View file

@ -417,7 +417,7 @@ class ScanAccountDirBloc
Future<List<File>> _queryOnlinePass2(ScanAccountDirBlocQueryBase ev, Future<List<File>> _queryOnlinePass2(ScanAccountDirBlocQueryBase ev,
Map<int, File> cacheMap, List<File> pass1Files) async { Map<int, File> cacheMap, List<File> pass1Files) async {
const touchTokenManager = TouchTokenManager(); final touchTokenManager = TouchTokenManager(_c);
// combine the file maps because [pass1Files] doesn't contain non-supported // combine the file maps because [pass1Files] doesn't contain non-supported
// files // files
final pass2CacheMap = CombinedMapView( final pass2CacheMap = CombinedMapView(
@ -427,8 +427,7 @@ class ScanAccountDirBloc
shouldCheckCache: true, shouldCheckCache: true,
forwardCacheManager: FileForwardCacheManager(_c, pass2CacheMap), forwardCacheManager: FileForwardCacheManager(_c, pass2CacheMap),
)); ));
final remoteTouchEtag = final remoteTouchEtag = await touchTokenManager.getRemoteRootEtag(account);
await touchTokenManager.getRemoteRootEtag(fileRepo, account);
if (remoteTouchEtag == null) { if (remoteTouchEtag == null) {
_log.info("[_queryOnlinePass2] remoteTouchEtag == null"); _log.info("[_queryOnlinePass2] remoteTouchEtag == null");
await touchTokenManager.setLocalRootEtag(account, null); await touchTokenManager.setLocalRootEtag(account, null);

View file

@ -251,3 +251,8 @@ class DiContainer {
sql.SqliteDb? _sqliteDb; sql.SqliteDb? _sqliteDb;
Pref? _pref; Pref? _pref;
} }
extension DiContainerExtension on DiContainer {
DiContainer withRemoteFileRepo() =>
copyWith(fileRepo: OrNull(fileRepoRemote));
}

View file

@ -469,7 +469,7 @@ class FileCachedDataSource implements FileDataSource {
await FileSqliteCacheUpdater(_c)(account, dir, remote: remote); await FileSqliteCacheUpdater(_c)(account, dir, remote: remote);
if (shouldCheckCache) { if (shouldCheckCache) {
// update our local touch token to match the remote one // update our local touch token to match the remote one
const tokenManager = TouchTokenManager(); final tokenManager = TouchTokenManager(_c);
try { try {
await tokenManager.setLocalToken( await tokenManager.setLocalToken(
account, dir, cacheLoader.remoteTouchToken); account, dir, cacheLoader.remoteTouchToken);
@ -556,7 +556,7 @@ class FileCachedDataSource implements FileDataSource {
// generate a new random token // generate a new random token
final token = const Uuid().v4().replaceAll("-", ""); final token = const Uuid().v4().replaceAll("-", "");
final dir = File(path: path_lib.dirname(f.path)); final dir = File(path: path_lib.dirname(f.path));
await const TouchTokenManager().setLocalToken(account, dir, token); await TouchTokenManager(_c).setLocalToken(account, dir, token);
// don't update remote token that frequently // don't update remote token that frequently
(_touchTokenThrottlers["${account.url}/${dir.path}"] ??= Throttler( (_touchTokenThrottlers["${account.url}/${dir.path}"] ??= Throttler(
onTriggered: _updateRemoteTouchToken, onTriggered: _updateRemoteTouchToken,
@ -605,10 +605,8 @@ class FileCachedDataSource implements FileDataSource {
Future<void> _updateRemoteTouchToken( Future<void> _updateRemoteTouchToken(
List<_TouchTokenThrottlerData> data) async { List<_TouchTokenThrottlerData> data) async {
try { try {
final fileRepo = FileRepo(this);
final d = data.last; final d = data.last;
await const TouchTokenManager() await TouchTokenManager(_c).setRemoteToken(d.account, d.dir, d.token);
.setRemoteToken(fileRepo, d.account, d.dir, d.token);
} catch (e, stackTrace) { } catch (e, stackTrace) {
_log.shout("[_updateRemoteTouchToken] Failed while setRemoteToken", e, _log.shout("[_updateRemoteTouchToken] Failed while setRemoteToken", e,
stackTrace); stackTrace);

View file

@ -72,10 +72,10 @@ class FileCacheLoader {
Account account, File f, List<File> cache) async { Account account, File f, List<File> cache) async {
final touchPath = final touchPath =
"${remote_storage_util.getRemoteTouchDir(account)}/${f.strippedPath}"; "${remote_storage_util.getRemoteTouchDir(account)}/${f.strippedPath}";
const tokenManager = TouchTokenManager(); final tokenManager = TouchTokenManager(_c);
String? remoteToken; String? remoteToken;
try { try {
remoteToken = await tokenManager.getRemoteToken(_c.fileRepo, account, f); remoteToken = await tokenManager.getRemoteToken(account, f);
} catch (e, stacktrace) { } catch (e, stacktrace) {
_log.shout( _log.shout(
"[_checkTouchToken] Failed getting remote token at '$touchPath'", "[_checkTouchToken] Failed getting remote token at '$touchPath'",

View file

@ -1,6 +1,5 @@
import 'dart:convert'; import 'dart:convert';
import 'package:kiwi/kiwi.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
import 'package:nc_photos/account.dart'; import 'package:nc_photos/account.dart';
import 'package:nc_photos/di_container.dart'; import 'package:nc_photos/di_container.dart';
@ -11,6 +10,7 @@ import 'package:nc_photos/mobile/platform.dart'
import 'package:nc_photos/pref.dart'; import 'package:nc_photos/pref.dart';
import 'package:nc_photos/remote_storage_util.dart' as remote_storage_util; import 'package:nc_photos/remote_storage_util.dart' as remote_storage_util;
import 'package:nc_photos/use_case/get_file_binary.dart'; import 'package:nc_photos/use_case/get_file_binary.dart';
import 'package:nc_photos/use_case/ls_single_file.dart';
import 'package:nc_photos/use_case/put_file_binary.dart'; import 'package:nc_photos/use_case/put_file_binary.dart';
import 'package:nc_photos/use_case/remove.dart'; import 'package:nc_photos/use_case/remove.dart';
@ -23,12 +23,17 @@ import 'package:nc_photos/use_case/remove.dart';
/// token requires downloading a file from the server so you may want to avoid /// token requires downloading a file from the server so you may want to avoid
/// doing it on every query /// doing it on every query
class TouchTokenManager { class TouchTokenManager {
const TouchTokenManager(); TouchTokenManager(this._c) : assert(require(_c));
Future<String?> getRemoteRootEtag(FileRepo fileRepo, Account account) async { static bool require(DiContainer c) =>
DiContainer.has(c, DiType.fileRepo) &&
DiContainer.has(c, DiType.fileRepoRemote);
Future<String?> getRemoteRootEtag(Account account) async {
try { try {
final touchDir = await fileRepo.listSingle( // we use the remote repo here to prevent it caching the result
account, File(path: remote_storage_util.getRemoteTouchDir(account))); final touchDir = await LsSingleFile(_c.withRemoteFileRepo())(
account, remote_storage_util.getRemoteTouchDir(account));
return touchDir.etag!; return touchDir.etag!;
} catch (_) { } catch (_) {
// dir not found on server // dir not found on server
@ -48,16 +53,14 @@ class TouchTokenManager {
return AccountPref.of(account).getTouchRootEtag(); return AccountPref.of(account).getTouchRootEtag();
} }
Future<void> setRemoteToken( Future<void> setRemoteToken(Account account, File file, String? token) async {
FileRepo fileRepo, Account account, File file, String? token) async {
_log.info( _log.info(
"[setRemoteToken] Set remote token for file '${file.path}': $token"); "[setRemoteToken] Set remote token for file '${file.path}': $token");
final path = _getRemotePath(account, file); final path = _getRemotePath(account, file);
if (token == null) { if (token == null) {
return Remove(KiwiContainer().resolve<DiContainer>())(account, [file], return Remove(_c)(account, [file], shouldCleanUp: false);
shouldCleanUp: false);
} else { } else {
return PutFileBinary(fileRepo)( return PutFileBinary(_c.fileRepo)(
account, path, const Utf8Encoder().convert(token), account, path, const Utf8Encoder().convert(token),
shouldCreateMissingDir: true); shouldCreateMissingDir: true);
} }
@ -65,11 +68,11 @@ class TouchTokenManager {
/// Return the touch token for [file] from remote source, or null if no such /// Return the touch token for [file] from remote source, or null if no such
/// file /// file
Future<String?> getRemoteToken( Future<String?> getRemoteToken(Account account, File file) async {
FileRepo fileRepo, Account account, File file) async {
final path = _getRemotePath(account, file); final path = _getRemotePath(account, file);
try { try {
final content = await GetFileBinary(fileRepo)(account, File(path: path)); final content =
await GetFileBinary(_c.fileRepo)(account, File(path: path));
return const Utf8Decoder().convert(content); return const Utf8Decoder().convert(content);
} on ApiException catch (e) { } on ApiException catch (e) {
if (e.response.statusCode == 404) { if (e.response.statusCode == 404) {
@ -114,5 +117,7 @@ class TouchTokenManager {
} }
} }
final DiContainer _c;
static final _log = Logger("touch_token_manager.TouchTokenManager"); static final _log = Logger("touch_token_manager.TouchTokenManager");
} }

View file

@ -53,12 +53,13 @@ class _RootPickerState extends State<RootPicker> {
} }
void _initAccount() async { void _initAccount() async {
final c = KiwiContainer().resolve<DiContainer>();
final files = <File>[]; final files = <File>[];
for (final r in widget.account.roots) { for (final r in widget.account.roots) {
try { try {
if (r.isNotEmpty) { if (r.isNotEmpty) {
_ensureInitDialog(); _ensureInitDialog();
files.add(await LsSingleFile(KiwiContainer().resolve<DiContainer>())( files.add(await LsSingleFile(c.withRemoteFileRepo())(
widget.account, file_util.unstripPath(widget.account, r))); widget.account, file_util.unstripPath(widget.account, r)));
} }
} catch (e, stackTrace) { } catch (e, stackTrace) {