d4a6d8f713
Replaces the placeholder Metrics shim with a prom-client implementation in src/observability/metrics.ts: all 10 Phase 1 metrics from the wiki spec, plus nodejs_* defaults. Exposes /metrics, /healthz, /readyz over node:http on METRICS_PORT (9090); /readyz returns 503 when Redis status is not 'ready' or the TCP listener isn't bound. The Metrics interface in src/core/types.ts is unchanged — adapter call sites continue to use the same inc/observe shape. Only main.ts sees the extended type that adds serializeMetrics(). Side effects: - Dockerfile re-enables HEALTHCHECK pointing at /readyz, and EXPOSE 9090. - frame-ingested log downgraded back to debug now that teltonika_records_published_total is scrapeable. - 19 new unit tests covering exposition format, all metric types, and every HTTP endpoint path. Total now 98 passing. Note: deploy/compose.yaml still does not expose 9090 — separate decision about how Prometheus reaches the service (host port vs. internal scraper on the same Docker network).
84 lines
3.6 KiB
Markdown
84 lines
3.6 KiB
Markdown
# tcp-ingestion
|
|
|
|
Node.js TCP server that accepts persistent connections from Teltonika GPS hardware (FMB/FMC/FMM/FMU series), parses Codec 8, 8E, and 16 AVL frames, and publishes normalized `Position` records to a Redis Stream for downstream consumers.
|
|
|
|
For the full architectural specification see `../docs/wiki/`. For the work plan and task status see `.planning/ROADMAP.md`.
|
|
|
|
---
|
|
|
|
## Quick start (local)
|
|
|
|
**Prerequisites:** Node.js 22+, pnpm, a local Redis instance (or use compose below).
|
|
|
|
```bash
|
|
git clone <repo-url>
|
|
cd tcp-ingestion
|
|
pnpm install
|
|
cp .env.example .env
|
|
# Edit .env — at minimum set REDIS_URL
|
|
pnpm dev
|
|
```
|
|
|
|
`pnpm dev` uses `tsx watch` for hot-reload during development. The server listens on `TELTONIKA_PORT` (default `5027`).
|
|
|
|
---
|
|
|
|
## Test the Docker build locally
|
|
|
|
`compose.dev.yaml` builds the image from source and runs it next to a Redis container. Useful for verifying Dockerfile changes before pushing:
|
|
|
|
```bash
|
|
docker compose -f compose.dev.yaml up --build
|
|
```
|
|
|
|
For day-to-day development, prefer `pnpm dev` directly — it has hot reload and faster iteration.
|
|
|
|
---
|
|
|
|
## Production / stage deployment
|
|
|
|
This service is **not** deployed standalone. It runs as part of the platform stack defined in the [`deploy/`](https://git.dev.microservices.al/trm/deploy) repo, which Portainer pulls and runs on the stage and production hosts.
|
|
|
|
The image itself is published to `git.dev.microservices.al/trm/tcp-ingestion:main` on every push to `main` (see CI behavior below). The `deploy/` repo's `compose.yaml` references that image; updates flow through there, not through this repo.
|
|
|
|
To pin a specific commit in production, set `TCP_INGESTION_TAG=<sha>` in the deploy stack's environment variables.
|
|
|
|
---
|
|
|
|
## Environment variables
|
|
|
|
See `.env.example` for all variables with descriptions and defaults. The only required variable is `REDIS_URL` — all others have sensible defaults.
|
|
|
|
---
|
|
|
|
## Tests
|
|
|
|
- `pnpm test` — unit tests only. Fast (~2s), no external dependencies. **This is what CI runs.**
|
|
- `pnpm test:integration` — integration tests that need Docker (testcontainers spins up a real Redis). **Opt-in.** Run locally before changes to the Redis publisher, or in a separate CI job with Docker access.
|
|
|
|
Integration tests live in `test/**/*.integration.test.ts` and are excluded from the default run by `vitest.config.ts`.
|
|
|
|
---
|
|
|
|
## CI behavior
|
|
|
|
Gitea Actions workflow is at `.gitea/workflows/build.yml`.
|
|
|
|
- **Push to `main`** (only when `src/`, `test/`, build config, Dockerfile, or the workflow file itself changes): runs `typecheck`, `lint`, `test` (unit tests only), then builds and pushes the Docker image tagged `:main`. Auto-deploys to stage if a Portainer webhook is configured.
|
|
- **Manual trigger** (`workflow_dispatch`): same flow, run on demand.
|
|
|
|
Integration tests are not run in CI — they need Docker access on the runner, which we don't currently configure. Run them locally as needed.
|
|
|
|
The workflow uses `secrets.REGISTRY_USERNAME` and `secrets.REGISTRY_PASSWORD` for the Gitea registry login — these must be configured in the repo's (or org's) Actions secrets.
|
|
|
|
---
|
|
|
|
## Pilot deployment notes
|
|
|
|
This service is running in pilot form. The following tasks are **paused** — they are not missing by accident, they are deferred by design to get onto real Teltonika hardware first:
|
|
|
|
- **Production hardening (task 1.12):** Graceful shutdown is a functional stub; uncaught-exception handling is minimal.
|
|
- **Device authority (task 1.13):** `AllowAllAuthority` is active — every IMEI is accepted. `STRICT_DEVICE_AUTH=true` is wired but the Redis allow-list refresher is not yet implemented.
|
|
|
|
See `.planning/ROADMAP.md` for the resume triggers for each deferred task.
|