diff --git a/lib/features/offline_mode/worker/hive_task.dart b/lib/features/offline_mode/worker/hive_task.dart new file mode 100644 index 000000000..d46a0100a --- /dev/null +++ b/lib/features/offline_mode/worker/hive_task.dart @@ -0,0 +1,44 @@ +import 'dart:async'; + +import 'package:equatable/equatable.dart'; +import 'package:tmail_ui_user/features/offline_mode/worker/hive_task_state.dart'; + +class HiveTask with EquatableMixin { + final String? id; + final A? action; + final Future Function()? conditionInvoked; + final Future Function() runnable; + + HiveTask({ + required this.runnable, + this.id, + this.action, + this.conditionInvoked, + }); + + Future execute() async { + final resultCompleter = Completer(); + + try { + if (conditionInvoked != null) { + final invoked = await conditionInvoked!.call(); + if (invoked) { + final result = await runnable.call(); + resultCompleter.complete(TaskSuccess(result: result)); + } else { + resultCompleter.completeError(TaskFailure()); + } + } else { + final result = await runnable.call(); + resultCompleter.complete(TaskSuccess(result: result)); + } + } catch (e) { + resultCompleter.completeError(TaskFailure(exception: e)); + } + + return resultCompleter.future; + } + + @override + List get props => [runnable, id, action, conditionInvoked]; +} \ No newline at end of file diff --git a/lib/features/offline_mode/worker/hive_task_state.dart b/lib/features/offline_mode/worker/hive_task_state.dart new file mode 100644 index 000000000..e957ad711 --- /dev/null +++ b/lib/features/offline_mode/worker/hive_task_state.dart @@ -0,0 +1,22 @@ + + +import 'package:core/presentation/state/failure.dart'; +import 'package:core/presentation/state/success.dart'; + +class TaskSuccess extends Success { + final dynamic result; + + TaskSuccess({this.result}); + + @override + List get props => [result]; +} + +class TaskFailure extends Failure { + final dynamic exception; + + TaskFailure({this.exception}); + + @override + List get props => [exception]; +} \ No newline at end of file diff --git a/lib/features/offline_mode/worker/hive_worker_queue.dart b/lib/features/offline_mode/worker/hive_worker_queue.dart new file mode 100644 index 000000000..4a3b49bc8 --- /dev/null +++ b/lib/features/offline_mode/worker/hive_worker_queue.dart @@ -0,0 +1,65 @@ + +import 'dart:async'; +import 'dart:collection'; + +import 'package:core/utils/app_logger.dart'; +import 'package:tmail_ui_user/features/offline_mode/worker/hive_task.dart'; + +abstract class WorkerQueue { + + final Queue> queue = Queue>(); + Completer? completer; + + String get workerName; + + Future addTask(HiveTask task) { + queue.add(task); + log('WorkerQueue<$workerName>::addTask(): QUEUE_LENGTH: ${queue.length}'); + return _processTask(); + } + + Future _processTask() async { + if (completer != null) { + return completer!.future; + } + completer = Completer(); + if (queue.isNotEmpty) { + final firstTask = queue.removeFirst(); + log('WorkerQueue<$workerName>::_processTask(): ${firstTask.id}'); + firstTask.execute() + .then(_handleTaskExecuteCompleted) + .catchError(_handleTaskExecuteError); + } else { + completer?.complete(); + } + return completer!.future; + } + + void _handleTaskExecuteCompleted(dynamic value) { + log('WorkerQueue<$workerName>::_handleTaskExecuteCompleted(): $value'); + completer?.complete(); + _releaseCompleter(); + if (queue.isNotEmpty) { + _processTask(); + } + } + + void _handleTaskExecuteError(error) { + log('WorkerQueue<$workerName>::_handleTaskExecuteError(): $error'); + completer?.complete(); + _releaseCompleter(); + if (queue.isNotEmpty) { + _processTask(); + } + } + + void _releaseCompleter() { + completer = null; + } + + Future release() async { + log('WorkerQueue<$workerName>::release():'); + queue.clear(); + _releaseCompleter(); + } +} \ No newline at end of file