Skip to content

Commit

Permalink
refactor: move databases back into main isolate
Browse files Browse the repository at this point in the history
  • Loading branch information
matthiasn committed May 3, 2024
1 parent 030134e commit d548e3e
Show file tree
Hide file tree
Showing 9 changed files with 50 additions and 121 deletions.
78 changes: 11 additions & 67 deletions lib/database/common.dart
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import 'dart:async';
import 'dart:io';
import 'dart:isolate';

import 'package:drift/drift.dart';
import 'package:drift/isolate.dart';
import 'package:drift/native.dart';
import 'package:flutter/foundation.dart';
import 'package:intl/intl.dart';
import 'package:lotti/get_it.dart';
import 'package:lotti/utils/file_utils.dart';
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart';
import 'package:sqlite3/sqlite3.dart';
import 'package:sqlite3_flutter_libs/sqlite3_flutter_libs.dart';

Future<File> getDatabaseFile(String dbFileName) async {
final dbFolder = getDocumentsDirectory();
Expand All @@ -33,66 +34,17 @@ LazyDatabase openDbConnection(
return NativeDatabase.memory();
}

final file = await getDatabaseFile(fileName);
debugPrint('DB LazyDatabase ${file.path}');
final dbFolder = await getApplicationDocumentsDirectory();
final file = File(p.join(dbFolder.path, fileName));

return NativeDatabase(file);
});
}

Future<DriftIsolate> createDriftIsolate(
String dbFileName, {
bool inMemory = false,
}) async {
// this method is called from the main isolate. Since we can't use
// getApplicationDocumentsDirectory on a background isolate, we calculate
// the database path in the foreground isolate and then inform the
// background isolate about the path.
final dir = getDocumentsDirectory();
final path = p.join(dir.path, dbFileName);
final receivePort = ReceivePort();

await Isolate.spawn(
inMemory ? _startBackgroundInMem : _startBackground,
_IsolateStartRequest(receivePort.sendPort, path),
);

// _startBackground will send the DriftIsolate to this ReceivePort
return await receivePort.first as DriftIsolate;
}

void _startBackground(_IsolateStartRequest request) {
// this is the entry point from the background isolate! Let's create
// the database from the path we received
final executor = NativeDatabase(File(request.targetPath));
// we're using DriftIsolate.inCurrent here as this method already runs on a
// background isolate. If we used DriftIsolate.spawn, a third isolate would be
// started which is not what we want!
final driftIsolate = DriftIsolate.inCurrent(
() => DatabaseConnection(executor),
);
// inform the starting isolate about this, so that it can call .connect()
request.sendDriftIsolate.send(driftIsolate);
}

void _startBackgroundInMem(_IsolateStartRequest request) {
final executor = NativeDatabase.memory();
final driftIsolate = DriftIsolate.inCurrent(
() => DatabaseConnection(executor),
);
request.sendDriftIsolate.send(driftIsolate);
}
if (Platform.isAndroid) {
await applyWorkaroundToOpenSqlite3OnOldAndroidVersions();
}

// used to bundle the SendPort and the target path, since isolate entry point
// functions can only take one parameter.
class _IsolateStartRequest {
_IsolateStartRequest(
this.sendDriftIsolate,
this.targetPath,
);
sqlite3.tempDirectory = (await getTemporaryDirectory()).path;

final SendPort sendDriftIsolate;
final String targetPath;
return NativeDatabase.createInBackground(file);
});
}

DatabaseConnection getDatabaseConnection(String dbFileName) {
Expand All @@ -105,11 +57,3 @@ DatabaseConnection getDatabaseConnection(String dbFileName) {
}),
);
}

DatabaseConnection getDbConnFromIsolate(DriftIsolate isolate) {
return DatabaseConnection.delayed(
Future.sync(() async {
return isolate.connect();
}),
);
}
34 changes: 28 additions & 6 deletions lib/database/database.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:collection/collection.dart';
import 'package:drift/drift.dart';
import 'package:drift/native.dart';
import 'package:enum_to_string/enum_to_string.dart';
import 'package:flutter/foundation.dart';
import 'package:lotti/classes/entity_definitions.dart';
Expand All @@ -16,6 +18,10 @@ import 'package:lotti/get_it.dart';
import 'package:lotti/sync/vector_clock.dart';
import 'package:lotti/utils/file_utils.dart';
import 'package:lotti/widgets/journal/entry_tools.dart';
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart';
import 'package:sqlite3/sqlite3.dart';
import 'package:sqlite3_flutter_libs/sqlite3_flutter_libs.dart';

part 'database.g.dart';

Expand All @@ -34,13 +40,33 @@ class JournalDb extends _$JournalDb {
this.inMemoryDatabase = false,
String? overriddenFilename,
}) : super(
openDbConnection(
_openConnection(
overriddenFilename ?? journalDbFileName,
inMemoryDatabase: inMemoryDatabase,
),
);

JournalDb.connect(super.connection) : super.connect();
static LazyDatabase _openConnection(
String fileName, {
bool inMemoryDatabase = false,
}) {
return LazyDatabase(() async {
if (inMemoryDatabase) {
return NativeDatabase.memory();
}

final dbFolder = await getApplicationDocumentsDirectory();
final file = File(p.join(dbFolder.path, fileName));

if (Platform.isAndroid) {
await applyWorkaroundToOpenSqlite3OnOldAndroidVersions();
}

sqlite3.tempDirectory = (await getTemporaryDirectory()).path;

return NativeDatabase.createInBackground(file);
});
}

bool inMemoryDatabase = false;

Expand Down Expand Up @@ -726,7 +752,3 @@ class JournalDb extends _$JournalDb {
return linesAffected;
}
}

