chore: Update Serverpod and prepare the release (#117)
This commit is contained in:
parent
519a8efca0
commit
2a6d66c79e
103 changed files with 358 additions and 323 deletions
|
|
@ -1,3 +1,12 @@
|
|||
## 0.0.5
|
||||
|
||||
- fix: BREAKING. Rebuilds foreign key and unique projection from authored facts.
|
||||
- perf: Increases unique-conflict merge throughput by ~40%.
|
||||
- perf: Increases foreign-key chain insert merge throughput by ~3.3×.
|
||||
- perf: Increases foreign-key chain delete merge throughput by ~44%.
|
||||
- perf: Reduces storage used by CRDT metadata on relations.
|
||||
- chore: Updated Serverpod to `4.0.0-rc.2`.
|
||||
|
||||
## 0.0.4
|
||||
|
||||
- chore: Updated Serverpod to `4.0.0-rc.1`.
|
||||
|
|
|
|||
61
README.md
61
README.md
|
|
@ -17,9 +17,8 @@ out-of-the-box with Serverpod's existing APIs.
|
|||
- [Getting started](#getting-started)
|
||||
- [1. Add the package to the project](#1-add-the-package-to-the-project)
|
||||
- [2. Prepare the synced tables](#2-prepare-the-synced-tables)
|
||||
- [3. Configure the sync engine on the server](#3-configure-the-sync-engine-on-the-server)
|
||||
- [4. Configure the sync engine on the client](#4-configure-the-sync-engine-on-the-client)
|
||||
- [5. Wire the sync call on the client](#5-wire-the-sync-call-on-the-client)
|
||||
- [3. Configure the sync engine on the client](#3-configure-the-sync-engine-on-the-client)
|
||||
- [4. Wire the sync call on the client](#4-wire-the-sync-call-on-the-client)
|
||||
- [Usage](#usage)
|
||||
- [Scopes and sharing](#scopes-and-sharing)
|
||||
- [Data modeling limitations](#data-modeling-limitations)
|
||||
|
|
@ -102,17 +101,17 @@ Add the packages to the server and client `pubspec.yaml` files.
|
|||
# your_project_client/pubspec.yaml
|
||||
dependencies:
|
||||
serverpod_offline_sync_client: 0.0.4
|
||||
```
|
||||
```0.0.5
|
||||
|
||||
```yaml
|
||||
# your_project_server/pubspec.yaml
|
||||
dependencies:
|
||||
serverpod_offline_sync_server: 0.0.4
|
||||
```
|
||||
```0.0.5
|
||||
|
||||
> [!NOTE]
|
||||
> Version `0.0.4` requires Serverpod `4.0.0-rc.1`.
|
||||
|
||||
> Version `0.0.4` requires Serverpod `4.0.0-rc.2`.
|
||||
0.0.5
|
||||
After adding the dependencies, list the `serverpod_offline_sync` module on the
|
||||
`generator.yaml` file and enable the experimental `database: sync` option:
|
||||
|
||||
|
|
@ -145,53 +144,25 @@ fields:
|
|||
name: String
|
||||
```
|
||||
|
||||
### 3. Configure the sync engine on the server
|
||||
The `serverpod generate` command will emit the `syncTables` list on the server
|
||||
and the client. It will also wire the sync engine on the generated `Serverpod`
|
||||
class, so no extra configuration is needed on the server.
|
||||
|
||||
On the server, the `databaseInterceptor` is what ensures that all `session.db`
|
||||
objects are database instances that tracks operations for sync.
|
||||
### 3. Configure the sync engine on the client
|
||||
|
||||
The generated client opens a CRDT-wrapped session for the same tables:
|
||||
|
||||
```dart
|
||||
final pod = Serverpod(
|
||||
args,
|
||||
Protocol(),
|
||||
Endpoints(),
|
||||
// Add the database interceptor.
|
||||
databaseInterceptor: crdtDatabaseInterceptor,
|
||||
);
|
||||
|
||||
// Initialize the sync engine before pod.start() is called.
|
||||
pod.initializeCrdtSync(
|
||||
syncTables: [Person.t, Book.t, Author.t],
|
||||
);
|
||||
```
|
||||
|
||||
Don't forget to also configure the authentication following the regular
|
||||
Serverpod auth setup. Authentication is required because the sync needs a
|
||||
logged in user to synchronize data.
|
||||
|
||||
### 4. Configure the sync engine on the client
|
||||
|
||||
On the client, the regular `DatabaseSession` must be replaced by a wrapped
|
||||
version that includes the sync engine.
|
||||
|
||||
```dart
|
||||
final session = CrdtDatabaseSession.wraps(
|
||||
await client.createSession(databasePath, isDebugMode: kDebugMode),
|
||||
syncTables: [Person.t, Book.t, Author.t], // Must be the same as on the server.
|
||||
final session = await client.createSyncSession(
|
||||
databasePath,
|
||||
isDebugMode: kDebugMode,
|
||||
persistentUserId: persistentUserId,
|
||||
);
|
||||
|
||||
// Initialize the sync engine.
|
||||
await session.db.initialize();
|
||||
```
|
||||
|
||||
Then, store the `session` instance in the service locator.
|
||||
|
||||
> [!NOTE]
|
||||
> The list of synced tables must be the same on the server and the client.
|
||||
> Otherwise, all sync attempts will fail with a schema mismatch error.
|
||||
|
||||
### 5. Wire the sync call on the client
|
||||
### 4. Wire the sync call on the client
|
||||
|
||||
Be sure to authenticate the client before calling the sync methods. Otherwise,
|
||||
the sync operation will fail with a `Unauthorized` error.
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ dependencies:
|
|||
benchmark_harness: ^2.4.0
|
||||
intl: ^0.20.2
|
||||
path: ^1.9.1
|
||||
serverpod_database: 4.0.0-rc.1
|
||||
serverpod_database: 4.0.0-rc.2
|
||||
serverpod_offline_sync:
|
||||
path: ../packages/serverpod_offline_sync
|
||||
serverpod_offline_sync_server:
|
||||
|
|
|
|||
|
|
@ -15,51 +15,27 @@ The work on this package was inspired by the excellent work on [Synql](https://g
|
|||
The main selling point of the package is that there is almost nothing to learn. The app is built
|
||||
as a normal offline Serverpod app (generated models, ordinary CRUD) and the plugin handles replication automatically.
|
||||
|
||||
The four steps below contain all required changes on a project to use the package:
|
||||
The three steps below contain all required changes on a project to use the package:
|
||||
|
||||
1. Prepare the synced tables by adding the `scopeId` field to the models.
|
||||
1. Prepare the synced tables by using `database: sync` keyword on the models.
|
||||
```yaml
|
||||
class: Person
|
||||
table: person
|
||||
database: all
|
||||
database: sync
|
||||
fields:
|
||||
id: UuidValue?, defaultPersist=random_v7
|
||||
### Owner scope of this row. Maintained by the CRDT sync layer.
|
||||
### The user never sets this field nor sees its value on reads.
|
||||
scopeId: int?, relation(parent=crdt_scopes, onDelete=Cascade)
|
||||
name: String
|
||||
```
|
||||
|
||||
2. Configure the sync engine on the server.
|
||||
2. Configure the sync engine on the client.
|
||||
```dart
|
||||
final pod = Serverpod(
|
||||
args,
|
||||
Protocol(),
|
||||
Endpoints(),
|
||||
// Add the database interceptor.
|
||||
databaseInterceptor: crdtDatabaseInterceptor,
|
||||
);
|
||||
|
||||
// Initialize the sync engine before pod.start() is called.
|
||||
pod.initializeCrdtSync(
|
||||
syncTables: [Person.t, Book.t, Author.t],
|
||||
);
|
||||
```
|
||||
|
||||
3. Configure the sync engine on the client.
|
||||
```dart
|
||||
final session = CrdtDatabaseSession.wraps(
|
||||
await client.createSession(databasePath, isDebugMode: kDebugMode),
|
||||
syncTables: [Person.t, Book.t, Author.t],
|
||||
final session = await client.createSyncSession(
|
||||
databasePath,
|
||||
isDebugMode: kDebugMode,
|
||||
persistentUserId: persistentUserId,
|
||||
);
|
||||
|
||||
// Initialize the sync engine.
|
||||
// Then store the `session` instance in the service locator.
|
||||
await session.db.initialize();
|
||||
```
|
||||
|
||||
4. Wire the sync call on the client.
|
||||
3. Wire the sync call on the client.
|
||||
```dart
|
||||
// Push local changes and merge remote ones once (i.e. pull-to-refresh).
|
||||
await client.crdt.syncOnce(session);
|
||||
|
|
|
|||
|
|
@ -7,8 +7,6 @@ import 'package:serverpod_database/serverpod_database.dart'
|
|||
import 'package:serverpod_offline_sync_client/serverpod_offline_sync_client.dart';
|
||||
import 'package:serverpod_offline_sync_test_client/serverpod_offline_sync_test_client.dart';
|
||||
|
||||
import 'table_ops.dart' show demoSyncTables;
|
||||
|
||||
/// One local replica: a Serverpod client database wrapped with the
|
||||
/// `serverpod_offline_sync` CRDT layer, plus the calls that synchronize it.
|
||||
///
|
||||
|
|
@ -61,7 +59,7 @@ class OfflineReplica {
|
|||
);
|
||||
final crdtSession = CrdtDatabaseSession.wraps(
|
||||
rawSession,
|
||||
syncTables: demoSyncTables,
|
||||
syncTables: syncTables,
|
||||
persistentUserId: persistentUserId,
|
||||
);
|
||||
await crdtSession.db.initialize();
|
||||
|
|
|
|||
|
|
@ -261,8 +261,8 @@ final Map<String, TableOps> demoTableOps = {
|
|||
ops.name: ops,
|
||||
};
|
||||
|
||||
/// Tables synchronized by the demo, derived from [demoTableOps]. Mirrors the
|
||||
/// server `demoSyncTables`.
|
||||
/// Tables shown in the demo UI, derived from [demoTableOps]. The CRDT engine
|
||||
/// uses the generated [syncTables] list so it matches the server.
|
||||
final List<Table> demoSyncTables = [
|
||||
for (final ops in demoTableOps.values) ops.table,
|
||||
];
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ dependencies:
|
|||
http: ^1.5.0
|
||||
path: ^1.9.1
|
||||
path_provider: ^2.1.5
|
||||
serverpod_database: 4.0.0-rc.1
|
||||
serverpod_database: 4.0.0-rc.2
|
||||
serverpod_offline_sync_client:
|
||||
path: ../../packages/serverpod_offline_sync_client
|
||||
serverpod_offline_sync_test_client:
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@
|
|||
// ignore_for_file: type_literal_in_constant_pattern
|
||||
// ignore_for_file: use_super_parameters
|
||||
// ignore_for_file: invalid_use_of_internal_member
|
||||
// ignore_for_file: dead_code, no_leading_underscores_for_library_prefixes
|
||||
// ignore_for_file: unnecessary_null_comparison
|
||||
// ignore_for_file: dead_code, unnecessary_null_comparison
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'package:serverpod_database/serverpod_database.dart' as _isd;
|
||||
import 'package:serverpod_offline_sync/serverpod_offline_sync.dart'
|
||||
as _icw2tu00;
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@
|
|||
// ignore_for_file: type_literal_in_constant_pattern
|
||||
// ignore_for_file: use_super_parameters
|
||||
// ignore_for_file: invalid_use_of_internal_member
|
||||
// ignore_for_file: dead_code, no_leading_underscores_for_library_prefixes
|
||||
// ignore_for_file: unnecessary_null_comparison
|
||||
// ignore_for_file: dead_code, unnecessary_null_comparison
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'package:serverpod_database/serverpod_database.dart' as _isd;
|
||||
import 'package:serverpod_offline_sync/serverpod_offline_sync.dart'
|
||||
as _icw2tu00;
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@
|
|||
// ignore_for_file: invalid_use_of_internal_member
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
|
||||
import 'package:serverpod_serialization/serverpod_serialization.dart' as _iss;
|
||||
|
||||
/// Why a synced user tombstone changed row visibility.
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@
|
|||
// ignore_for_file: type_literal_in_constant_pattern
|
||||
// ignore_for_file: use_super_parameters
|
||||
// ignore_for_file: invalid_use_of_internal_member
|
||||
// ignore_for_file: dead_code, no_leading_underscores_for_library_prefixes
|
||||
// ignore_for_file: unnecessary_null_comparison
|
||||
// ignore_for_file: dead_code, unnecessary_null_comparison
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'package:serverpod_database/serverpod_database.dart' as _isd;
|
||||
import 'package:serverpod_offline_sync/serverpod_offline_sync.dart'
|
||||
as _icw2tu00;
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@
|
|||
// ignore_for_file: invalid_use_of_internal_member
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
|
||||
import 'package:serverpod_serialization/serverpod_serialization.dart' as _iss;
|
||||
|
||||
/// Why a domain column currently differs from its authored value.
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@
|
|||
// ignore_for_file: type_literal_in_constant_pattern
|
||||
// ignore_for_file: use_super_parameters
|
||||
// ignore_for_file: invalid_use_of_internal_member
|
||||
// ignore_for_file: dead_code, no_leading_underscores_for_library_prefixes
|
||||
// ignore_for_file: unnecessary_null_comparison
|
||||
// ignore_for_file: dead_code, unnecessary_null_comparison
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'package:serverpod_database/serverpod_database.dart' as _isd;
|
||||
import 'package:serverpod_offline_sync/serverpod_offline_sync.dart'
|
||||
as _icw2tu00;
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@
|
|||
// ignore_for_file: invalid_use_of_internal_member
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
|
||||
import 'package:serverpod_serialization/serverpod_serialization.dart' as _iss;
|
||||
|
||||
/// Materialized visibility state for a CRDT row.
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@
|
|||
// ignore_for_file: invalid_use_of_internal_member
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
|
||||
import 'package:serverpod_serialization/serverpod_serialization.dart' as _iss;
|
||||
|
||||
/// Base class for HLC timestamps.
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@
|
|||
// ignore_for_file: invalid_use_of_internal_member
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
|
||||
import 'package:serverpod_offline_sync/serverpod_offline_sync.dart'
|
||||
as _icw2tu00;
|
||||
import 'package:serverpod_serialization/serverpod_serialization.dart' as _iss;
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@
|
|||
// ignore_for_file: invalid_use_of_internal_member
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
|
||||
import 'package:serverpod_database/serverpod_database.dart' as _isd;
|
||||
import 'package:serverpod_offline_sync/serverpod_offline_sync.dart'
|
||||
as _icw2tu00;
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@
|
|||
// ignore_for_file: type_literal_in_constant_pattern
|
||||
// ignore_for_file: use_super_parameters
|
||||
// ignore_for_file: invalid_use_of_internal_member
|
||||
// ignore_for_file: dead_code, no_leading_underscores_for_library_prefixes
|
||||
// ignore_for_file: unnecessary_null_comparison
|
||||
// ignore_for_file: dead_code, unnecessary_null_comparison
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'package:serverpod_database/serverpod_database.dart' as _isd;
|
||||
import 'package:serverpod_offline_sync/serverpod_offline_sync.dart'
|
||||
as _icw2tu00;
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@
|
|||
// ignore_for_file: type_literal_in_constant_pattern
|
||||
// ignore_for_file: use_super_parameters
|
||||
// ignore_for_file: invalid_use_of_internal_member
|
||||
// ignore_for_file: dead_code, no_leading_underscores_for_library_prefixes
|
||||
// ignore_for_file: unnecessary_null_comparison
|
||||
// ignore_for_file: dead_code, unnecessary_null_comparison
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'package:serverpod_database/serverpod_database.dart' as _isd;
|
||||
import 'package:serverpod_offline_sync/serverpod_offline_sync.dart'
|
||||
as _icw2tu00;
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@
|
|||
// ignore_for_file: type_literal_in_constant_pattern
|
||||
// ignore_for_file: use_super_parameters
|
||||
// ignore_for_file: invalid_use_of_internal_member
|
||||
// ignore_for_file: dead_code, no_leading_underscores_for_library_prefixes
|
||||
// ignore_for_file: unnecessary_null_comparison
|
||||
// ignore_for_file: dead_code, unnecessary_null_comparison
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'package:serverpod_database/serverpod_database.dart' as _isd;
|
||||
import 'package:serverpod_offline_sync/serverpod_offline_sync.dart'
|
||||
as _icw2tu00;
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue