connect method

Future<void> connect({
  1. required PowerSyncBackendConnector connector,
  2. SyncOptions? options,
  3. @Deprecated('Use SyncOptions.crudThrottleTime instead') Duration? crudThrottleTime,
  4. Map<String, dynamic>? params,
})
inherited

Connect to the PowerSync service, and keep the databases in sync.

The connection is automatically re-opened if it fails for any reason.

To set sync parameters used in your sync rules (if any), use SyncOptions.params. SyncOptions can also be used to tune the behavior of the sync client, see that class for more information.

Status changes are reported on statusStream.

Implementation

Future<void> connect({
  required PowerSyncBackendConnector connector,
  SyncOptions? options,
  @Deprecated('Use SyncOptions.crudThrottleTime instead')
  Duration? crudThrottleTime,
  Map<String, dynamic>? params,
}) async {
  // The initialization process acquires a sync connect lock (through
  // updateSchema), so ensure the database is ready before we try to acquire
  // the lock for the connection.
  await initialize();

  final resolvedOptions = ResolvedSyncOptions.resolve(
    options,
    crudThrottleTime: crudThrottleTime,
    // ignore: deprecated_member_use_from_same_package
    retryDelay: retryDelay,
    params: params,
  );

  // ignore: deprecated_member_use_from_same_package
  clientParams = params;
  var thisConnectAborter = AbortController();
  final zone = Zone.current;

  late void Function() retryHandler;

  Future<void> connectWithSyncLock() async {
    // Ensure there has not been a subsequent connect() call installing a new
    // sync client.
    assert(identical(_abortActiveSync, thisConnectAborter));
    assert(!thisConnectAborter.aborted);

    await connectInternal(
      connector: connector,
      options: resolvedOptions,
      abort: thisConnectAborter,
      // Run follow-up async tasks in the parent zone, a new one is introduced
      // while we hold the lock (and async tasks won't hold the sync lock).
      asyncWorkZone: zone,
    );

    thisConnectAborter.onCompletion.whenComplete(retryHandler);
  }

  // If the sync encounters a failure without being aborted, retry
  retryHandler = Zone.current.bindCallback(() async {
    _activeGroup.syncConnectMutex.lock(() async {
      // Is this still supposed to be active? (abort is only called within
      // mutex)
      if (!thisConnectAborter.aborted) {
        // We only change _abortActiveSync after disconnecting, which resets
        // the abort controller.
        assert(identical(_abortActiveSync, thisConnectAborter));

        // We need a new abort controller for this attempt
        _abortActiveSync = thisConnectAborter = AbortController();

        logger.warning('Sync client failed, retrying...');
        await connectWithSyncLock();
      }
    });
  });

  await _activeGroup.syncConnectMutex.lock(() async {
    // Disconnect a previous sync client, if one is active.
    await _abortCurrentSync();
    assert(_abortActiveSync == null);

    // Install the abort controller for this particular connect call, allowing
    // it to be disconnected.
    _abortActiveSync = thisConnectAborter;
    await connectWithSyncLock();
  });
}