mirror of
https://gitlab.com/nkming2/nc-photos.git
synced 2025-02-02 06:46:22 +01:00
Throttle calls to update remote touch token
This commit is contained in:
parent
7563fa2ad6
commit
799594443b
3 changed files with 65 additions and 11 deletions
|
@ -17,6 +17,7 @@ import 'package:nc_photos/exception.dart';
|
|||
import 'package:nc_photos/iterable_extension.dart';
|
||||
import 'package:nc_photos/object_extension.dart';
|
||||
import 'package:nc_photos/or_null.dart';
|
||||
import 'package:nc_photos/throttler.dart';
|
||||
import 'package:nc_photos/touch_token_manager.dart';
|
||||
import 'package:nc_photos/use_case/compat/v32.dart';
|
||||
import 'package:path/path.dart' as path_lib;
|
||||
|
@ -539,13 +540,18 @@ class FileCachedDataSource implements FileDataSource {
|
|||
|
||||
// generate a new random token
|
||||
final token = const Uuid().v4().replaceAll("-", "");
|
||||
const tokenManager = TouchTokenManager();
|
||||
final dir = File(path: path_lib.dirname(f.path));
|
||||
await tokenManager.setLocalToken(account, dir, token);
|
||||
final fileRepo = FileRepo(this);
|
||||
await tokenManager.setRemoteToken(fileRepo, account, dir, token);
|
||||
_log.info(
|
||||
"[updateMetadata] New touch token '$token' for dir '${dir.path}'");
|
||||
await const TouchTokenManager().setLocalToken(account, dir, token);
|
||||
// don't update remote token that frequently
|
||||
(_touchTokenThrottlers["${account.url}/${dir.path}"] ??= Throttler(
|
||||
onTriggered: _updateRemoteTouchToken,
|
||||
logTag: "FileCachedDataSource._touchTokenThrottlers",
|
||||
))
|
||||
.trigger(
|
||||
maxResponceTime: const Duration(seconds: 20),
|
||||
maxPendingCount: 20,
|
||||
data: _TouchTokenThrottlerData(account, dir, token),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -575,6 +581,25 @@ class FileCachedDataSource implements FileDataSource {
|
|||
await _remoteSrc.createDir(account, path);
|
||||
}
|
||||
|
||||
Future<void> updateRemoteTouchTokenNow() async {
|
||||
for (final t in _touchTokenThrottlers.values) {
|
||||
await t.triggerNow();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _updateRemoteTouchToken(
|
||||
List<_TouchTokenThrottlerData> data) async {
|
||||
try {
|
||||
final fileRepo = FileRepo(this);
|
||||
final d = data.last;
|
||||
await const TouchTokenManager()
|
||||
.setRemoteToken(fileRepo, d.account, d.dir, d.token);
|
||||
} catch (e, stackTrace) {
|
||||
_log.shout("[_updateRemoteTouchToken] Failed while setRemoteToken", e,
|
||||
stackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
final DiContainer _c;
|
||||
final bool shouldCheckCache;
|
||||
final FileForwardCacheManager? forwardCacheManager;
|
||||
|
@ -582,9 +607,19 @@ class FileCachedDataSource implements FileDataSource {
|
|||
final _remoteSrc = const FileWebdavDataSource();
|
||||
final FileSqliteDbDataSource _sqliteDbSrc;
|
||||
|
||||
final _touchTokenThrottlers = <String, Throttler<_TouchTokenThrottlerData>>{};
|
||||
|
||||
static final _log = Logger("entity.file.data_source.FileCachedDataSource");
|
||||
}
|
||||
|
||||
class _TouchTokenThrottlerData {
|
||||
const _TouchTokenThrottlerData(this.account, this.dir, this.token);
|
||||
|
||||
final Account account;
|
||||
final File dir;
|
||||
final String token;
|
||||
}
|
||||
|
||||
/// Forward cache for listing AppDb dirs
|
||||
///
|
||||
/// It's very expensive to list a dir and its sub-dirs one by one in multiple
|
||||
|
|
|
@ -10,6 +10,7 @@ import 'package:nc_photos/app_init.dart' as app_init;
|
|||
import 'package:nc_photos/app_localizations.dart';
|
||||
import 'package:nc_photos/di_container.dart';
|
||||
import 'package:nc_photos/entity/file.dart';
|
||||
import 'package:nc_photos/entity/file/data_source.dart';
|
||||
import 'package:nc_photos/entity/file_util.dart' as file_util;
|
||||
import 'package:nc_photos/event/event.dart';
|
||||
import 'package:nc_photos/event/native_event.dart';
|
||||
|
@ -230,6 +231,12 @@ class _MetadataTask {
|
|||
NativeEvent.fire(FileExifUpdatedEvent(_processedIds).toEvent());
|
||||
_processedIds = [];
|
||||
}
|
||||
|
||||
final c = KiwiContainer().resolve<DiContainer>();
|
||||
if (c.fileRepo.dataSrc is FileCachedDataSource) {
|
||||
await (c.fileRepo.dataSrc as FileCachedDataSource)
|
||||
.updateRemoteTouchTokenNow();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _updateMetadata() async {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import 'dart:async';
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:nc_photos/int_util.dart';
|
||||
|
||||
|
@ -56,17 +55,30 @@ class Throttler<T> {
|
|||
_currentResponseTime = null;
|
||||
_count = 0;
|
||||
_maxCount = null;
|
||||
// _data may be used else where, thus we must not call List.clear() here
|
||||
_data = <T>[];
|
||||
}
|
||||
|
||||
void _doTrigger() {
|
||||
onTriggered?.call(_data);
|
||||
clear();
|
||||
Future<void> triggerNow() async {
|
||||
if (_hasPendingEvent) {
|
||||
_log.info("[triggerNow]$_logTag Triggered");
|
||||
return _doTrigger();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _doTrigger() async {
|
||||
if (_hasPendingEvent) {
|
||||
final data = _data;
|
||||
clear();
|
||||
await onTriggered?.call(data);
|
||||
}
|
||||
}
|
||||
|
||||
bool get _hasPendingEvent => _count > 0;
|
||||
|
||||
String get _logTag => logTag == null ? "" : "[$logTag]";
|
||||
|
||||
final ValueChanged<List<T>>? onTriggered;
|
||||
final FutureOr<void> Function(List<T>)? onTriggered;
|
||||
|
||||
/// Extra tag printed with logs from this class
|
||||
final String? logTag;
|
||||
|
|
Loading…
Reference in a new issue