Documentation
¶
Overview ¶
Command sensor-service is the go-codex flagship example: a small but complete sensor-readings service structured as a real project, with each concern in its own package:
domain/ — Layer 1+2: models, codecs, field factories, constraints,
pure business rules (validated-config factories included)
pipeline/ — business logic: forge functions + stream topology,
parameterized by the consumer-defined Store interface
ioports/ — the service's complete IO surface: protocol-agnostic
ports (EventPattern/SQLPattern/FilePattern) + REST routes
observability/ — cross-cutting CountingObserver (fanned out with a
LoggingObserver, stored once in the context)
adapters/ — infrastructure edge: mock MQTT client, SQL ReadingStore,
HTTP handler factories
db/ — sqlc-generated queries + goose migrations
main.go — wiring ONLY: config, DB, observer, adapter binds, server
demo.go — the runnable demo scenario
Import direction is strictly acyclic: main → {ioports, pipeline, adapters, observability, domain}; pipeline → domain; ioports → domain; adapters → domain; domain → nothing internal but db.
What it demonstrates ¶
- ports.SourcePort + adaptermqtt.SubscribeAdapter — MQTT ingestion wired to a protocol-agnostic SourcePort; pipeline code has no MQTT import. The topic + params are declared once via ports.EventPattern on the port itself (ioports.Sensors); ports.EventHandle derives the *ChannelHandle for the adapter — no separate events.NewChannel/Register step needed.
- ports.SinkPort + adaptermqtt.PublishAdapter — MQTT alert publishing wired to a SinkPort (ioports.Alerts); supports fan-out to additional sinks.
- ports.IOPort + sqladapter.QueryEachAdapter — persistence as an explicit intermediate IO step (ioports.Readings): the pipeline's forge function stays PURE (payload → insert params); the save happens through the port, whose adapter is chosen here. Table/Op metadata declared once via ports.SQLPattern.
- ports.ToolPort + nethttp.PipelineAdapter — GET /sensors/{sensorID}/readings (ioports.HistoryTool, ports.RESTPattern): the tool pipeline Connects through ioports.History (IOPort, SQLPattern) — REST layer and database never meet directly.
- ports.SinkPort + fileadapter.DrainWriteFileAdapter — POST /export (ioports.ExportTool): query through ioports.ExportQuery (SQLPattern), write the snapshot through ioports.NewExportsPort's ports.FilePattern ({exportID}.json); the response path comes from the SAME declaration via ports.FileHandle.BuildPath.
- nethttp.HandlerLatest — reactive cache endpoint; GET /readings/latest returns the most recently saved reading without querying the DB.
- Validated-config factory pattern — main() loads domain.AlertConfig once via format.FromEnv (APP_ALERT_THRESHOLD, default 50.0); the pipeline functions close over the typed, validated config (see domain.NewShouldAlert).
- One stats.NewFanout observer across HTTP, MQTT, SQL, file, and stream.
Run:
go run ./examples/sensor-service APP_ALERT_THRESHOLD=90 go run ./examples/sensor-service
Directories
¶
| Path | Synopsis |
|---|---|
|
Package adapters holds the sensor service's infrastructure edge: the mock MQTT client used for the demo, the SQL-backed ReadingStore, and the HTTP handler factories.
|
Package adapters holds the sensor service's infrastructure edge: the mock MQTT client used for the demo, the SQL-backed ReadingStore, and the HTTP handler factories. |
|
Package domain is Layer 1 + Layer 2 of the sensor service: models, codecs, and pure business rules.
|
Package domain is Layer 1 + Layer 2 of the sensor service: models, codecs, and pure business rules. |
|
Package ioports declares every IO boundary of the sensor service as a protocol-agnostic port or route — the service's complete IO surface, readable as a compact spec, with ZERO adapter imports.
|
Package ioports declares every IO boundary of the sensor service as a protocol-agnostic port or route — the service's complete IO surface, readable as a compact spec, with ZERO adapter imports. |
|
Package observability holds the cross-cutting observer for the sensor service.
|
Package observability holds the cross-cutting observer for the sensor service. |
|
Package pipeline is the sensor service's business logic layer: forge functions and the stream topology.
|
Package pipeline is the sensor service's business logic layer: forge functions and the stream topology. |
Click to show internal directories.
Click to hide internal directories.