Review Date: February 11, 2025
Scope: Four services (bridge, server, location, decoder) and their internal packages
Reviewer: Automated Code Review
This report reviews the custom packages used across the four main services of the presence detection system. The codebase demonstrates a coherent architecture with clear separation of concerns, but several reliability issues, unused code paths, and refactoring opportunities were identified.
Overall Rating: 6.5/10
cmd/bridge/main.go)| Package | Purpose |
|---|---|
internal/pkg/common/appcontext |
Shared application state (beacon lookup, settings) |
internal/pkg/config |
Environment-based configuration |
internal/pkg/kafkaclient |
Kafka consumer/producer management |
internal/pkg/logger |
Structured logging setup |
internal/pkg/model |
Data structures |
cmd/server/main.go)| Package | Purpose |
|---|---|
internal/pkg/apiclient |
External API authentication and data fetching |
internal/pkg/common/appcontext |
Shared application state |
internal/pkg/config |
Configuration |
internal/pkg/controller |
HTTP handlers for REST API |
internal/pkg/database |
PostgreSQL connection (GORM) |
internal/pkg/kafkaclient |
Kafka management |
internal/pkg/logger |
Logging |
internal/pkg/model |
Data structures |
internal/pkg/service |
Business logic (location, parser) |
cmd/location/main.go)| Package | Purpose |
|---|---|
internal/pkg/common/appcontext |
Beacon state, settings |
internal/pkg/common/utils |
Distance calculation |
internal/pkg/config |
Configuration |
internal/pkg/kafkaclient |
Kafka management |
internal/pkg/logger |
Logging |
internal/pkg/model |
Data structures |
cmd/decoder/main.go)| Package | Purpose |
|---|---|
internal/pkg/common/appcontext |
Beacon events state |
internal/pkg/common/utils |
AD structure parsing, flag removal |
internal/pkg/config |
Configuration |
internal/pkg/kafkaclient |
Kafka management |
internal/pkg/logger |
Logging |
internal/pkg/model |
Data structures, parser registry |
Resolved
Location: cmd/location/main.go:99-101
Resolved
Location: cmd/server/main.go:60
configFile, err := os.Open("/app/cmd/server/config.json")
This path is Docker-specific and fails in local development or other deployment environments.
Fix: Use configurable path (e.g., CONFIG_PATH env var) or relative path based on executable location.
Locations:
internal/pkg/config/config.go: Default values include ClientSecret, HTTPPassword with production-like stringsinternal/pkg/apiclient/auth.go: GetToken() hardcodes credentials in formData (lines 21-24) instead of using cfg.HTTPClientID, cfg.ClientSecret, etc.HTTPClientID, ClientSecret, HTTPUsername, etc., but auth.go ignores themRecommendation: Wire config values into auth; never commit production credentials.
Location: internal/pkg/apiclient/updatedb.go:21-22
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
Recommendation: Use proper certificates or make this configurable for dev only.
Resolved
Resolved
Location: internal/pkg/bridge/mqtthandler/mqtthandler.go:75-83
Resolved
Location: cmd/server/main.go:31
var _ io.Writer = (*os.File)(nil)
Redundant; *os.File implements io.Writer. Safe to remove.
| Package | Notes |
|---|---|
github.com/boltdb/bolt |
Not imported in any source file |
github.com/yosssi/gmq |
Not imported |
github.com/gorilla/websocket |
Not imported |
Recommendation: Run go mod tidy after removing dead imports, or explicitly remove if kept for future use.
Location: internal/pkg/kafkaclient/consumer.go:20-23
On ReadMessage or Unmarshal error, the consumer logs and continues. For context.Canceled or partition errors, this may cause tight loops. Consider backoff or bounded retries.
Location: internal/pkg/kafkaclient/manager.go:101-111
GetReader and GetWriter hold the lock for the entire call including return. If the returned pointer is used after the lock is released, that’s fine, but the pattern holds the lock longer than necessary. Prefer:
func (m *KafkaManager) GetReader(topic string) *kafka.Reader {
m.kafkaReadersMap.KafkaReadersLock.RLock()
defer m.kafkaReadersMap.KafkaReadersLock.RUnlock()
return m.kafkaReadersMap.KafkaReaders[topic]
}
Use RLock for read-only access.
Location: internal/pkg/logger/logger.go
The opened file f is never closed. For long-running processes this is usually acceptable (log files stay open), but worth documenting. If multiple loggers are created, each holds a file descriptor.
Location: cmd/server/main.go:68
json.Unmarshal(b, &configs)
Error is ignored. Invalid JSON would leave configs empty without feedback.
log.Printf, fmt.Println, fmt.Printf, and slog.Info/ErrorseenW := 1.5, rssiW := 0.75mqtthandler inline while internal/pkg/bridge/mqtthandler exists with similar logicappcontext.BeaconExists for lookup; bridge version also sets adv.ID from lookupDecoder expects msg.ID values: "add", "delete", "update".
ParserDeleteController sends ID: "delete" ✓
ParserAddController sends ID: "add" ✓
ParserUpdateController sends ID: "update" ✓
Decoder’s update case re-registers; add and update are effectively the same.
AppState mixes safe and unsafe access:
beaconsLookup (map) has no mutex; AddBeaconToLookup, RemoveBeaconFromLookup, CleanLookup, BeaconExists are not thread-safeRecommendation: Protect beaconsLookup with sync.RWMutex or use sync.Map.
internal/pkg/bridge/mqtthandler and fix it, or remove the package and keep logic in bridge.formatMac in beacon_service.go could move to internal/pkg/common/utils for reuse and testing.| Directory | Status |
|---|---|
internal/app/_your_app_/ |
Placeholder with .keep; safe to remove or repurpose |
internal/pkg/model/.keep |
Placeholder; low impact |
web/app/, web/static/, web/template/ |
Empty except .keep; clarify if planned |
build/package/ |
Contains Dockerfiles; structure is reasonable |
| Priority | Action |
|---|---|
| P0 | Fix TrackerDelete "Delete" → "DELETE" |
| P0 | Guard empty BeaconMetrics in location |
| P1 | Make config.json path configurable |
| P1 | Fix beaconsLookup concurrency in AppState |
| P2 | Remove or integrate internal/pkg/redis and internal/pkg/bridge |
| P2 | Remove unused functions (ValidateRSSI, EventToBeaconService, etc.) |
| P2 | Replace hardcoded credentials in apiclient with config |
| P3 | Unify logging (slog), fix typos, extract constants |
| P3 | Run go mod tidy and drop unused dependencies |
| Category | Score | Notes |
|---|---|---|
| Architecture | 7/10 | Clear service boundaries; some shared-state issues |
| Reliability | 5/10 | Critical bugs (case mismatch, panic risk); error handling could improve |
| Security | 4/10 | Hardcoded credentials; disabled TLS verification |
| Maintainability | 6/10 | Duplication, magic numbers, inconsistent logging |
| Code Cleanliness | 5/10 | Unused code, dead packages, redundant assertions |
Overall: 6.5/10
The system has a solid foundation and sensible separation of concerns. Addressing the critical bugs, security issues, and removing dead code would materially improve reliability and maintainability.