Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 
 

246 wiersze
6.1 KiB

  1. package appcontext
  2. import (
  3. "fmt"
  4. "log/slog"
  5. "os"
  6. "sync"
  7. "time"
  8. "github.com/AFASystems/presence/internal/pkg/kafkaclient"
  9. "github.com/mitchellh/mapstructure"
  10. )
  11. // AppState provides centralized access to application state
  12. type AppState struct {
  13. beacons BeaconsList
  14. settings Settings
  15. beaconEvents BeaconEventList
  16. beaconsLookup BeaconsLookup
  17. health Health
  18. startTime time.Time
  19. mu sync.RWMutex
  20. }
  21. func getEnv(key, def string) string {
  22. if v := os.Getenv(key); v != "" {
  23. return v
  24. }
  25. return def
  26. }
  27. // NewAppState creates a new application context AppState with default values
  28. func NewAppState() *AppState {
  29. return &AppState{
  30. startTime: time.Now(),
  31. beacons: BeaconsList{
  32. Beacons: make(map[string]Beacon),
  33. },
  34. settings: Settings{
  35. ID: 1,
  36. CurrentAlgorithm: getEnv("ALGORITHM", "filter"),
  37. LocationConfidence: 4,
  38. LastSeenThreshold: 15,
  39. BeaconMetricSize: 30,
  40. HASendInterval: 5,
  41. HASendChangesOnly: false,
  42. RSSIEnforceThreshold: false,
  43. RSSIMinThreshold: 100,
  44. },
  45. beaconEvents: BeaconEventList{
  46. Beacons: make(map[string]BeaconEvent),
  47. },
  48. beaconsLookup: BeaconsLookup{
  49. Lookup: make(map[string]string),
  50. },
  51. health: Health{
  52. Location: LocationHealth{
  53. BaseHealth: BaseHealth{
  54. Uptime: 0,
  55. ActiveReaders: []string{},
  56. ActiveWriters: []string{},
  57. ActiveBeacons: []string{},
  58. },
  59. },
  60. Decoder: DecoderHealth{
  61. BaseHealth: BaseHealth{
  62. Uptime: 0,
  63. ActiveReaders: []string{},
  64. ActiveWriters: []string{},
  65. ActiveBeacons: []string{},
  66. },
  67. },
  68. Bridge: BridgeHealth{
  69. BaseHealth: BaseHealth{
  70. Uptime: 0,
  71. ActiveReaders: []string{},
  72. ActiveWriters: []string{},
  73. ActiveBeacons: []string{},
  74. },
  75. },
  76. },
  77. }
  78. }
  79. func (m *AppState) GetHealth() Health {
  80. m.mu.RLock()
  81. defer m.mu.RUnlock()
  82. return m.health
  83. }
  84. func (m *AppState) UpdateLocationHealth(h LocationHealth) {
  85. m.mu.Lock()
  86. m.health.Location = h
  87. m.mu.Unlock()
  88. }
  89. func (m *AppState) UpdateDecoderHealth(h DecoderHealth) {
  90. m.mu.Lock()
  91. m.health.Decoder = h
  92. m.mu.Unlock()
  93. }
  94. func (m *AppState) UpdateBridgeHealth(h BridgeHealth) {
  95. m.mu.Lock()
  96. m.health.Bridge = h
  97. m.mu.Unlock()
  98. }
  99. func (m *AppState) GetLocationHealth(k *kafkaclient.KafkaManager) ([]byte, error) {
  100. m.health.Location.GetUptime(m.startTime)
  101. m.health.Location.GetActiveReaders(k)
  102. m.health.Location.GetActiveWriters(k)
  103. m.health.Location.GetActiveBeacons(m)
  104. return m.health.Location.Marshal()
  105. }
  106. func (m *AppState) GetDecoderHealth(k *kafkaclient.KafkaManager) ([]byte, error) {
  107. m.health.Decoder.GetUptime(m.startTime)
  108. m.health.Decoder.GetActiveReaders(k)
  109. m.health.Decoder.GetActiveWriters(k)
  110. m.health.Decoder.GetActiveBeacons(m)
  111. return m.health.Decoder.Marshal()
  112. }
  113. func (m *AppState) GetBridgeHealth(k *kafkaclient.KafkaManager) ([]byte, error) {
  114. m.health.Bridge.GetUptime(m.startTime)
  115. m.health.Bridge.GetActiveReaders(k)
  116. m.health.Bridge.GetActiveWriters(k)
  117. m.health.Bridge.GetActiveBeacons(m)
  118. return m.health.Bridge.Marshal()
  119. }
  120. // GetBeacons returns thread-safe access to beacons list
  121. func (m *AppState) GetBeacons() *BeaconsList {
  122. m.beacons.Lock.RLock()
  123. defer m.beacons.Lock.RUnlock()
  124. return &m.beacons
  125. }
  126. // GetSettings returns thread-safe access to settings
  127. func (m *AppState) GetSettings() *Settings {
  128. return &m.settings
  129. }
  130. // GetBeaconEvents returns thread-safe access to beacon events
  131. func (m *AppState) GetBeaconEvents() *BeaconEventList {
  132. m.beaconEvents.Lock.RLock()
  133. defer m.beaconEvents.Lock.RUnlock()
  134. return &m.beaconEvents
  135. }
  136. // AddBeaconToLookup adds a beacon ID to the lookup map
  137. func (m *AppState) AddBeaconToLookup(id, value string) {
  138. m.beaconsLookup.Lock.Lock()
  139. m.beaconsLookup.Lookup[id] = value
  140. m.beaconsLookup.Lock.Unlock()
  141. }
  142. // RemoveBeaconFromLookup removes a beacon ID from the lookup map
  143. func (m *AppState) RemoveBeaconFromLookup(id string) {
  144. m.beaconsLookup.Lock.Lock()
  145. delete(m.beaconsLookup.Lookup, id)
  146. m.beaconsLookup.Lock.Unlock()
  147. }
  148. func (m *AppState) CleanLookup() {
  149. m.beaconsLookup.Lock.Lock()
  150. clear(m.beaconsLookup.Lookup)
  151. m.beaconsLookup.Lock.Unlock()
  152. }
  153. // BeaconExists checks if a beacon exists in the lookup
  154. func (m *AppState) BeaconExists(id string) (string, bool) {
  155. m.beaconsLookup.Lock.RLock()
  156. defer m.beaconsLookup.Lock.RUnlock()
  157. val, exists := m.beaconsLookup.Lookup[id]
  158. return val, exists
  159. }
  160. // GetBeacon returns a beacon by ID (thread-safe)
  161. func (m *AppState) GetBeacon(id string) (Beacon, bool) {
  162. m.beacons.Lock.RLock()
  163. defer m.beacons.Lock.RUnlock()
  164. beacon, exists := m.beacons.Beacons[id]
  165. return beacon, exists
  166. }
  167. // UpdateBeacon updates a beacon in the list (thread-safe)
  168. func (m *AppState) UpdateBeacon(id string, beacon Beacon) {
  169. m.beacons.Lock.Lock()
  170. defer m.beacons.Lock.Unlock()
  171. m.beacons.Beacons[id] = beacon
  172. }
  173. // GetBeaconEvent returns a beacon event by ID (thread-safe)
  174. func (m *AppState) GetBeaconEvent(id string) (BeaconEvent, bool) {
  175. m.beaconEvents.Lock.RLock()
  176. defer m.beaconEvents.Lock.RUnlock()
  177. event, exists := m.beaconEvents.Beacons[id]
  178. return event, exists
  179. }
  180. // UpdateBeaconEvent updates a beacon event in the list (thread-safe)
  181. func (m *AppState) UpdateBeaconEvent(id string, event BeaconEvent) {
  182. m.beaconEvents.Lock.Lock()
  183. defer m.beaconEvents.Lock.Unlock()
  184. m.beaconEvents.Beacons[id] = event
  185. }
  186. // GetAllBeacons returns a copy of all beacons
  187. func (m *AppState) GetAllBeacons() map[string]Beacon {
  188. m.beacons.Lock.RLock()
  189. defer m.beacons.Lock.RUnlock()
  190. beacons := make(map[string]Beacon)
  191. for id, beacon := range m.beacons.Beacons {
  192. beacons[id] = beacon
  193. }
  194. return beacons
  195. }
  196. // GetBeaconCount returns the number of tracked beacons
  197. func (m *AppState) GetBeaconCount() int {
  198. m.beacons.Lock.RLock()
  199. defer m.beacons.Lock.RUnlock()
  200. return len(m.beacons.Beacons)
  201. }
  202. // GetSettingsValue returns current settings as a value
  203. func (m *AppState) GetSettingsValue() Settings {
  204. return m.settings
  205. }
  206. // UpdateSettings updates the system settings (thread-safe)
  207. func (m *AppState) UpdateSettings(settings map[string]any) {
  208. if err := mapstructure.Decode(settings, &m.settings); err != nil {
  209. msg := fmt.Sprintf("Error in persisting settings: %v", err)
  210. slog.Error(msg)
  211. }
  212. }