Background
The README and architecture diagram explicitly describe a Storage Adapter layer: "Extensible Storage Adapter — Plug in your preferred database (PostgreSQL, MongoDB, InfluxDB, etc.) for persisting historical tracks." The docker-compose.yml already provisions a PostgreSQL container. Currently, no storage code exists — location_update messages are broadcast and immediately forgotten.
Category: Enhancement / Missing Feature
Difficulty: Medium
Priority: High
Labels: enhancement, backend
Problem Statement
There is no persistence layer. Location updates are ephemeral — once broadcast, they are lost. The PostgreSQL service defined in docker-compose.yml is never connected to. Operators cannot query historical tracks or replay events.
Requirements
- Create
src/storage.js exporting a createStorageAdapter(config) factory.
- The adapter must implement an async
saveLocation(clientId, roomId, payload) method.
- Implement a
NullAdapter (no-op) used by default when DATABASE_URL is not set.
- Implement a
PostgresAdapter that writes to a locations table: id, client_id, room_id, latitude, longitude, altitude, accuracy, speed, recorded_at.
- Wire the adapter into
server.js: after a valid location_update is broadcast, call adapter.saveLocation(...) fire-and-forget with error logging.
- Add a SQL migration file at
db/migrations/001_create_locations.sql.
- Write unit tests for the
NullAdapter and a mocked PostgresAdapter.
Acceptance Criteria
Implementation Notes
Use the postgres npm package (not an ORM). Keep the adapter interface minimal — only saveLocation is required for this issue. Connection pooling and migration tooling are out of scope.
Fire-and-forget pattern:
adapter.saveLocation(clientId, roomId, msg.payload).catch((err) => {
logger.error('Failed to persist location', { clientId, error: err.message });
});
Files Likely to Change
src/storage.js (new)
src/server.js
src/index.js
db/migrations/001_create_locations.sql (new)
tests/storage.test.js (new)
Definition of Done
Location updates are persisted when DATABASE_URL is set. Service degrades gracefully when it is not. Both paths are tested.
Estimated Complexity
Medium — new module, clear interface, but requires async lifecycle management and error handling discipline.
Background
The README and architecture diagram explicitly describe a Storage Adapter layer: "Extensible Storage Adapter — Plug in your preferred database (PostgreSQL, MongoDB, InfluxDB, etc.) for persisting historical tracks." The
docker-compose.ymlalready provisions a PostgreSQL container. Currently, no storage code exists —location_updatemessages are broadcast and immediately forgotten.Category: Enhancement / Missing Feature
Difficulty: Medium
Priority: High
Labels: enhancement, backend
Problem Statement
There is no persistence layer. Location updates are ephemeral — once broadcast, they are lost. The PostgreSQL service defined in
docker-compose.ymlis never connected to. Operators cannot query historical tracks or replay events.Requirements
src/storage.jsexporting acreateStorageAdapter(config)factory.saveLocation(clientId, roomId, payload)method.NullAdapter(no-op) used by default whenDATABASE_URLis not set.PostgresAdapterthat writes to alocationstable:id,client_id,room_id,latitude,longitude,altitude,accuracy,speed,recorded_at.server.js: after a validlocation_updateis broadcast, calladapter.saveLocation(...)fire-and-forget with error logging.db/migrations/001_create_locations.sql.NullAdapterand a mockedPostgresAdapter.Acceptance Criteria
createStorageAdapter()with noDATABASE_URLreturns aNullAdapterwith a no-opsaveLocation.createStorageAdapter({ url: 'postgres://...' })returns aPostgresAdapter.location_updateprocessed byserver.jstriggersadapter.saveLocation().db/migrations/001_create_locations.sqlcreates thelocationstable.Implementation Notes
Use the
postgresnpm package (not an ORM). Keep the adapter interface minimal — onlysaveLocationis required for this issue. Connection pooling and migration tooling are out of scope.Fire-and-forget pattern:
Files Likely to Change
src/storage.js(new)src/server.jssrc/index.jsdb/migrations/001_create_locations.sql(new)tests/storage.test.js(new)Definition of Done
Location updates are persisted when
DATABASE_URLis set. Service degrades gracefully when it is not. Both paths are tested.Estimated Complexity
Medium — new module, clear interface, but requires async lifecycle management and error handling discipline.