fix: Make the CrdtDatabase class ephemeral (#82)
This commit is contained in:
parent
de7e22d91a
commit
517abde4a1
2 changed files with 362 additions and 151 deletions
|
|
@ -1,12 +1,34 @@
|
|||
import 'package:serverpod/serverpod.dart';
|
||||
import 'package:serverpod_offline_sync_client/serverpod_offline_sync_client.dart';
|
||||
|
||||
/// The CRDT sync configured per [Serverpod] instance.
|
||||
///
|
||||
/// Keyed by the [Serverpod] instance so each pod owns its own [CrdtSync] (and
|
||||
/// the [CrdtDatabaseContext] it carries) instead of sharing a single
|
||||
/// process-wide singleton.
|
||||
final _crdtSyncByServerpod = Expando<CrdtSync>('crdtSync');
|
||||
|
||||
/// Intercepts each Serverpod session database with a CRDT-aware database once
|
||||
/// [CrdtSyncInitialize.initializeCrdtSync] has configured sync.
|
||||
///
|
||||
/// When sync has not been configured for the session's [Serverpod], the
|
||||
/// original [inner] database is returned unchanged.
|
||||
Database crdtDatabaseInterceptor(Session session, Database inner) {
|
||||
final crdtSync = _crdtSyncByServerpod[session.server.serverpod];
|
||||
return crdtSync?.wrapDatabase(inner) ?? inner;
|
||||
}
|
||||
|
||||
/// Extension methods for [Serverpod] to configure the CRDT sync on the server.
|
||||
extension CrdtSyncInitialize on Serverpod {
|
||||
/// Configures the endpoint with the given sync tables.
|
||||
/// Configures the CRDT sync with the given sync tables.
|
||||
///
|
||||
/// Must be called during server startup before any sync requests are made.
|
||||
/// Will override any previous initialization.
|
||||
/// Will override any previous initialization for this [Serverpod] instance.
|
||||
///
|
||||
/// The [Serverpod] instance must be constructed with [crdtDatabaseInterceptor]
|
||||
/// as its `databaseInterceptor`. Otherwise each session's [Session.db] stays a
|
||||
/// plain database and server-side ORM mutations on synced tables are not
|
||||
/// CRDT-tracked.
|
||||
///
|
||||
/// [syncBatchSize] controls the maximum number of merge changes carried by
|
||||
/// each sync stream chunk.
|
||||
|
|
@ -18,7 +40,7 @@ extension CrdtSyncInitialize on Serverpod {
|
|||
int syncBatchSize = CrdtSync.defaultSyncBatchSize,
|
||||
Duration continuousSyncInterval = CrdtSync.defaultContinuousSyncInterval,
|
||||
}) {
|
||||
CrdtSync.initialize(
|
||||
_crdtSyncByServerpod[this] = CrdtSync(
|
||||
syncTables: syncTables,
|
||||
serializationManager: serializationManager,
|
||||
syncBatchSize: syncBatchSize,
|
||||
|
|
@ -26,3 +48,15 @@ extension CrdtSyncInitialize on Serverpod {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Extension to access the CRDT sync for [Session] from the [Serverpod] instance.
|
||||
extension CrdtSessionExtension on Session {
|
||||
/// Returns the CRDT sync configured for this session.
|
||||
CrdtSync get crdt =>
|
||||
_crdtSyncByServerpod[server.serverpod] ??
|
||||
(throw StateError(
|
||||
'The CrdtSync has not been initialized for this Serverpod instance. '
|
||||
'Call pod.initializeCrdtSync(...) during server startup to configure '
|
||||
'the CRDT sync.',
|
||||
));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ import 'dart:async';
|
|||
import 'package:serverpod/serverpod.dart';
|
||||
import 'package:serverpod_offline_sync_client/serverpod_offline_sync_client.dart';
|
||||
|
||||
import '../business/crdt_sync.dart';
|
||||
|
||||
/// Endpoint for CRDT-based offline-first synchronization.
|
||||
class CrdtSyncEndpoint extends Endpoint {
|
||||
@override
|
||||
|
|
@ -14,7 +16,7 @@ class CrdtSyncEndpoint extends Endpoint {
|
|||
required Stream<CrdtSyncStreamEvent> changes,
|
||||
bool once = false,
|
||||
}) async* {
|
||||
yield* CrdtSync.instance.sync(
|
||||
yield* session.crdt.sync(
|
||||
session,
|
||||
userId: UuidValue.withValidation(session.authenticated!.userIdentifier),
|
||||
inbound: changes,
|
||||
|
|
|
|||
Loading…
Reference in a new issue