Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/sqflite #18

Merged
merged 4 commits into from
Nov 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .flutter-plugins
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,6 @@ path_provider_android=/Users/dan/.pub-cache/hosted/pub.dev/path_provider_android
path_provider_foundation=/Users/dan/.pub-cache/hosted/pub.dev/path_provider_foundation-2.3.2/
path_provider_linux=/Users/dan/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/
path_provider_windows=/Users/dan/.pub-cache/hosted/pub.dev/path_provider_windows-2.2.1/
sqflite=/Users/dan/.pub-cache/hosted/pub.dev/sqflite-2.4.1/
sqflite_android=/Users/dan/.pub-cache/hosted/pub.dev/sqflite_android-2.4.0/
sqflite_darwin=/Users/dan/.pub-cache/hosted/pub.dev/sqflite_darwin-2.4.1/
8 changes: 0 additions & 8 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
Expand All @@ -12,8 +10,6 @@
"kind": "build",
"isDefault": true
},
"problemMatcher": [],
"detail": "Runs a specific Flutter test file on the Chrome platform."
},
{
"label": "Native tests",
Expand All @@ -24,8 +20,6 @@
"kind": "build",
"isDefault": true
},
"problemMatcher": [],
"detail": "Runs a specific Flutter test file on the Chrome platform."
},
{
"label": "Web tests",
Expand All @@ -41,8 +35,6 @@
"kind": "build",
"isDefault": true
},
"problemMatcher": [],
"detail": "Runs a specific Flutter test file on the Chrome platform."
}
]
}
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,8 @@ The currently available persistence options are broken down by platform:

### Native

* **FilePersistor**: The default file-based persistence implementation for native platforms. Documents are stored in one or more files based on the persistence configuration.
* **SqlitePersistor**: A SQLite persistence implementation using [sqflite](https://pub.dev/packages/sqflite). Documents are distributed in rows based on their persistence configuration.
* **FilePersistor**: A file-based persistence implementation for native platforms. Documents are stored in one or more files based on the persistence configuration.

### Web

Expand Down
89 changes: 49 additions & 40 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,16 @@ import 'package:uuid/uuid.dart';

const uuid = Uuid();

final logger = Logger('Playground');

void main() async {
WidgetsFlutterBinding.ensureInitialized();

Loon.configure(
persistor: Persistor.current(),
enableLogging: true,
);

await Loon.hydrate();
await logger.measure('Hydrate', () => Loon.hydrate());

runApp(const MyApp());
}
Expand Down Expand Up @@ -130,40 +131,42 @@ class _MyHomePageState extends State<MyHomePage> {
userSnap.data.name.startsWith(_controller.text),
),
builder: (context, usersSnap) {
return ListView.builder(
shrinkWrap: true,
itemCount: usersSnap.length,
itemBuilder: (context, index) {
final userSnap = usersSnap[index];
final user = userSnap.data;

return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(user.name),
TextButton(
onPressed: () {
_showEditDialog(userSnap.doc);
},
child: const Text('Edit'),
),
TextButton(
onPressed: () {
UserModel.store.doc(userSnap.id).delete();
},
child: Text(
'Remove',
style: Theme.of(context)
.textTheme
.bodyMedium!
.copyWith(
color: Colors.red,
),
return Flexible(
child: ListView.builder(
shrinkWrap: true,
itemCount: usersSnap.length,
itemBuilder: (context, index) {
final userSnap = usersSnap[index];
final user = userSnap.data;

return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(user.name),
TextButton(
onPressed: () {
_showEditDialog(userSnap.doc);
},
child: const Text('Edit'),
),
TextButton(
onPressed: () {
UserModel.store.doc(userSnap.id).delete();
},
child: Text(
'Remove',
style: Theme.of(context)
.textTheme
.bodyMedium!
.copyWith(
color: Colors.red,
),
),
),
),
],
);
},
],
);
},
),
);
},
),
Expand All @@ -182,18 +185,24 @@ class _MyHomePageState extends State<MyHomePage> {
FloatingActionButton(
onPressed: () {
final id = uuid.v4();
final doc = UserModel.store.doc(id);

if (!doc.exists()) {
UserModel.store.doc(id).create(UserModel(name: 'User $id'));
},
child: const Icon(Icons.add),
),
const SizedBox(width: 24),
FloatingActionButton.extended(
label: const Text('Load test (10000)'),
onPressed: () {
for (int i = 0; i < 10000; i++) {
final id = uuid.v4();
UserModel.store.doc(id).create(UserModel(name: 'User $id'));
}
},
child: const Icon(Icons.add),
),
const SizedBox(width: 24),
FloatingActionButton(
onPressed: () {
UserModel.store.delete();
Loon.clearAll();
},
child: const Icon(Icons.delete),
),
Expand Down
2 changes: 2 additions & 0 deletions example/macos/Flutter/GeneratedPluginRegistrant.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ import Foundation

import flutter_secure_storage_macos
import path_provider_foundation
import sqflite_darwin

func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
}
7 changes: 7 additions & 0 deletions example/macos/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@ PODS:
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
- sqflite_darwin (0.0.4):
- Flutter
- FlutterMacOS

DEPENDENCIES:
- flutter_secure_storage_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos`)
- FlutterMacOS (from `Flutter/ephemeral`)
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
- sqflite_darwin (from `Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin`)

EXTERNAL SOURCES:
flutter_secure_storage_macos:
Expand All @@ -18,11 +22,14 @@ EXTERNAL SOURCES:
:path: Flutter/ephemeral
path_provider_foundation:
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin
sqflite_darwin:
:path: Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin

SPEC CHECKSUMS:
flutter_secure_storage_macos: 59459653abe1adb92abbc8ea747d79f8d19866c9
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c
sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d

PODFILE CHECKSUM: 236401fc2c932af29a9fcf0e97baeeb2d750d367

Expand Down
52 changes: 50 additions & 2 deletions example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -331,10 +331,10 @@ packages:
dependency: transitive
description:
name: plugin_platform_interface
sha256: "6a2128648c854906c53fa8e33986fc0247a1116122f9534dd20e3ab9e16a32bc"
sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
url: "https://pub.dev"
source: hosted
version: "2.1.4"
version: "2.1.8"
pointycastle:
dependency: transitive
description:
Expand Down Expand Up @@ -372,6 +372,46 @@ packages:
url: "https://pub.dev"
source: hosted
version: "7.0.0"
sqflite:
dependency: transitive
description:
name: sqflite
sha256: "2d7299468485dca85efeeadf5d38986909c5eb0cd71fd3db2c2f000e6c9454bb"
url: "https://pub.dev"
source: hosted
version: "2.4.1"
sqflite_android:
dependency: transitive
description:
name: sqflite_android
sha256: "78f489aab276260cdd26676d2169446c7ecd3484bbd5fead4ca14f3ed4dd9ee3"
url: "https://pub.dev"
source: hosted
version: "2.4.0"
sqflite_common:
dependency: transitive
description:
name: sqflite_common
sha256: "4468b24876d673418a7b7147e5a08a715b4998a7ae69227acafaab762e0e5490"
url: "https://pub.dev"
source: hosted
version: "2.5.4+5"
sqflite_darwin:
dependency: transitive
description:
name: sqflite_darwin
sha256: "96a698e2bc82bd770a4d6aab00b42396a7c63d9e33513a56945cbccb594c2474"
url: "https://pub.dev"
source: hosted
version: "2.4.1"
sqflite_platform_interface:
dependency: transitive
description:
name: sqflite_platform_interface
sha256: "8dd4515c7bdcae0a785b0062859336de775e8c65db81ae33dd5445f35be61920"
url: "https://pub.dev"
source: hosted
version: "2.4.0"
stack_trace:
dependency: transitive
description:
Expand All @@ -396,6 +436,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.3.0"
synchronized:
dependency: transitive
description:
name: synchronized
sha256: "69fe30f3a8b04a0be0c15ae6490fc859a78ef4c43ae2dd5e8a623d45bfcf9225"
url: "https://pub.dev"
source: hosted
version: "3.3.0+3"
term_glyph:
dependency: transitive
description:
Expand Down
3 changes: 2 additions & 1 deletion lib/loon.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ library loon;
import 'dart:async';
import 'dart:convert';
import 'package:flutter/foundation.dart' hide Key;
import 'package:loon/persistor/file_persistor/file_persistor.dart';
import 'package:loon/persistor/indexed_db_persistor/indexed_db_persistor.dart';
import 'package:uuid/uuid.dart';
import 'dart:collection';
import 'persistor/platform_persistor/platform_persistor.dart';

export 'widgets/query_stream_builder.dart';
export 'widgets/document_stream_builder.dart';
Expand Down
34 changes: 20 additions & 14 deletions lib/persistor/data_store_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,42 +9,49 @@ class DataStoreManager {
/// The duration by which to throttle persistence changes to the file system.
final Duration persistenceThrottle;

/// The global persistor settings.
final PersistorSettings settings;

final void Function()? onSync;

final void Function(String text) onLog;

/// The resolver that contains a mapping of documents to the file data store in which
/// the document is currently stored.
final DataStoreResolver resolver;
final DataStoreFactory factory;

/// The index of [DualDataStore] objects by store name.
final Map<String, DualDataStore> index = {};
final Future<void> Function() _clearAll;

final DataStoreFactory factory;
final DataStoreResolverConfig resolverConfig;

/// The sync lock is used to block operations from accessing the file system while there is an ongoing sync
/// operation and conversely blocks a sync from starting until the ongoing operation holding the lock has finished.
final _syncLock = Lock();

late final _logger = Logger('DataStoreManager', output: onLog);

/// The sync timer is used to throttle syncing changes to the file system using
/// the given [persistenceThrottle]. After an that mutates the file system operation runs, it schedules
/// a sync to run on a timer. When the sync runs, it acquires the [_syncLock], blocking any operations
/// from being processed until the sync completes.
Timer? _syncTimer;

late final _logger = Logger('DataStoreManager', output: onLog);
/// The resolver that contains a mapping of documents to the file data store in which
/// the document is currently stored.
DataStoreResolver resolver;

/// The index of [DualDataStore] objects by store name.
Map<String, DualDataStore> index = {};

DataStoreManager({
required this.persistenceThrottle,
required this.onSync,
required this.onLog,
required this.settings,
required this.factory,
required DataStoreResolverConfig resolverConfig,
required this.resolverConfig,
required Set<String> initialStoreNames,
}) : resolver = DataStoreResolver(resolverConfig) {
required Future<void> Function() clearAll,
}) : _clearAll = clearAll,
resolver = DataStoreResolver(resolverConfig) {
for (final name in initialStoreNames) {
index[name] = DualDataStore(name, factory: factory);
}
Expand Down Expand Up @@ -311,12 +318,11 @@ class DataStoreManager {
// Cancel any pending sync, since all data stores are being cleared immediately.
_cancelSync();

await Future.wait([
...index.values.map((dataStore) => dataStore.delete()),
resolver.delete(),
]);
await _clearAll();

index.clear();
// Reset the data store index and resolver.
index = {};
resolver = DataStoreResolver(resolverConfig);
});
}
}
4 changes: 2 additions & 2 deletions lib/persistor/file_persistor/file_persistor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class FilePersistor extends Persistor {
super.settings = const PersistorSettings(),
super.persistenceThrottle = const Duration(milliseconds: 100),
DataStoreEncrypter? encrypter,
}) : encrypter = encrypter ?? DataStoreEncrypter(),
}) : encrypter = encrypter = encrypter ?? DataStoreEncrypter(),
logger = Logger('FilePersistor', output: Loon.logger.log);

void _onMessage(dynamic message) {
Expand Down Expand Up @@ -110,7 +110,7 @@ class FilePersistor extends Persistor {
return Isolate.spawn(
FilePersistorWorker.init,
initMessage,
debugName: 'Loon worker',
debugName: 'FilePersistorWorker',
);
});

Expand Down
Loading
Loading