tryInitialiseStream method

Future<void> tryInitialiseStream()

Initializes the authentication state stream and data synchronization.

Sets up listeners for user authentication changes and manages the data stream.

Implementation

Future<void> tryInitialiseStream() async {
  _log.info('Initialising TurboAuthSyncService stream..');
  try {
    _userSubscription ??= FirebaseAuth.instance.userChanges().listen(
      (user) async {
        final userId = user?.uid;
        if (userId != null) {
          cachedUserId = userId;
          await onAuth?.call(user!);

          // Ensure auth token is ready and cached before starting Firestore stream
          // This ensures Firestore security rules have access to request.auth
          try {
            await _ensureAuthTokenReady(user!);
          } catch (error, stackTrace) {
            _log.error(
              'Failed to ensure auth token ready, proceeding anyway',
              error: error,
              stackTrace: stackTrace,
            );
            // Continue - let the stream attempt and retry mechanism handle failures
          }

          // Cancel any existing subscription before creating a new one
          // This ensures we start fresh with the token-ready user
          await _subscription?.cancel();
          _subscription = null;

          _subscription = (await stream(user!)).listen(
            (value) async {
              await onData(value, user);
            },
            onError: (Object error, StackTrace stackTrace) {
              _log.error(
                'Stream error occurred inside of stream!',
                error: error,
                stackTrace: stackTrace,
              );

              // Convert error to TurboFirestoreException if needed
              final exception = error is TFirestoreException
                  ? error
                  : TFirestoreException.fromFirestoreException(
                      error,
                      stackTrace,
                      operationType: TOperationType.stream,
                    );

              // Call onError handler
              onError(exception);

              _tryRetry();
            },
            onDone: () => onDone(_nrOfRetry, _maxNrOfRetry),
          );
        } else {
          cachedUserId = null;
          _clearTokenCache();
          await _subscription?.cancel();
          _subscription = null;
          await onData(null, null);
        }
      },
    );
  } catch (error, stack) {
    _log.error(
      'Stream error occurred while setting up stream!',
      error: error,
      stackTrace: stack,
    );

    // Convert error to TurboFirestoreException if needed
    final exception = error is TFirestoreException
        ? error
        : TFirestoreException.fromFirestoreException(
            error,
            stack,
            operationType: TOperationType.stream,
          );

    // Call onError handler
    onError(exception);

    _tryRetry();
  }
}