Files
firebase/docs/adr/ADR-002-sdk-lifecycle-management.md

61 lines
2.7 KiB
Markdown
Raw Permalink Normal View History

# ADR-002: Firebase SDK Lifecycle Management via launcher.Component
**Status:** Accepted
**Date:** 2026-03-18
## Context
The firebase-admin-go SDK (`firebase.google.com/go/v4`) manages its own internal gRPC
connections, HTTP transports, and credential refresh cycles. The SDK entry point is a
`*firebase.App` instance, obtained via `fb.NewApp(ctx, config)`. Service-specific clients
(Auth, Firestore, etc.) are obtained from the App on demand via `app.Auth(ctx)` and
`app.Firestore(ctx)`.
Applications that construct the App outside of a lifecycle manager risk:
- Attempting to use the App before it is initialised.
- Not having a clear shutdown point (the SDK has no explicit `Close` method on `App`).
- Difficulty in testing components that depend on Firebase.
## Decision
`firebaseComponent` implements `launcher.Component` with three lifecycle methods:
- **`OnInit`**: Validates that `Config.ProjectID` is non-empty, then calls `fb.NewApp` to
create the App and store it in the struct. Returns an error if project ID is missing or
if the SDK fails to create the App. No network calls are made at this point — the SDK
is lazy about establishing connections.
- **`OnStart`**: Logs that the app is ready. Currently a no-op beyond logging; the SDK does
not require an explicit start call.
- **`OnStop`**: Logs shutdown. The firebase-admin-go SDK has no `Close` method on `*fb.App`.
Connections managed by the SDK (gRPC channels, HTTP transport) are closed by the Go
runtime's garbage collector when the App is no longer referenced. This is the accepted
behaviour of the SDK.
Consumers access the App via `App() *fb.App` (the `Provider` interface) and then obtain
service-specific clients themselves:
```go
authClient, err := component.App().Auth(ctx)
firestoreClient, err := component.App().Firestore(ctx)
```
This keeps the `firebase` module focused on App lifecycle without prescribing which Firebase
services consumers use.
## Consequences
**Positive:**
- Firebase App creation is integrated into the application startup sequence. Failures (bad
credentials, missing project ID) surface at startup, not at the first API call.
- The module is minimal: `OnInit` + `OnStart` + `OnStop` cover the full SDK lifecycle.
- Consumers are not limited to Auth; they can use any service the SDK supports.
**Negative:**
- There is no explicit SDK shutdown. The `OnStop` method is effectively a log-and-return.
In-flight requests to Firebase at shutdown time are handled by the SDK's own timeouts
and the context cancellation of callers, not by this module.
- `App()` returns `nil` before `OnInit` is called. Consumers must not call `App()` before
the lifecycle has been initialised (this is verified by `TestComponent_App_ReturnsNilBeforeInit`).