docs: document SQLite storage for FCM registrations

Update README and .env.example for the SQLite database location, schema overview, backup/WAL notes, and clarify that JSON data is not migrated.
This commit is contained in:
Jose Olarte III
2026-07-24 20:52:38 +08:00
parent ddb969c26d
commit 06ec0f63e4
2 changed files with 52 additions and 3 deletions

View File

@@ -8,7 +8,8 @@ PORT=3003
# If unset, uses Application Default Credentials (e.g. GOOGLE_APPLICATION_CREDENTIALS).
# FIREBASE_SERVICE_ACCOUNT_JSON={"type":"service_account",...}
# Local persistence directory for registered FCM tokens (default: ./data)
# Directory for the SQLite FCM registration database (default: ./data).
# Creates fcm-tokens.sqlite (plus -wal/-shm while the process is running).
# FCM_TOKEN_DATA_DIR=./data
# Set to "test-local" to bypass ethr JWT expiry verification in local dev only.

View File

@@ -1,5 +1,7 @@
A lightweight Express service that schedules and sends Firebase Cloud Messaging (FCM) push notifications to wake up registered devices.
Device registrations are stored in a local **SQLite** database (not JSON).
## Dev
```bash
@@ -11,6 +13,8 @@ Here is one way to generate the contents: `cat your-downloaded-key.json | jq -c
Optionally set `ENDORSER_URL` if you are not using the default production Endorser API (`https://api.endorser.ch`).
Optionally set `FCM_TOKEN_DATA_DIR` if you want the SQLite database somewhere other than `./data`.
```bash
pnpm install
pnpm run dev
@@ -18,6 +22,8 @@ pnpm run dev
The server starts on `http://localhost:3003` (or the port in `PORT`). Hot-reloads on file changes.
On first use, the service creates `FCM_TOKEN_DATA_DIR` (default `./data`) and the SQLite file `fcm-tokens.sqlite` with the required schema.
### Authentication
`POST /notifications/register` and `POST /notifications/refresh` require a Bearer JWT. After local JWT verification, the service checks the token with Endorser (`GET /api/report/rateLimits` on `ENDORSER_URL`). Registration and refresh continue only if Endorser accepts the JWT.
@@ -26,6 +32,42 @@ The server starts on `http://localhost:3003` (or the port in `PORT`). Hot-reload
Set `NODE_ENV=test-local` in `.env` to bypass ethr JWT *expiry* verification during local development (this is separate from the `testMode` bypass above).
## Storage
### Database location
| Path | Description |
|---|---|
| `{FCM_TOKEN_DATA_DIR}/fcm-tokens.sqlite` | Primary SQLite database (default dir: `./data`) |
| `{FCM_TOKEN_DATA_DIR}/fcm-tokens.sqlite-wal` | WAL journal (present while the process is running) |
| `{FCM_TOKEN_DATA_DIR}/fcm-tokens.sqlite-shm` | Shared-memory file used with WAL mode |
`FCM_TOKEN_DATA_DIR` defaults to `./data` (relative to the process working directory). The `data/` directory is gitignored.
### Schema (high level)
Table `fcm_registrations` holds one row per registered device:
- Identity: `id`, `user_id`, `device_id`, `fcm_token`, `platform`
- Flags: `test_mode`
- Timestamps: `created_at`, `updated_at`, `last_notified_at`
Unique on `(user_id, device_id)`. Indexes also exist on `user_id`, `device_id`, `fcm_token`, and `(user_id, fcm_token)`.
The schema is created automatically on startup if the database or tables do not already exist.
### JSON → SQLite
There is **no automatic migration** from the old JSON file (`fcm-tokens.json`). That format is no longer used. If you still have a local `fcm-tokens.json` from earlier development, it is ignored; re-register devices or import data manually if you need it.
### Backup
Persist or back up the SQLite files under `FCM_TOKEN_DATA_DIR`:
1. Prefer stopping the service, then copy `fcm-tokens.sqlite` (and any `-wal` / `-shm` sidecars if present).
2. Or, while the service is running, copy **all three** files (`fcm-tokens.sqlite`, `-wal`, `-shm`) together so the backup stays consistent under WAL mode.
3. For Docker, mount a volume at the data directory (or set `FCM_TOKEN_DATA_DIR` to a mounted path) so registrations survive container recreation.
## Production
Runs TypeScript directly via `tsx` (no compile step).
@@ -35,13 +77,19 @@ pnpm install --prod
pnpm start
```
Ensure `FCM_TOKEN_DATA_DIR` points at a durable location (or accept the default `./data` next to the process cwd).
Or with Docker:
```bash
docker build --no-cache -t notify-wakeup-api:amd-$NOTIFY_WAKEUP_API_VERSION --platform linux/amd64 .
docker run --env-file notify-wakeup-api.env -p 3003:3003 notify-wakeup-api
docker run --env-file notify-wakeup-api.env -p 3003:3003 \
-v notify-wakeup-data:/app/data \
notify-wakeup-api
```
Mount a volume over `/app/data` (or whatever path you set with `FCM_TOKEN_DATA_DIR`) so the SQLite database is not lost when the container is replaced.
Required environment variables:
| Variable | Description |
@@ -49,4 +97,4 @@ Required environment variables:
| `FIREBASE_SERVICE_ACCOUNT_JSON` | Inline service account JSON (one line). If unset, falls back to Application Default Credentials. |
| `PORT` | HTTP port (default: `3003`). |
| `ENDORSER_URL` | Endorser API base URL used for auth checks on register/refresh (default: `https://api.endorser.ch`). |
| `FCM_TOKEN_DATA_DIR` | Directory for persisting registered FCM tokens (default: `./data`). |
| `FCM_TOKEN_DATA_DIR` | Directory for the SQLite database file `fcm-tokens.sqlite` (default: `./data`). |