選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 
 

101 行
3.1 KiB

  1. package location
  2. import (
  3. "context"
  4. "fmt"
  5. "log/slog"
  6. "sync"
  7. "time"
  8. "github.com/AFASystems/presence/internal/pkg/common/appcontext"
  9. "github.com/AFASystems/presence/internal/pkg/config"
  10. "github.com/AFASystems/presence/internal/pkg/kafkaclient"
  11. "github.com/AFASystems/presence/internal/pkg/logger"
  12. pkglocation "github.com/AFASystems/presence/internal/pkg/location"
  13. "github.com/AFASystems/presence/internal/pkg/model"
  14. )
  15. // LocationApp holds dependencies for the location service.
  16. type LocationApp struct {
  17. Cfg *config.Config
  18. KafkaManager *kafkaclient.KafkaManager
  19. AppState *appcontext.AppState
  20. Inferencer pkglocation.Inferencer
  21. ChRaw chan model.BeaconAdvertisement
  22. ChSettings chan map[string]any
  23. Cleanup func()
  24. wg sync.WaitGroup
  25. }
  26. // New creates a LocationApp with Kafka readers (rawbeacons, settings) and writer (locevents).
  27. func New(cfg *config.Config) (*LocationApp, error) {
  28. appState := appcontext.NewAppState()
  29. kafkaManager := kafkaclient.InitKafkaManager()
  30. srvLogger, cleanup := logger.CreateLogger("location.log")
  31. slog.SetDefault(srvLogger)
  32. readerTopics := []string{"rawbeacons", "settings"}
  33. writerTopics := []string{"locevents"}
  34. kafkaManager.PopulateKafkaManager(cfg.KafkaURL, "location", readerTopics)
  35. kafkaManager.PopulateKafkaManager(cfg.KafkaURL, "", writerTopics)
  36. slog.Info("location service initialized", "readers", readerTopics, "writers", writerTopics)
  37. return &LocationApp{
  38. Cfg: cfg,
  39. KafkaManager: kafkaManager,
  40. AppState: appState,
  41. Inferencer: pkglocation.NewDefaultInferencer(cfg.TLSInsecureSkipVerify),
  42. ChRaw: make(chan model.BeaconAdvertisement, config.LARGE_CHANNEL_SIZE),
  43. ChSettings: make(chan map[string]any, config.SMALL_CHANNEL_SIZE),
  44. Cleanup: cleanup,
  45. }, nil
  46. }
  47. // Run starts consumers and the event loop until ctx is cancelled.
  48. func (a *LocationApp) Run(ctx context.Context) {
  49. a.wg.Add(2)
  50. go kafkaclient.Consume(a.KafkaManager.GetReader("rawbeacons"), a.ChRaw, ctx, &a.wg)
  51. go kafkaclient.Consume(a.KafkaManager.GetReader("settings"), a.ChSettings, ctx, &a.wg)
  52. locTicker := time.NewTicker(config.SMALL_TICKER_INTERVAL)
  53. defer locTicker.Stop()
  54. for {
  55. select {
  56. case <-ctx.Done():
  57. return
  58. case <-locTicker.C:
  59. settings := a.AppState.GetSettings()
  60. slog.Info("location tick", "settings", fmt.Sprintf("%+v", settings))
  61. switch settings.CurrentAlgorithm {
  62. case "filter":
  63. pkglocation.GetLikelyLocations(a.AppState, a.KafkaManager.GetWriter("locevents"))
  64. case "ai":
  65. inferred, err := a.Inferencer.Infer(ctx, a.Cfg)
  66. if err != nil {
  67. slog.Error("AI inference", "err", err)
  68. continue
  69. }
  70. slog.Info("AI algorithm", "count", inferred.Count, "items", len(inferred.Items))
  71. }
  72. case msg := <-a.ChRaw:
  73. pkglocation.AssignBeaconToList(msg, a.AppState)
  74. case msg := <-a.ChSettings:
  75. slog.Info("settings update", "msg", msg)
  76. a.AppState.UpdateSettings(msg)
  77. }
  78. }
  79. }
  80. // Shutdown waits for consumers and cleans up Kafka and logger.
  81. func (a *LocationApp) Shutdown() {
  82. a.wg.Wait()
  83. a.KafkaManager.CleanKafkaReaders()
  84. a.KafkaManager.CleanKafkaWriters()
  85. if a.Cleanup != nil {
  86. a.Cleanup()
  87. }
  88. slog.Info("location service shutdown complete")
  89. }