|
- package decoder
-
- import (
- "context"
- "log/slog"
- "sync"
-
- "github.com/AFASystems/presence/internal/pkg/common/appcontext"
- "github.com/AFASystems/presence/internal/pkg/config"
- "github.com/AFASystems/presence/internal/pkg/decoder"
- "github.com/AFASystems/presence/internal/pkg/kafkaclient"
- "github.com/AFASystems/presence/internal/pkg/logger"
- "github.com/AFASystems/presence/internal/pkg/model"
- )
-
- // DecoderApp holds dependencies for the decoder service.
- type DecoderApp struct {
- Cfg *config.Config
- KafkaManager *kafkaclient.KafkaManager
- AppState *appcontext.AppState
- ParserRegistry *model.ParserRegistry
- ChRaw chan model.BeaconAdvertisement
- ChParser chan model.KafkaParser
- Cleanup func()
- wg sync.WaitGroup
- }
-
- // New creates a DecoderApp with Kafka readers (rawbeacons, parser) and writer (alertbeacons).
- func New(cfg *config.Config) (*DecoderApp, error) {
- appState := appcontext.NewAppState()
- kafkaManager := kafkaclient.InitKafkaManager()
-
- srvLogger, cleanup := logger.CreateLogger("decoder.log")
- slog.SetDefault(srvLogger)
-
- readerTopics := []string{"rawbeacons", "parser"}
- writerTopics := []string{"alertbeacons"}
- kafkaManager.PopulateKafkaManager(cfg.KafkaURL, "decoder", readerTopics)
- kafkaManager.PopulateKafkaManager(cfg.KafkaURL, "", writerTopics)
- slog.Info("decoder service initialized", "readers", readerTopics, "writers", writerTopics)
-
- registry := &model.ParserRegistry{
- ParserList: make(map[string]model.BeaconParser),
- }
-
- return &DecoderApp{
- Cfg: cfg,
- KafkaManager: kafkaManager,
- AppState: appState,
- ParserRegistry: registry,
- ChRaw: make(chan model.BeaconAdvertisement, config.LARGE_CHANNEL_SIZE),
- ChParser: make(chan model.KafkaParser, config.SMALL_CHANNEL_SIZE),
- Cleanup: cleanup,
- }, nil
- }
-
- // Run starts Kafka consumers and the event loop until ctx is cancelled.
- func (a *DecoderApp) Run(ctx context.Context) {
- a.wg.Add(2)
- go kafkaclient.Consume(a.KafkaManager.GetReader("rawbeacons"), a.ChRaw, ctx, &a.wg)
- go kafkaclient.Consume(a.KafkaManager.GetReader("parser"), a.ChParser, ctx, &a.wg)
-
- for {
- select {
- case <-ctx.Done():
- return
- case msg := <-a.ChRaw:
- decoder.ProcessIncoming(msg, a.AppState, a.KafkaManager.GetWriter("alertbeacons"), a.ParserRegistry)
- case msg := <-a.ChParser:
- switch msg.ID {
- case "add":
- a.ParserRegistry.Register(msg.Config.Name, msg.Config)
- case "delete":
- a.ParserRegistry.Unregister(msg.Name)
- case "update":
- a.ParserRegistry.Register(msg.Config.Name, msg.Config)
- }
- }
- }
- }
-
- // Shutdown waits for consumers and cleans up.
- func (a *DecoderApp) Shutdown() {
- a.wg.Wait()
- a.KafkaManager.CleanKafkaReaders()
- a.KafkaManager.CleanKafkaWriters()
- if a.Cleanup != nil {
- a.Cleanup()
- }
- slog.Info("decoder service shutdown complete")
- }
|