nc-photos/app/lib/use_case/startup_sync.dart

169 lines
5.4 KiB
Dart
Raw Normal View History

2022-07-28 11:13:39 +02:00
import 'dart:async';
import 'package:flutter_isolate/flutter_isolate.dart';
import 'package:kiwi/kiwi.dart';
import 'package:logging/logging.dart';
import 'package:mutex/mutex.dart';
2022-07-28 11:13:39 +02:00
import 'package:nc_photos/account.dart';
import 'package:nc_photos/app_init.dart' as app_init;
import 'package:nc_photos/controller/files_controller.dart';
import 'package:nc_photos/controller/persons_controller.dart';
2022-07-28 11:13:39 +02:00
import 'package:nc_photos/di_container.dart';
import 'package:nc_photos/entity/person.dart';
2023-07-03 19:23:42 +02:00
import 'package:nc_photos/use_case/person/sync_person.dart';
2022-07-28 11:13:39 +02:00
import 'package:nc_photos/use_case/sync_favorite.dart';
2022-08-05 11:28:28 +02:00
import 'package:nc_photos/use_case/sync_tag.dart';
2022-12-16 16:01:04 +01:00
import 'package:np_codegen/np_codegen.dart';
import 'package:np_common/object_util.dart';
import 'package:np_common/type.dart';
import 'package:np_db/np_db.dart';
2023-08-27 12:58:05 +02:00
import 'package:np_platform_util/np_platform_util.dart';
import 'package:to_string/to_string.dart';
2022-12-16 16:01:04 +01:00
part 'startup_sync.g.dart';
2022-07-28 11:13:39 +02:00
/// Sync various properties with server during startup
2022-12-16 16:01:04 +01:00
@npLog
2022-07-28 11:13:39 +02:00
class StartupSync {
2023-07-03 19:23:42 +02:00
StartupSync(this._c) : assert(require(_c));
2022-07-28 11:13:39 +02:00
static bool require(DiContainer c) => SyncFavorite.require(c);
2022-07-28 11:13:39 +02:00
/// Sync in a background isolate
2023-07-03 19:23:42 +02:00
static Future<SyncResult> runInIsolate(
Account account,
FilesController filesController,
PersonsController personsController,
PersonProvider personProvider,
) async {
return _mutex.protect(() async {
2023-08-27 12:58:05 +02:00
if (getRawPlatform() == NpPlatform.web) {
// not supported on web
final c = KiwiContainer().resolve<DiContainer>();
return await StartupSync(c)(account, personProvider);
} else {
// we can't use regular isolate here because self-signed cert support
// requires native plugins
final resultJson = await flutterCompute(
_isolateMain, _IsolateMessage(account, personProvider).toJson());
final result = SyncResult.fromJson(resultJson);
// events fired in background isolate won't be noticed by the main isolate,
// so we fire them again here
_broadcastResult(account, filesController, personsController, result);
return result;
}
});
2022-07-28 11:13:39 +02:00
}
Future<SyncResult> call(
Account account, PersonProvider personProvider) async {
2022-07-28 11:13:39 +02:00
_log.info("[_run] Begin sync");
2022-08-05 10:42:40 +02:00
final stopwatch = Stopwatch()..start();
DbSyncIdResult? syncFavoriteResult;
DbSyncIdResult? syncTagResult;
var isSyncPersonUpdated = false;
2022-07-28 11:13:39 +02:00
try {
syncFavoriteResult = await SyncFavorite(_c)(account);
2022-07-28 11:13:39 +02:00
} catch (e, stackTrace) {
_log.shout("[_run] Failed while SyncFavorite", e, stackTrace);
}
2022-08-05 11:28:28 +02:00
try {
syncTagResult = await SyncTag(_c)(account);
2022-08-05 11:28:28 +02:00
} catch (e, stackTrace) {
_log.shout("[_run] Failed while SyncTag", e, stackTrace);
}
2022-08-05 11:39:49 +02:00
try {
isSyncPersonUpdated = await SyncPerson(_c)(account, personProvider);
2022-08-05 11:39:49 +02:00
} catch (e, stackTrace) {
_log.shout("[_run] Failed while SyncPerson", e, stackTrace);
}
2022-08-05 10:42:40 +02:00
_log.info("[_run] Elapsed time: ${stopwatch.elapsedMilliseconds}ms");
2023-07-03 19:23:42 +02:00
return SyncResult(
syncFavoriteResult: syncFavoriteResult,
syncTagResult: syncTagResult,
2023-07-03 19:23:42 +02:00
isSyncPersonUpdated: isSyncPersonUpdated,
);
2022-07-28 11:13:39 +02:00
}
static void _broadcastResult(
Account account,
FilesController filesController,
PersonsController personsController,
SyncResult result,
) {
_$StartupSyncNpLog.log.info('[_broadcastResult] $result');
if (result.syncFavoriteResult != null) {
filesController.applySyncResult(favorites: result.syncFavoriteResult!);
2022-07-28 11:13:39 +02:00
}
if (result.isSyncPersonUpdated) {
personsController.reload();
}
2022-07-28 11:13:39 +02:00
}
final DiContainer _c;
static final _mutex = Mutex();
2022-07-28 11:13:39 +02:00
}
@toString
2022-07-28 11:13:39 +02:00
class SyncResult {
2023-07-03 19:23:42 +02:00
const SyncResult({
required this.syncFavoriteResult,
required this.syncTagResult,
2023-07-03 19:23:42 +02:00
required this.isSyncPersonUpdated,
});
2022-07-28 11:13:39 +02:00
factory SyncResult.fromJson(JsonObj json) => SyncResult(
syncFavoriteResult: (json["syncFavoriteResult"] as Map?)
?.cast<String, dynamic>()
.let(DbSyncIdResult.fromJson),
syncTagResult: (json["syncTagResult"] as Map?)
?.cast<String, dynamic>()
.let(DbSyncIdResult.fromJson),
2023-07-03 19:23:42 +02:00
isSyncPersonUpdated: json["isSyncPersonUpdated"],
2022-07-28 11:13:39 +02:00
);
JsonObj toJson() => {
"syncFavoriteResult": syncFavoriteResult?.toJson(),
"syncTagResult": syncTagResult?.toJson(),
2023-07-03 19:23:42 +02:00
"isSyncPersonUpdated": isSyncPersonUpdated,
2022-07-28 11:13:39 +02:00
};
@override
String toString() => _$toString();
final DbSyncIdResult? syncFavoriteResult;
final DbSyncIdResult? syncTagResult;
2023-07-03 19:23:42 +02:00
final bool isSyncPersonUpdated;
2022-07-28 11:13:39 +02:00
}
class _IsolateMessage {
const _IsolateMessage(this.account, this.personProvider);
2022-07-28 11:13:39 +02:00
factory _IsolateMessage.fromJson(JsonObj json) => _IsolateMessage(
Account.fromJson(
json["account"].cast<String, dynamic>(),
upgraderV1: const AccountUpgraderV1(),
)!,
PersonProvider.fromValue(json["personProvider"]),
2022-07-28 11:13:39 +02:00
);
JsonObj toJson() => <String, dynamic>{
2022-07-28 11:13:39 +02:00
"account": account.toJson(),
"personProvider": personProvider.index,
2022-07-28 11:13:39 +02:00
};
final Account account;
final PersonProvider personProvider;
2022-07-28 11:13:39 +02:00
}
2022-12-10 15:43:41 +01:00
@pragma("vm:entry-point")
2022-07-28 11:13:39 +02:00
Future<JsonObj> _isolateMain(JsonObj messageJson) async {
final message = _IsolateMessage.fromJson(messageJson);
await app_init.init(app_init.InitIsolateType.flutterIsolate);
final c = KiwiContainer().resolve<DiContainer>();
final result = await StartupSync(c)(message.account, message.personProvider);
2022-07-28 11:13:39 +02:00
return result.toJson();
}