mirror of
https://gitlab.com/nkming2/nc-photos.git
synced 2025-02-24 18:38:48 +01:00
Skip touch token check if etag matches
This commit is contained in:
parent
7a515fdad1
commit
afaf432ab0
3 changed files with 105 additions and 25 deletions
|
@ -14,6 +14,7 @@ import 'package:nc_photos/event/event.dart';
|
|||
import 'package:nc_photos/exception_event.dart';
|
||||
import 'package:nc_photos/pref.dart';
|
||||
import 'package:nc_photos/throttler.dart';
|
||||
import 'package:nc_photos/touch_token_manager.dart';
|
||||
import 'package:nc_photos/use_case/ls.dart';
|
||||
import 'package:nc_photos/use_case/scan_dir.dart';
|
||||
import 'package:nc_photos/use_case/scan_dir_offline.dart';
|
||||
|
@ -307,7 +308,7 @@ class ScanAccountDirBloc
|
|||
Stream<ScanAccountDirBlocState> _queryOnline(
|
||||
ScanAccountDirBlocQueryBase ev, List<File>? cache) async* {
|
||||
// 1st pass: scan for new files
|
||||
final files = <File>[];
|
||||
var files = <File>[];
|
||||
{
|
||||
final stopwatch = Stopwatch()..start();
|
||||
final fileRepo = FileRepo(FileCachedDataSource(AppDb(),
|
||||
|
@ -336,32 +337,56 @@ class ScanAccountDirBloc
|
|||
yield ScanAccountDirBlocLoading(files);
|
||||
}
|
||||
|
||||
if (_shouldCheckCache) {
|
||||
// 2nd pass: check outdated cache
|
||||
_shouldCheckCache = false;
|
||||
final stopwatch = Stopwatch()..start();
|
||||
final fileRepo = FileRepo(FileCachedDataSource(AppDb(),
|
||||
shouldCheckCache: true,
|
||||
forwardCacheManager: FileForwardCacheManager(AppDb())));
|
||||
final fileRepoNoCache =
|
||||
FileRepo(FileCachedDataSource(AppDb(), shouldCheckCache: true));
|
||||
final newFiles = <File>[];
|
||||
await for (final event in _queryWithFileRepo(fileRepo, ev,
|
||||
fileRepoForShareDir: fileRepoNoCache)) {
|
||||
if (event is ExceptionEvent) {
|
||||
_log.shout("[_queryOnline] Exception while request (2nd pass)",
|
||||
event.error, event.stackTrace);
|
||||
yield ScanAccountDirBlocSuccess(files);
|
||||
return;
|
||||
}
|
||||
newFiles.addAll(event);
|
||||
try {
|
||||
if (_shouldCheckCache) {
|
||||
// 2nd pass: check outdated cache
|
||||
_shouldCheckCache = false;
|
||||
files = await _queryOnlinePass2(ev, files);
|
||||
}
|
||||
_log.info(
|
||||
"[_queryOnline] Elapsed time (pass2): ${stopwatch.elapsedMilliseconds}ms");
|
||||
yield ScanAccountDirBlocSuccess(newFiles);
|
||||
} else {
|
||||
yield ScanAccountDirBlocSuccess(files);
|
||||
} catch (e, stackTrace) {
|
||||
_log.shout(
|
||||
"[_queryOnline] Failed while _queryOnlinePass2", e, stackTrace);
|
||||
}
|
||||
yield ScanAccountDirBlocSuccess(files);
|
||||
}
|
||||
|
||||
Future<List<File>> _queryOnlinePass2(
|
||||
ScanAccountDirBlocQueryBase ev, List<File> pass1Files) async {
|
||||
const touchTokenManager = TouchTokenManager();
|
||||
final fileRepo = FileRepo(FileCachedDataSource(AppDb(),
|
||||
shouldCheckCache: true,
|
||||
forwardCacheManager: FileForwardCacheManager(AppDb())));
|
||||
final remoteTouchEtag =
|
||||
await touchTokenManager.getRemoteRootEtag(fileRepo, account);
|
||||
if (remoteTouchEtag == null) {
|
||||
_log.info("[_queryOnlinePass2] remoteTouchEtag == null");
|
||||
await touchTokenManager.setLocalRootEtag(account, null);
|
||||
return pass1Files;
|
||||
}
|
||||
final localTouchEtag = await touchTokenManager.getLocalRootEtag(account);
|
||||
if (remoteTouchEtag == localTouchEtag) {
|
||||
_log.info("[_queryOnlinePass2] remoteTouchEtag matched");
|
||||
return pass1Files;
|
||||
}
|
||||
|
||||
final stopwatch = Stopwatch()..start();
|
||||
final fileRepoNoCache =
|
||||
FileRepo(FileCachedDataSource(AppDb(), shouldCheckCache: true));
|
||||
final newFiles = <File>[];
|
||||
await for (final event in _queryWithFileRepo(fileRepo, ev,
|
||||
fileRepoForShareDir: fileRepoNoCache)) {
|
||||
if (event is ExceptionEvent) {
|
||||
_log.shout("[_queryOnlinePass2] Exception while request (2nd pass)",
|
||||
event.error, event.stackTrace);
|
||||
return pass1Files;
|
||||
}
|
||||
newFiles.addAll(event);
|
||||
}
|
||||
_log.info(
|
||||
"[_queryOnlinePass2] Elapsed time (pass2): ${stopwatch.elapsedMilliseconds}ms");
|
||||
_log.info("[_queryOnlinePass2] Save new touch root etag: $remoteTouchEtag");
|
||||
await touchTokenManager.setLocalRootEtag(account, remoteTouchEtag);
|
||||
return newFiles;
|
||||
}
|
||||
|
||||
/// Emit all files under this account
|
||||
|
|
|
@ -236,6 +236,14 @@ class AccountPref {
|
|||
value,
|
||||
(key, value) => provider.setBool(key, value));
|
||||
|
||||
String? getTouchRootEtag() => provider.getString(PrefKey.touchRootEtag);
|
||||
String getTouchRootEtagOr([String def = ""]) => getTouchRootEtag() ?? def;
|
||||
Future<bool> setTouchRootEtag(String value) => _set<String>(
|
||||
PrefKey.touchRootEtag,
|
||||
value,
|
||||
(key, value) => provider.setString(key, value));
|
||||
Future<bool> removeTouchRootEtag() => _remove(PrefKey.touchRootEtag);
|
||||
|
||||
Future<bool> _set<T>(PrefKey key, T value,
|
||||
Future<bool> Function(PrefKey key, T value) setFn) async {
|
||||
if (await setFn(key, value)) {
|
||||
|
@ -248,6 +256,8 @@ class AccountPref {
|
|||
}
|
||||
}
|
||||
|
||||
Future<bool> _remove(PrefKey key) => provider.remove(key);
|
||||
|
||||
final PrefProvider provider;
|
||||
|
||||
static final _insts = <String, AccountPref>{};
|
||||
|
@ -267,6 +277,7 @@ abstract class PrefProvider {
|
|||
List<String>? getStringList(PrefKey key);
|
||||
Future<bool> setStringList(PrefKey key, List<String> value);
|
||||
|
||||
Future<bool> remove(PrefKey key);
|
||||
Future<bool> clear();
|
||||
}
|
||||
|
||||
|
@ -311,6 +322,9 @@ class PrefSharedPreferencesProvider extends PrefProvider {
|
|||
setStringList(PrefKey key, List<String> value) =>
|
||||
_pref.setStringList(key.toStringKey(), value);
|
||||
|
||||
@override
|
||||
remove(PrefKey key) => _pref.remove(key.toStringKey());
|
||||
|
||||
@override
|
||||
clear() => _pref.clear();
|
||||
|
||||
|
@ -348,6 +362,14 @@ class PrefUniversalStorageProvider extends PrefProvider {
|
|||
@override
|
||||
setStringList(PrefKey key, List<String> value) => _set(key, value);
|
||||
|
||||
@override
|
||||
remove(PrefKey key) async {
|
||||
final newData = Map.of(_data)..remove(key.toStringKey());
|
||||
await platform.UniversalStorage().putString(name, jsonEncode(newData));
|
||||
_data.remove(key.toStringKey());
|
||||
return true;
|
||||
}
|
||||
|
||||
@override
|
||||
clear() async {
|
||||
await platform.UniversalStorage().remove(name);
|
||||
|
@ -395,6 +417,12 @@ class PrefMemoryProvider extends PrefProvider {
|
|||
@override
|
||||
setStringList(PrefKey key, List<String> value) => _set(key, value);
|
||||
|
||||
@override
|
||||
remove(PrefKey key) async {
|
||||
_data.remove(key);
|
||||
return true;
|
||||
}
|
||||
|
||||
@override
|
||||
clear() async {
|
||||
_data.clear();
|
||||
|
@ -439,6 +467,7 @@ enum PrefKey {
|
|||
shareFolder,
|
||||
hasNewSharedAlbum,
|
||||
isEnableMemoryAlbum,
|
||||
touchRootEtag,
|
||||
}
|
||||
|
||||
extension on PrefKey {
|
||||
|
@ -496,6 +525,8 @@ extension on PrefKey {
|
|||
return "hasNewSharedAlbum";
|
||||
case PrefKey.isEnableMemoryAlbum:
|
||||
return "isEnableMemoryAlbum";
|
||||
case PrefKey.touchRootEtag:
|
||||
return "touchRootEtag";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import 'package:nc_photos/entity/file.dart';
|
|||
import 'package:nc_photos/exception.dart';
|
||||
import 'package:nc_photos/mobile/platform.dart'
|
||||
if (dart.library.html) 'package:nc_photos/web/platform.dart' as platform;
|
||||
import 'package:nc_photos/pref.dart';
|
||||
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/put_file_binary.dart';
|
||||
|
@ -24,6 +25,29 @@ import 'package:nc_photos/use_case/remove.dart';
|
|||
class TouchTokenManager {
|
||||
const TouchTokenManager();
|
||||
|
||||
Future<String?> getRemoteRootEtag(FileRepo fileRepo, Account account) async {
|
||||
try {
|
||||
final touchDir = await fileRepo.listSingle(
|
||||
account, File(path: remote_storage_util.getRemoteTouchDir(account)));
|
||||
return touchDir.etag!;
|
||||
} catch (_) {
|
||||
// dir not found on server
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> setLocalRootEtag(Account account, String? etag) async {
|
||||
if (etag == null) {
|
||||
await AccountPref.of(account).removeTouchRootEtag();
|
||||
} else {
|
||||
await AccountPref.of(account).setTouchRootEtag(etag);
|
||||
}
|
||||
}
|
||||
|
||||
Future<String?> getLocalRootEtag(Account account) async {
|
||||
return AccountPref.of(account).getTouchRootEtag();
|
||||
}
|
||||
|
||||
Future<void> setRemoteToken(
|
||||
FileRepo fileRepo, Account account, File file, String? token) async {
|
||||
_log.info(
|
||||
|
|
Loading…
Reference in a new issue