Feat: Stellt den BackgroundManager auf IsolateManager um
This commit is contained in:
@@ -1,19 +1,18 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:isolate';
|
|
||||||
|
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:isolate_manager/isolate_manager.dart';
|
||||||
import 'package:workmanager/workmanager.dart';
|
import 'package:workmanager/workmanager.dart';
|
||||||
|
|
||||||
import '../Tasks/generate_transactions_task.dart';
|
import '../Tasks/workers.dart';
|
||||||
import '../Tasks/task.dart';
|
import '../Tasks/workmanager_workers.dart';
|
||||||
import 'port_controller.dart';
|
|
||||||
|
|
||||||
/// Erstellt Hintergrundtasks und führt diese aus
|
/// Erstellt Hintergrundtasks und führt diese aus
|
||||||
class BackgroundTaskController {
|
class BackgroundTaskController {
|
||||||
/// Erstellt eine neue Instanz dieser Klasse
|
/// Erstellt eine neue Instanz dieser Klasse
|
||||||
BackgroundTaskController() {
|
BackgroundTaskController() {
|
||||||
if (Platform.isAndroid) {
|
if (!kIsWeb && Platform.isAndroid) {
|
||||||
unawaited(Workmanager().initialize(callbackDispatcher));
|
unawaited(Workmanager().initialize(callbackDispatcher));
|
||||||
unawaited(
|
unawaited(
|
||||||
Workmanager().registerPeriodicTask(
|
Workmanager().registerPeriodicTask(
|
||||||
@@ -25,47 +24,12 @@ class BackgroundTaskController {
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
unawaited(
|
unawaited(
|
||||||
Isolate.run(() {
|
IsolateManager.runFunction(runTask, {
|
||||||
unawaited(_runTask(
|
'taskName': 'generate_transactions',
|
||||||
GenerateTransactionsTask(),
|
'initialDelayMinutes': 1,
|
||||||
const Duration(minutes: 1),
|
'frequencyMinutes': 30,
|
||||||
const Duration(minutes: 30),
|
|
||||||
));
|
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _runTask(
|
|
||||||
final Task task,
|
|
||||||
final Duration initialDelay,
|
|
||||||
final Duration frequency,
|
|
||||||
) async {
|
|
||||||
await Future.delayed(initialDelay);
|
|
||||||
|
|
||||||
final RootIsolateToken? rootIsolateToken = await PortController()
|
|
||||||
.getRootIsolateToken();
|
|
||||||
|
|
||||||
if (rootIsolateToken != null) {
|
|
||||||
BackgroundIsolateBinaryMessenger.ensureInitialized(rootIsolateToken);
|
|
||||||
await GenerateTransactionsTask().execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
await Future.delayed(frequency);
|
|
||||||
|
|
||||||
unawaited(_runTask(task, initialDelay, frequency));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Die Funktion wird von Hintergrundtasks ausgerufen, um diese auszuführen
|
|
||||||
@pragma('vm:entry-point')
|
|
||||||
void callbackDispatcher() {
|
|
||||||
Workmanager().executeTask((final task, final inputData) {
|
|
||||||
switch (task) {
|
|
||||||
case 'generate_transactions':
|
|
||||||
return GenerateTransactionsTask().execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Future.value(true);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,24 +2,28 @@ import 'dart:async';
|
|||||||
import 'dart:isolate';
|
import 'dart:isolate';
|
||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
|
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:logger/logger.dart';
|
||||||
|
|
||||||
/// Ein PortController mit verschiedenen FUnktionen zur KOmmunikations zwischen
|
/// Ein PortController mit verschiedenen Funktionen zur Kommunikation zwischen
|
||||||
/// main und anderen Isolates
|
/// main und anderen Isolates
|
||||||
class PortController {
|
class PortController {
|
||||||
/// Gibt eine Instanz dieser Klasse zurück
|
/// Gibt eine Instanz dieser Klasse zurück
|
||||||
factory PortController() => _instance;
|
factory PortController() => _instance;
|
||||||
|
|
||||||
PortController._internal() {
|
PortController._internal() {
|
||||||
if (ServicesBinding.rootIsolateToken != null) {
|
if (!kIsWeb && ServicesBinding.rootIsolateToken != null) {
|
||||||
_registerRootIsolateTokenSender();
|
_registerRootIsolateTokenSender();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static final PortController _instance = PortController._internal();
|
static final PortController _instance = PortController._internal();
|
||||||
|
final Logger _logger = Logger();
|
||||||
|
|
||||||
/// Fügt einen Port mit [name] zum NameServer hinzu
|
/// Fügt einen Port mit [name] zum NameServer hinzu
|
||||||
void addPort(final SendPort sendPort, final String name) {
|
void addPort(final SendPort sendPort, final String name) {
|
||||||
|
IsolateNameServer.removePortNameMapping(name);
|
||||||
IsolateNameServer.registerPortWithName(sendPort, name);
|
IsolateNameServer.registerPortWithName(sendPort, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,6 +33,8 @@ class PortController {
|
|||||||
|
|
||||||
/// Gibt das [RootIsolateToken] der main-Isolate zurück
|
/// Gibt das [RootIsolateToken] der main-Isolate zurück
|
||||||
Future<RootIsolateToken?> getRootIsolateToken() async {
|
Future<RootIsolateToken?> getRootIsolateToken() async {
|
||||||
|
_logger.d('Trying to retrieve RootIsolateToken...');
|
||||||
|
|
||||||
final ReceivePort receivePort = ReceivePort();
|
final ReceivePort receivePort = ReceivePort();
|
||||||
|
|
||||||
final SendPort? rootPort = IsolateNameServer.lookupPortByName(
|
final SendPort? rootPort = IsolateNameServer.lookupPortByName(
|
||||||
@@ -36,21 +42,26 @@ class PortController {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (rootPort == null) {
|
if (rootPort == null) {
|
||||||
|
_logger.e("Couldn't get Port from IsolateNameServer!");
|
||||||
receivePort.close();
|
receivePort.close();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_logger.i('Sending communication attempt...');
|
||||||
rootPort.send(receivePort.sendPort);
|
rootPort.send(receivePort.sendPort);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final dynamic message = await receivePort.first;
|
final dynamic message = await receivePort.first;
|
||||||
|
|
||||||
if (message is RootIsolateToken) {
|
if (message is RootIsolateToken) {
|
||||||
|
_logger.i('Got RootIsolateToken, returning...');
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_logger.w("Couldn't get RootIsolateToken!");
|
||||||
return null;
|
return null;
|
||||||
} finally {
|
} finally {
|
||||||
|
_logger.i('Closing receivePort...');
|
||||||
receivePort.close();
|
receivePort.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -58,6 +69,8 @@ class PortController {
|
|||||||
void _registerRootIsolateTokenSender() {
|
void _registerRootIsolateTokenSender() {
|
||||||
final ReceivePort receivePort = ReceivePort()
|
final ReceivePort receivePort = ReceivePort()
|
||||||
..listen((final value) {
|
..listen((final value) {
|
||||||
|
_logger.d('Received Message with $value');
|
||||||
|
|
||||||
if (value is SendPort) {
|
if (value is SendPort) {
|
||||||
value.send(ServicesBinding.rootIsolateToken);
|
value.send(ServicesBinding.rootIsolateToken);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -102,5 +102,6 @@ class AppDatabase extends _$AppDatabase {
|
|||||||
sqlite3Wasm: Uri.parse('sqlite3.wasm'),
|
sqlite3Wasm: Uri.parse('sqlite3.wasm'),
|
||||||
driftWorker: Uri.parse('drift_worker.js'),
|
driftWorker: Uri.parse('drift_worker.js'),
|
||||||
),
|
),
|
||||||
|
native: const DriftNativeOptions(shareAcrossIsolates: true)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -577,8 +577,7 @@ class RecurringTransaction extends DataClass
|
|||||||
String toString() {
|
String toString() {
|
||||||
return (StringBuffer('RecurringTransaction(')
|
return (StringBuffer('RecurringTransaction(')
|
||||||
..write('id: $id, ')
|
..write('id: $id, ')
|
||||||
..write('name: $name, ')
|
..write('name: $name, ')..write('startDate: $startDate, ')..write(
|
||||||
..write('startDate: $startDate, ')..write(
|
|
||||||
'timeFrame: $timeFrame, ')..write('amount: $amount, ')..write(
|
'timeFrame: $timeFrame, ')..write('amount: $amount, ')..write(
|
||||||
'accountId: $accountId, ')..write('updatedAt: $updatedAt')
|
'accountId: $accountId, ')..write('updatedAt: $updatedAt')
|
||||||
..write(')'))
|
..write(')'))
|
||||||
@@ -702,8 +701,7 @@ class RecurringTransactionsCompanion
|
|||||||
String toString() {
|
String toString() {
|
||||||
return (StringBuffer('RecurringTransactionsCompanion(')
|
return (StringBuffer('RecurringTransactionsCompanion(')
|
||||||
..write('id: $id, ')
|
..write('id: $id, ')
|
||||||
..write('name: $name, ')
|
..write('name: $name, ')..write('startDate: $startDate, ')..write(
|
||||||
..write('startDate: $startDate, ')..write(
|
|
||||||
'timeFrame: $timeFrame, ')..write('amount: $amount, ')..write(
|
'timeFrame: $timeFrame, ')..write('amount: $amount, ')..write(
|
||||||
'accountId: $accountId, ')..write('updatedAt: $updatedAt')
|
'accountId: $accountId, ')..write('updatedAt: $updatedAt')
|
||||||
..write(')'))
|
..write(')'))
|
||||||
@@ -1076,11 +1074,14 @@ class Transaction extends DataClass implements Insertable<Transaction> {
|
|||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return (StringBuffer('Transaction(')
|
return (StringBuffer('Transaction(')
|
||||||
..write('id: $id, ')..write('name: $name, ')..write(
|
..write('id: $id, ')
|
||||||
'date: $date, ')..write('amount: $amount, ')..write(
|
..write('name: $name, ')
|
||||||
'checked: $checked, ')..write('accountId: $accountId, ')..write(
|
..write('date: $date, ')
|
||||||
'recurringTransactionId: $recurringTransactionId, ')..write(
|
..write('amount: $amount, ')
|
||||||
'updatedAt: $updatedAt')
|
..write('checked: $checked, ')
|
||||||
|
..write('accountId: $accountId, ')
|
||||||
|
..write('recurringTransactionId: $recurringTransactionId, ')
|
||||||
|
..write('updatedAt: $updatedAt')
|
||||||
..write(')'))
|
..write(')'))
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
@@ -1220,11 +1221,15 @@ class TransactionsCompanion extends UpdateCompanion<Transaction> {
|
|||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return (StringBuffer('TransactionsCompanion(')
|
return (StringBuffer('TransactionsCompanion(')
|
||||||
..write('id: $id, ')..write('name: $name, ')..write(
|
..write('id: $id, ')
|
||||||
'date: $date, ')..write('amount: $amount, ')..write(
|
..write('name: $name, ')
|
||||||
'checked: $checked, ')..write('accountId: $accountId, ')..write(
|
..write('date: $date, ')
|
||||||
'recurringTransactionId: $recurringTransactionId, ')..write(
|
..write('amount: $amount, ')
|
||||||
'updatedAt: $updatedAt')..write(')'))
|
..write('checked: $checked, ')
|
||||||
|
..write('accountId: $accountId, ')
|
||||||
|
..write('recurringTransactionId: $recurringTransactionId, ')
|
||||||
|
..write('updatedAt: $updatedAt')
|
||||||
|
..write(')'))
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1233,9 +1238,7 @@ class $SyncLogTable extends SyncLog with TableInfo<$SyncLogTable, SyncLogData> {
|
|||||||
@override
|
@override
|
||||||
final GeneratedDatabase attachedDatabase;
|
final GeneratedDatabase attachedDatabase;
|
||||||
final String? _alias;
|
final String? _alias;
|
||||||
|
|
||||||
$SyncLogTable(this.attachedDatabase, [this._alias]);
|
$SyncLogTable(this.attachedDatabase, [this._alias]);
|
||||||
|
|
||||||
static const VerificationMeta _idMeta = const VerificationMeta('id');
|
static const VerificationMeta _idMeta = const VerificationMeta('id');
|
||||||
@override
|
@override
|
||||||
late final GeneratedColumn<int> id = GeneratedColumn<int>(
|
late final GeneratedColumn<int> id = GeneratedColumn<int>(
|
||||||
@@ -1251,13 +1254,13 @@ class $SyncLogTable extends SyncLog with TableInfo<$SyncLogTable, SyncLogData> {
|
|||||||
);
|
);
|
||||||
@override
|
@override
|
||||||
late final GeneratedColumnWithTypeConverter<SyncLogTypeEnum, int> type =
|
late final GeneratedColumnWithTypeConverter<SyncLogTypeEnum, int> type =
|
||||||
GeneratedColumn<int>(
|
GeneratedColumn<int>(
|
||||||
'type',
|
'type',
|
||||||
aliasedName,
|
aliasedName,
|
||||||
false,
|
false,
|
||||||
type: DriftSqlType.int,
|
type: DriftSqlType.int,
|
||||||
requiredDuringInsert: true,
|
requiredDuringInsert: true,
|
||||||
).withConverter<SyncLogTypeEnum>($SyncLogTable.$convertertype);
|
).withConverter<SyncLogTypeEnum>($SyncLogTable.$convertertype);
|
||||||
static const VerificationMeta _descriptionMeta = const VerificationMeta(
|
static const VerificationMeta _descriptionMeta = const VerificationMeta(
|
||||||
'description',
|
'description',
|
||||||
);
|
);
|
||||||
@@ -1282,19 +1285,16 @@ class $SyncLogTable extends SyncLog with TableInfo<$SyncLogTable, SyncLogData> {
|
|||||||
requiredDuringInsert: false,
|
requiredDuringInsert: false,
|
||||||
defaultValue: currentDateAndTime,
|
defaultValue: currentDateAndTime,
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<GeneratedColumn> get $columns => [id, type, description, updatedAt];
|
List<GeneratedColumn> get $columns => [id, type, description, updatedAt];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get aliasedName => _alias ?? actualTableName;
|
String get aliasedName => _alias ?? actualTableName;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get actualTableName => $name;
|
String get actualTableName => $name;
|
||||||
static const String $name = 'sync_log';
|
static const String $name = 'sync_log';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
VerificationContext validateIntegrity(Insertable<SyncLogData> instance, {
|
VerificationContext validateIntegrity(
|
||||||
|
Insertable<SyncLogData> instance, {
|
||||||
bool isInserting = false,
|
bool isInserting = false,
|
||||||
}) {
|
}) {
|
||||||
final context = VerificationContext();
|
final context = VerificationContext();
|
||||||
@@ -1322,7 +1322,6 @@ class $SyncLogTable extends SyncLog with TableInfo<$SyncLogTable, SyncLogData> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Set<GeneratedColumn> get $primaryKey => {id};
|
Set<GeneratedColumn> get $primaryKey => {id};
|
||||||
|
|
||||||
@override
|
@override
|
||||||
SyncLogData map(Map<String, dynamic> data, {String? tablePrefix}) {
|
SyncLogData map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||||
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
|
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
|
||||||
@@ -1354,7 +1353,7 @@ class $SyncLogTable extends SyncLog with TableInfo<$SyncLogTable, SyncLogData> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static JsonTypeConverter2<SyncLogTypeEnum, int, int> $convertertype =
|
static JsonTypeConverter2<SyncLogTypeEnum, int, int> $convertertype =
|
||||||
const EnumIndexConverter<SyncLogTypeEnum>(SyncLogTypeEnum.values);
|
const EnumIndexConverter<SyncLogTypeEnum>(SyncLogTypeEnum.values);
|
||||||
}
|
}
|
||||||
|
|
||||||
class SyncLogData extends DataClass implements Insertable<SyncLogData> {
|
class SyncLogData extends DataClass implements Insertable<SyncLogData> {
|
||||||
@@ -1369,14 +1368,12 @@ class SyncLogData extends DataClass implements Insertable<SyncLogData> {
|
|||||||
|
|
||||||
/// Wann dieser SyncLog das letzte mal geupdated wurde
|
/// Wann dieser SyncLog das letzte mal geupdated wurde
|
||||||
final DateTime updatedAt;
|
final DateTime updatedAt;
|
||||||
|
|
||||||
const SyncLogData({
|
const SyncLogData({
|
||||||
required this.id,
|
required this.id,
|
||||||
required this.type,
|
required this.type,
|
||||||
required this.description,
|
required this.description,
|
||||||
required this.updatedAt,
|
required this.updatedAt,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||||
final map = <String, Expression>{};
|
final map = <String, Expression>{};
|
||||||
@@ -1398,7 +1395,8 @@ class SyncLogData extends DataClass implements Insertable<SyncLogData> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
factory SyncLogData.fromJson(Map<String, dynamic> json, {
|
factory SyncLogData.fromJson(
|
||||||
|
Map<String, dynamic> json, {
|
||||||
ValueSerializer? serializer,
|
ValueSerializer? serializer,
|
||||||
}) {
|
}) {
|
||||||
serializer ??= driftRuntimeOptions.defaultSerializer;
|
serializer ??= driftRuntimeOptions.defaultSerializer;
|
||||||
@@ -1411,7 +1409,6 @@ class SyncLogData extends DataClass implements Insertable<SyncLogData> {
|
|||||||
updatedAt: serializer.fromJson<DateTime>(json['updatedAt']),
|
updatedAt: serializer.fromJson<DateTime>(json['updatedAt']),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Map<String, dynamic> toJson({ValueSerializer? serializer}) {
|
Map<String, dynamic> toJson({ValueSerializer? serializer}) {
|
||||||
serializer ??= driftRuntimeOptions.defaultSerializer;
|
serializer ??= driftRuntimeOptions.defaultSerializer;
|
||||||
@@ -1428,14 +1425,12 @@ class SyncLogData extends DataClass implements Insertable<SyncLogData> {
|
|||||||
SyncLogTypeEnum? type,
|
SyncLogTypeEnum? type,
|
||||||
String? description,
|
String? description,
|
||||||
DateTime? updatedAt,
|
DateTime? updatedAt,
|
||||||
}) =>
|
}) => SyncLogData(
|
||||||
SyncLogData(
|
id: id ?? this.id,
|
||||||
id: id ?? this.id,
|
type: type ?? this.type,
|
||||||
type: type ?? this.type,
|
description: description ?? this.description,
|
||||||
description: description ?? this.description,
|
updatedAt: updatedAt ?? this.updatedAt,
|
||||||
updatedAt: updatedAt ?? this.updatedAt,
|
);
|
||||||
);
|
|
||||||
|
|
||||||
SyncLogData copyWithCompanion(SyncLogCompanion data) {
|
SyncLogData copyWithCompanion(SyncLogCompanion data) {
|
||||||
return SyncLogData(
|
return SyncLogData(
|
||||||
id: data.id.present ? data.id.value : this.id,
|
id: data.id.present ? data.id.value : this.id,
|
||||||
@@ -1450,23 +1445,24 @@ class SyncLogData extends DataClass implements Insertable<SyncLogData> {
|
|||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return (StringBuffer('SyncLogData(')
|
return (StringBuffer('SyncLogData(')
|
||||||
..write('id: $id, ')..write('type: $type, ')..write(
|
..write('id: $id, ')
|
||||||
'description: $description, ')..write('updatedAt: $updatedAt')..write(
|
..write('type: $type, ')
|
||||||
')'))
|
..write('description: $description, ')
|
||||||
|
..write('updatedAt: $updatedAt')
|
||||||
|
..write(')'))
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(id, type, description, updatedAt);
|
int get hashCode => Object.hash(id, type, description, updatedAt);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) =>
|
bool operator ==(Object other) =>
|
||||||
identical(this, other) ||
|
identical(this, other) ||
|
||||||
(other is SyncLogData &&
|
(other is SyncLogData &&
|
||||||
other.id == this.id &&
|
other.id == this.id &&
|
||||||
other.type == this.type &&
|
other.type == this.type &&
|
||||||
other.description == this.description &&
|
other.description == this.description &&
|
||||||
other.updatedAt == this.updatedAt);
|
other.updatedAt == this.updatedAt);
|
||||||
}
|
}
|
||||||
|
|
||||||
class SyncLogCompanion extends UpdateCompanion<SyncLogData> {
|
class SyncLogCompanion extends UpdateCompanion<SyncLogData> {
|
||||||
@@ -1474,21 +1470,18 @@ class SyncLogCompanion extends UpdateCompanion<SyncLogData> {
|
|||||||
final Value<SyncLogTypeEnum> type;
|
final Value<SyncLogTypeEnum> type;
|
||||||
final Value<String> description;
|
final Value<String> description;
|
||||||
final Value<DateTime> updatedAt;
|
final Value<DateTime> updatedAt;
|
||||||
|
|
||||||
const SyncLogCompanion({
|
const SyncLogCompanion({
|
||||||
this.id = const Value.absent(),
|
this.id = const Value.absent(),
|
||||||
this.type = const Value.absent(),
|
this.type = const Value.absent(),
|
||||||
this.description = const Value.absent(),
|
this.description = const Value.absent(),
|
||||||
this.updatedAt = const Value.absent(),
|
this.updatedAt = const Value.absent(),
|
||||||
});
|
});
|
||||||
|
|
||||||
SyncLogCompanion.insert({
|
SyncLogCompanion.insert({
|
||||||
this.id = const Value.absent(),
|
this.id = const Value.absent(),
|
||||||
required SyncLogTypeEnum type,
|
required SyncLogTypeEnum type,
|
||||||
this.description = const Value.absent(),
|
this.description = const Value.absent(),
|
||||||
this.updatedAt = const Value.absent(),
|
this.updatedAt = const Value.absent(),
|
||||||
}) : type = Value(type);
|
}) : type = Value(type);
|
||||||
|
|
||||||
static Insertable<SyncLogData> custom({
|
static Insertable<SyncLogData> custom({
|
||||||
Expression<int>? id,
|
Expression<int>? id,
|
||||||
Expression<int>? type,
|
Expression<int>? type,
|
||||||
@@ -1540,8 +1533,10 @@ class SyncLogCompanion extends UpdateCompanion<SyncLogData> {
|
|||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return (StringBuffer('SyncLogCompanion(')
|
return (StringBuffer('SyncLogCompanion(')
|
||||||
..write('id: $id, ')..write('type: $type, ')..write(
|
..write('id: $id, ')
|
||||||
'description: $description, ')..write('updatedAt: $updatedAt')
|
..write('type: $type, ')
|
||||||
|
..write('description: $description, ')
|
||||||
|
..write('updatedAt: $updatedAt')
|
||||||
..write(')'))
|
..write(')'))
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
@@ -2905,7 +2900,6 @@ class $$SyncLogTableFilterComposer
|
|||||||
super.$addJoinBuilderToRootComposer,
|
super.$addJoinBuilderToRootComposer,
|
||||||
super.$removeJoinBuilderFromRootComposer,
|
super.$removeJoinBuilderFromRootComposer,
|
||||||
});
|
});
|
||||||
|
|
||||||
ColumnFilters<int> get id => $composableBuilder(
|
ColumnFilters<int> get id => $composableBuilder(
|
||||||
column: $table.id,
|
column: $table.id,
|
||||||
builder: (column) => ColumnFilters(column),
|
builder: (column) => ColumnFilters(column),
|
||||||
@@ -2937,7 +2931,6 @@ class $$SyncLogTableOrderingComposer
|
|||||||
super.$addJoinBuilderToRootComposer,
|
super.$addJoinBuilderToRootComposer,
|
||||||
super.$removeJoinBuilderFromRootComposer,
|
super.$removeJoinBuilderFromRootComposer,
|
||||||
});
|
});
|
||||||
|
|
||||||
ColumnOrderings<int> get id => $composableBuilder(
|
ColumnOrderings<int> get id => $composableBuilder(
|
||||||
column: $table.id,
|
column: $table.id,
|
||||||
builder: (column) => ColumnOrderings(column),
|
builder: (column) => ColumnOrderings(column),
|
||||||
@@ -2968,7 +2961,6 @@ class $$SyncLogTableAnnotationComposer
|
|||||||
super.$addJoinBuilderToRootComposer,
|
super.$addJoinBuilderToRootComposer,
|
||||||
super.$removeJoinBuilderFromRootComposer,
|
super.$removeJoinBuilderFromRootComposer,
|
||||||
});
|
});
|
||||||
|
|
||||||
GeneratedColumn<int> get id =>
|
GeneratedColumn<int> get id =>
|
||||||
$composableBuilder(column: $table.id, builder: (column) => column);
|
$composableBuilder(column: $table.id, builder: (column) => column);
|
||||||
|
|
||||||
@@ -3069,7 +3061,6 @@ class $AppDatabaseManager {
|
|||||||
$$RecurringTransactionsTableTableManager(_db, _db.recurringTransactions);
|
$$RecurringTransactionsTableTableManager(_db, _db.recurringTransactions);
|
||||||
$$TransactionsTableTableManager get transactions =>
|
$$TransactionsTableTableManager get transactions =>
|
||||||
$$TransactionsTableTableManager(_db, _db.transactions);
|
$$TransactionsTableTableManager(_db, _db.transactions);
|
||||||
|
|
||||||
$$SyncLogTableTableManager get syncLog =>
|
$$SyncLogTableTableManager get syncLog =>
|
||||||
$$SyncLogTableTableManager(_db, _db.syncLog);
|
$$SyncLogTableTableManager(_db, _db.syncLog);
|
||||||
}
|
}
|
||||||
|
|||||||
16
lib/Tasks/background_init.dart
Normal file
16
lib/Tasks/background_init.dart
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:logger/logger.dart';
|
||||||
|
|
||||||
|
import '../Controller/port_controller.dart';
|
||||||
|
|
||||||
|
/// Initialisiert benötigte Services in Background-Isolates
|
||||||
|
Future<void> initBackground() async {
|
||||||
|
final Logger logger = Logger()..d('Init Background for Native');
|
||||||
|
|
||||||
|
final RootIsolateToken? rootIsolateToken = await PortController()
|
||||||
|
.getRootIsolateToken();
|
||||||
|
if (rootIsolateToken != null) {
|
||||||
|
logger.i('Initialising BackgroundIsolateBinaryMessenger...');
|
||||||
|
BackgroundIsolateBinaryMessenger.ensureInitialized(rootIsolateToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
6
lib/Tasks/background_init_web.dart
Normal file
6
lib/Tasks/background_init_web.dart
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import 'package:logger/logger.dart';
|
||||||
|
|
||||||
|
/// Initialisiert benötigte Services in Background-Isolates für Web
|
||||||
|
Future<void> initBackground() async {
|
||||||
|
Logger().d('Init Background for Web');
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:logger/logger.dart';
|
||||||
|
|
||||||
import '../Entities/drift_database.dart';
|
import '../Entities/drift_database.dart';
|
||||||
import '../Entities/time_frame_enum.dart';
|
import '../Entities/time_frame_enum.dart';
|
||||||
@@ -13,12 +14,18 @@ class GenerateTransactionsTask extends Task {
|
|||||||
final RecurringTransactionRepository _recurringTransactionRepository =
|
final RecurringTransactionRepository _recurringTransactionRepository =
|
||||||
RecurringTransactionRepository();
|
RecurringTransactionRepository();
|
||||||
|
|
||||||
|
final Logger _logger = Logger();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<bool> execute() async {
|
Future<bool> execute() async {
|
||||||
|
_logger.i('Generating Transactions of recurring Transactions...');
|
||||||
|
|
||||||
final List<RecurringTransaction> recurringTransactions =
|
final List<RecurringTransaction> recurringTransactions =
|
||||||
await _recurringTransactionRepository.findBy();
|
await _recurringTransactionRepository.findBy();
|
||||||
|
|
||||||
for (final recurringTransaction in recurringTransactions) {
|
for (final recurringTransaction in recurringTransactions) {
|
||||||
|
_logger.i('Generating Transactions of $recurringTransaction...');
|
||||||
|
|
||||||
final List<Transaction> transactions = await _transactionRepository
|
final List<Transaction> transactions = await _transactionRepository
|
||||||
.findBy(
|
.findBy(
|
||||||
recurringTransaction: recurringTransaction,
|
recurringTransaction: recurringTransaction,
|
||||||
@@ -43,6 +50,7 @@ class GenerateTransactionsTask extends Task {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (DateTime.now().compareTo(nextTransactionDate) <= 0) {
|
if (DateTime.now().compareTo(nextTransactionDate) <= 0) {
|
||||||
|
// TODO: Nicht mit NOW, sondern Ende dieses Monats Vergleichen
|
||||||
final TransactionsCompanion transaction = TransactionsCompanion(
|
final TransactionsCompanion transaction = TransactionsCompanion(
|
||||||
name: Value(recurringTransaction.name),
|
name: Value(recurringTransaction.name),
|
||||||
date: Value(nextTransactionDate),
|
date: Value(nextTransactionDate),
|
||||||
@@ -52,10 +60,15 @@ class GenerateTransactionsTask extends Task {
|
|||||||
recurringTransactionId: Value(recurringTransaction.id),
|
recurringTransactionId: Value(recurringTransaction.id),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
_logger.i(
|
||||||
|
'Adding transaction ${transaction.name} on ${transaction.date}',
|
||||||
|
);
|
||||||
|
|
||||||
await _transactionRepository.add(transaction);
|
await _transactionRepository.add(transaction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_logger.i('Generating transactions completed.');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
38
lib/Tasks/workers.dart
Normal file
38
lib/Tasks/workers.dart
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:isolate_manager/isolate_manager.dart';
|
||||||
|
|
||||||
|
import 'background_init_web.dart' if (dart.library.io) 'background_init.dart';
|
||||||
|
import 'generate_transactions_task.dart';
|
||||||
|
|
||||||
|
@pragma('vm:entry-point')
|
||||||
|
@isolateManagerWorker
|
||||||
|
/// Führt eine Hintergrundtask lokal aus
|
||||||
|
Future<void> runTask(final Map<String, dynamic> params) async {
|
||||||
|
final String taskName = params['taskName'];
|
||||||
|
final int initialDelayMinutes = params['initialDelayMinutes'];
|
||||||
|
final int frequencyMinutes = params['frequencyMinutes'];
|
||||||
|
|
||||||
|
await Future.delayed(Duration(minutes: initialDelayMinutes));
|
||||||
|
|
||||||
|
await executeTask(taskName, null);
|
||||||
|
|
||||||
|
await Future.delayed(Duration(minutes: frequencyMinutes));
|
||||||
|
|
||||||
|
unawaited(runTask(params));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Funktion um Hintergrundaufgaben auszuführen
|
||||||
|
Future<bool> executeTask(
|
||||||
|
final String taskName,
|
||||||
|
final Map<String, dynamic>? inputData,
|
||||||
|
) async {
|
||||||
|
await initBackground();
|
||||||
|
|
||||||
|
switch (taskName) {
|
||||||
|
case 'generate_transactions':
|
||||||
|
return GenerateTransactionsTask().execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Future.value(true);
|
||||||
|
}
|
||||||
9
lib/Tasks/workmanager_workers.dart
Normal file
9
lib/Tasks/workmanager_workers.dart
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import 'package:workmanager/workmanager.dart';
|
||||||
|
|
||||||
|
import 'workers.dart';
|
||||||
|
|
||||||
|
/// Die Funktion wird von Hintergrundtasks ausgerufen, um diese auszuführen
|
||||||
|
@pragma('vm:entry-point')
|
||||||
|
void callbackDispatcher() {
|
||||||
|
Workmanager().executeTask(executeTask);
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ import 'package:flutter_localizations/flutter_localizations.dart';
|
|||||||
import 'package:routemaster/routemaster.dart';
|
import 'package:routemaster/routemaster.dart';
|
||||||
|
|
||||||
import 'Controller/background_task_controller.dart';
|
import 'Controller/background_task_controller.dart';
|
||||||
|
import 'Controller/port_controller.dart';
|
||||||
import 'Services/navigation_service.dart';
|
import 'Services/navigation_service.dart';
|
||||||
import 'Services/router_service.dart';
|
import 'Services/router_service.dart';
|
||||||
import 'Services/theme_service.dart';
|
import 'Services/theme_service.dart';
|
||||||
@@ -10,6 +11,7 @@ import 'Services/theme_service.dart';
|
|||||||
void main() {
|
void main() {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
||||||
|
PortController();
|
||||||
BackgroundTaskController();
|
BackgroundTaskController();
|
||||||
|
|
||||||
runApp(
|
runApp(
|
||||||
|
|||||||
15465
web/runTask.js
Normal file
15465
web/runTask.js
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user