- T1: SIGTERM/SIGINT → client.Disconnect(250) → os.Exit(0) - T2: 11 tests with miniredis mock (handleMessage, getEnv, parseInt, randomString) - T3: golang.org/x/net/context → stdlib context, math/rand → math/rand/v2 - T4: .golangci.yml + .github/workflows/ci.yml - T5: Redis SETEX error log includes key and memberID - Dockerfile: add git for go mod tidy
5.2 KiB
5.2 KiB
Repository Guidelines
Project Overview
MQTT presence service written in Go. Subscribes to an MQTT topic (presence), parses incoming messages (memberID;...), and stores presence data in Redis with a TTL. Purpose: real-time member presence tracking for the Backone platform (port of a Django/Python original).
Architecture & Data Flow
MQTT Broker ──publish──▶ MQTT Client (paho.mqtt)
│
▼
handleMessage()
- parse memberID from payload (split on ";")
- truncate memberID to 50 chars
- build JSON {mqtt, ts}
- SETEX to Redis key "presence:<memberID>"
│
▼
Redis
Single goroutine architecture. main() connects Redis, connects MQTT, subscribes on connect, then blocks forever (select {}). All message handling is synchronous in the MQTT callback.
Key Directories
backone-manage-go/
├── mqtt_presence_redis_go/ # ALL source code lives here
│ ├── mqtt_presence_redis_go.go # Single-file application (package main)
│ ├── go.mod / go.sum
│ └── Dockerfile
├── .gitignore
└── README.md
No subpackages, no internal/, no cmd/. The entire application is one .go file.
Development Commands
# Build
cd mqtt_presence_redis_go && go build -o mqtt_presence_redis_go mqtt_presence_redis_go.go
# Run locally (requires MQTT broker + Redis running)
cd mqtt_presence_redis_go && go run mqtt_presence_redis_go.go
# Docker build
cd mqtt_presence_redis_go && docker build -t mqtt-presence-redis-go .
# No Makefile, no CI pipeline, no lint config
Code Conventions & Common Patterns
Configuration
- All config via environment variables — no config files, no viper/yaml.
- Pattern:
getEnv("ENV_KEY", "default")helper at package level. - Env vars:
MQTT_HOST,MQTT_PORT,MQTT_USER,MQTT_PASS,MQTT_TOPIC_PRESENCE,MQTT_REDIS_HOST,MQTT_REDIS_PORT,MQTT_REDIS_DB,MQTT_REDIS_PREFIX,MQTT_REDIS_SETEX,MQTT_REDIS_PASSWORD.
Naming
- Package-level vars:
camelCase(e.g.mqttHost,redisPrefix). - Functions:
camelCase(e.g.handleMessage,getEnv,parseInt,randomString). - Constants: no
constblock used; inline defaults. - File naming:
<package_name>.gomatches module directory.
Error Handling
log.Fatalffor startup failures (Redis ping, MQTT connect).log.Printf+returnfor runtime errors (message handling).- No custom error types; no error wrapping.
Dependencies
github.com/eclipse/paho.mqtt.golang— MQTT clientgithub.com/go-redis/redis/v8— Redis clientgolang.org/x/net/context— context (stdlibcontextpreferred in Go 1.7+)
Patterns
- No interfaces, no DI, no dependency injection.
- No middleware, no routing — single topic subscription.
- No graceful shutdown handling (
select {}blocks forever). math/randfor client ID (notcrypto/rand) — acceptable for non-security use.- JSON marshaling via
map[string]interface{}— no typed struct for presence data.
Important Files
| File | Purpose |
|---|---|
mqtt_presence_redis_go/mqtt_presence_redis_go.go |
Entire application |
mqtt_presence_redis_go/go.mod |
Module: git.proit.id/dsutanto/backone-manage-go/mqtt_presence_redis_go, Go 1.24.3 |
mqtt_presence_redis_go/Dockerfile |
Multi-stage build: golang:1.24-alpine → alpine:3.20 |
Runtime/Tooling Preferences
- Go 1.24.3 (specified in go.mod and Dockerfile)
- No package manager beyond
go mod - No linter configured (no
.golangci.yml) - No formatter config (standard
gofmtassumed) - No CI/CD — deployment via Docker only
- Redis 8 client (
go-redis/v8) — requires Redis 6+ for SETEX - MQTT 3.1.1 via paho client
Testing & QA
- No tests exist. No
*_test.gofiles anywhere. - No test framework configured.
- No coverage tooling, no test scripts.
- If adding tests: use standard
testingpackage. Table-driven tests forhandleMessagemessage parsing logic. Mock Redis withminiredisorgo-redis/mock. Mock MQTT with a test broker or interface-based mock.
Key Observations for AI Assistants
- Single-file architecture — all changes go in
mqtt_presence_redis_go.go. No cross-file imports to track. - No tests — any refactor carries risk. Consider adding tests for
handleMessagebefore significant changes. - No graceful shutdown —
select {}means no signal handling, no MQTT disconnect on SIGTERM. Docker sends SIGTERM then SIGKILL. golang.org/x/net/contextis used instead of stdlibcontext— this is a legacy import; stdlibcontextis standard since Go 1.7.- Payload parsing is fragile: splits on
;, takes first element, truncates to 50 chars. No validation of payload format. - Redis key pattern:
presence:<memberID>with configurable prefix and TTL (default 86400s / 24h). - The comment about Django indicates this is a port — check Python original for behavioral reference if behavior questions arise.