77 "encoding/hex"
88 "github.com/google/uuid"
99 "github.com/icinga/icinga-go-library/backoff"
10- "github.com/icinga/icinga-go-library/com"
1110 "github.com/icinga/icinga-go-library/database"
1211 "github.com/icinga/icinga-go-library/logging"
1312 "github.com/icinga/icinga-go-library/retry"
@@ -19,6 +18,7 @@ import (
1918 "github.com/pkg/errors"
2019 "go.uber.org/zap"
2120 "sync"
21+ "sync/atomic"
2222 "time"
2323)
2424
@@ -35,7 +35,7 @@ type haState struct {
3535
3636// HA provides high availability and indicates whether a Takeover or Handover must be made.
3737type HA struct {
38- state com. Atomic [haState ]
38+ state atomic. Pointer [haState ]
3939 ctx context.Context
4040 cancelCtx context.CancelFunc
4141 instanceId types.Binary
@@ -71,6 +71,8 @@ func NewHA(ctx context.Context, db *database.DB, heartbeat *icingaredis.Heartbea
7171 done : make (chan struct {}),
7272 }
7373
74+ ha .state .Store (& haState {})
75+
7476 go ha .controller ()
7577
7678 return ha
@@ -121,7 +123,8 @@ func (h *HA) Takeover() chan string {
121123
122124// State returns the status quo.
123125func (h * HA ) State () (responsibleTsMilli int64 , responsible , otherResponsible bool ) {
124- state , _ := h .state .Load ()
126+ state := h .state .Load ()
127+
125128 return state .responsibleTsMilli , state .responsible , state .otherResponsible
126129}
127130
@@ -428,9 +431,12 @@ func (h *HA) realize(
428431
429432 h .signalTakeover (takeover )
430433 } else if otherResponsible {
431- if state , _ := h .state .Load (); ! state .otherResponsible {
432- state .otherResponsible = true
433- h .state .Store (state )
434+ if state := h .state .Load (); ! state .otherResponsible {
435+ // Dereference pointer to create a copy of the value it points to.
436+ // Ensures that any modifications do not directly affect the original data unless explicitly stored back.
437+ newState := * state
438+ newState .otherResponsible = true
439+ h .state .Store (& newState )
434440 }
435441 }
436442
@@ -496,7 +502,7 @@ func (h *HA) removeOldInstances(s *icingaredisv1.IcingaStatus, envId types.Binar
496502// signalHandover gives up HA.responsible and notifies the HA.Handover chan.
497503func (h * HA ) signalHandover (reason string ) {
498504 if h .responsible {
499- h .state .Store (haState {
505+ h .state .Store (& haState {
500506 responsibleTsMilli : time .Now ().UnixMilli (),
501507 responsible : false ,
502508 otherResponsible : false ,
@@ -514,7 +520,7 @@ func (h *HA) signalHandover(reason string) {
514520// signalTakeover claims HA.responsible and notifies the HA.Takeover chan.
515521func (h * HA ) signalTakeover (reason string ) {
516522 if ! h .responsible {
517- h .state .Store (haState {
523+ h .state .Store (& haState {
518524 responsibleTsMilli : time .Now ().UnixMilli (),
519525 responsible : true ,
520526 otherResponsible : false ,
0 commit comments