JournalDb getJournalDb() {
return JournalDb.connect(getDatabaseConnection(journalDbFileName));
}
4 changes: 0 additions & 4 deletions lib/database/logging_db.dart
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,3 @@ class LoggingDb extends _$LoggingDb {
return allLogEntries(limit).watch();
}
}

LoggingDb getLoggingDb() {
return LoggingDb.connect(getDatabaseConnection(loggingDbFileName));
}
4 changes: 0 additions & 4 deletions lib/database/settings_db.dart
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,3 @@ class SettingsDb extends _$SettingsDb {
}
}
}

SettingsDb getSettingsDb() {
return SettingsDb.connect(getDatabaseConnection(settingsDbFileName));
}
4 changes: 0 additions & 4 deletions lib/database/sync_db.dart
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,3 @@ class SyncDatabase extends _$SyncDatabase {
@override
int get schemaVersion => 1;
}

SyncDatabase getSyncDatabase() {
return SyncDatabase.connect(getDatabaseConnection(syncDbFileName));
}
30 changes: 6 additions & 24 deletions lib/get_it.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import 'dart:async';

import 'package:drift/isolate.dart';
import 'package:get_it/get_it.dart';
import 'package:lotti/database/common.dart';
import 'package:lotti/database/database.dart';
import 'package:lotti/database/editor_db.dart';
import 'package:lotti/database/fts5_db.dart';
Expand All @@ -14,7 +12,6 @@ import 'package:lotti/logic/ai/ai_logic.dart';
import 'package:lotti/logic/health_import.dart';
import 'package:lotti/logic/persistence_logic.dart';
import 'package:lotti/services/asr_service.dart';
import 'package:lotti/services/db_notification.dart';
import 'package:lotti/services/editor_state_service.dart';
import 'package:lotti/services/entities_cache_service.dart';
import 'package:lotti/services/link_service.dart';
Expand All @@ -29,32 +26,17 @@ import 'package:lotti/sync/outbox/outbox_service.dart';
final getIt = GetIt.instance;

Future<void> registerSingletons() async {
await getIt.registerSingleton<Future<DriftIsolate>>(
createDriftIsolate(journalDbFileName),
instanceName: journalDbFileName,
);

await getIt.registerSingleton<Future<DriftIsolate>>(
createDriftIsolate(loggingDbFileName),
instanceName: loggingDbFileName,
);

await getIt.registerSingleton<Future<DriftIsolate>>(
createDriftIsolate(syncDbFileName),
instanceName: syncDbFileName,
);

getIt
..registerSingleton<Fts5Db>(Fts5Db())
..registerSingleton<LoggingDb>(getLoggingDb())
..registerSingleton<JournalDb>(getJournalDb())
..registerSingleton<DatabaseUpdateNotifications>(
DatabaseUpdateNotifications(),
)
..registerSingleton<LoggingDb>(LoggingDb())
..registerSingleton<JournalDb>(JournalDb())
// ..registerSingleton<DatabaseUpdateNotifications>(
// DatabaseUpdateNotifications(),
// )
..registerSingleton<EditorDb>(EditorDb())
..registerSingleton<TagsService>(TagsService())
..registerSingleton<EntitiesCacheService>(EntitiesCacheService())
..registerSingleton<SyncDatabase>(getSyncDatabase())
..registerSingleton<SyncDatabase>(SyncDatabase())
..registerSingleton<AsrService>(AsrService())
..registerSingleton<VectorClockService>(VectorClockService())
..registerSingleton<TimeService>(TimeService())
Expand Down
12 changes: 2 additions & 10 deletions lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import 'dart:async';
import 'dart:io';

import 'package:drift/isolate.dart';
import 'package:flutter/material.dart';
import 'package:flutter_animate/flutter_animate.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:hotkey_manager/hotkey_manager.dart';
import 'package:lotti/beamer/beamer_app.dart';
import 'package:lotti/database/common.dart';
import 'package:lotti/database/logging_db.dart';
import 'package:lotti/database/settings_db.dart';
import 'package:lotti/get_it.dart';
Expand All @@ -34,14 +32,8 @@ Future<void> main() async {

getIt
..registerSingleton<SecureStorage>(SecureStorage())
..registerSingleton<Directory>(docDir);

await getIt.registerSingleton<Future<DriftIsolate>>(
createDriftIsolate(settingsDbFileName),
instanceName: settingsDbFileName,
);
getIt
..registerSingleton<SettingsDb>(getSettingsDb())
..registerSingleton<Directory>(docDir)
..registerSingleton<SettingsDb>(SettingsDb())
..registerSingleton<WindowService>(WindowService());

await getIt<WindowService>().restore();
Expand Down
2 changes: 1 addition & 1 deletion pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2501,7 +2501,7 @@ packages:
source: hosted
version: "2.3.3"
sqlite3:
dependency: transitive
dependency: "direct main"
description:
name: sqlite3
sha256: "1abbeb84bf2b1a10e5e1138c913123c8aa9d83cd64e5f9a0dd847b3c83063202"
Expand Down
3 changes: 2 additions & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: lotti
description: Achieve your goals and keep your data private with Lotti.
publish_to: 'none'
version: 0.9.459+2494
version: 0.9.459+2496

msix_config:
display_name: LottiApp
Expand Down Expand Up @@ -138,6 +138,7 @@ dependencies:
share_plus: ^9.0.0
sqflite: ^2.0.1
sqflite_common_ffi: ^2.3.3
sqlite3: ^2.4.2
sqlite3_flutter_libs: ^0.5.15
timezone: ^0.9.1
tinycolor2: ^3.0.0
Expand Down

0 comments on commit d548e3e

Please sign in to comment.