handleAuthenticated method

  1. @override
Future<void> handleAuthenticated(
  1. String? uid
)
override

Public handler for auth state changes. Called when user authenticates.

This method can be passed to AuthService constructor for race-free initialization, ensuring callbacks are registered before Firebase listeners attach.

Usage

// Race-free initialization pattern:
final deviceService = DeviceServiceImpl();
final auth = AuthServiceImpl(
  firebaseApp: app,
  onAuthenticatedCallbacks: [deviceService.handleAuthenticated],
);
await deviceService.initialize(authService: auth);

Defensive Behavior

  • Returns immediately if uid is null (shouldn't happen in practice)
  • Logs a warning if called before initialize (indicates ordering bug)
  • Uses pending payload fallback for graceful degradation

Parameters

  • uid: The authenticated user's ID, or null on logout.

Implementation

@override
Future<void> handleAuthenticated(String? uid) async {
  // Defensive check - uid should never be null when called from AuthService,
  // but guard against unexpected edge cases.
  if (uid == null) {
    logw('DeviceService: handleAuthenticated called with null uid, skipping');
    return;
  }

  // Defensive check - warn if called before initialize().
  // This can happen if initialize() awaits are executed sequentially rather than
  // in parallel, allowing the auth callback to fire before all services are ready.
  // The pending payload system provides graceful degradation, but this indicates
  // an initialization ordering bug that should be fixed.
  if (_authService == null) {
    logw('DeviceService: handleAuthenticated called before initialize(). '
        'Device registration will use pending payload fallback. '
        'This indicates an initialization ordering issue - see Constraint 2 in plan.auth-race.md');
  }

  logd('DeviceService: handleAuthenticated called, uid=$uid');
  await _flushPendingPayload(bypassBackoff: true);
  await registerDevice();
}