61 lines
1.9 KiB
Go
61 lines
1.9 KiB
Go
package probe
|
|
|
|
import (
|
|
"database/sql"
|
|
"errors"
|
|
)
|
|
|
|
// Item 7 B6: the notification engine's durable state lives in
|
|
// probe_setting, next to the roll-up watermark — the offline marks
|
|
// (one key per agent, "notify_down:<id>", the hub's down_since column
|
|
// in KV form so DeleteAgentData can strike exactly one agent's mark),
|
|
// the traffic steps already announced ("traffic_alerted", hub's key
|
|
// of the same name) and the expiry digest's last-sent date
|
|
// ("notify_expiry_sent"). The store stays the only writer of
|
|
// probe.db; the notify package reads and writes through here.
|
|
|
|
// StateGet reads one probe_setting value from the default store.
|
|
// ok is false when the key was never written; err is non-nil when no
|
|
// store is available, which callers treat as "skip this section"
|
|
// (the hub skips the traffic steps on a failed read rather than
|
|
// recording crossings it did not announce).
|
|
func StateGet(key string) (string, bool, error) {
|
|
st := Default()
|
|
if st == nil {
|
|
return "", false, errors.New("probe store unavailable")
|
|
}
|
|
return st.getState(key)
|
|
}
|
|
|
|
// StateSet writes one probe_setting value on the default store. An
|
|
// empty value deletes the key, so "cleared" and "never set" are the
|
|
// same state, as with the hub's down_since = 0.
|
|
func StateSet(key, value string) error {
|
|
st := Default()
|
|
if st == nil {
|
|
return errors.New("probe store unavailable")
|
|
}
|
|
return st.setState(key, value)
|
|
}
|
|
|
|
func (s *Store) getState(key string) (string, bool, error) {
|
|
var v string
|
|
err := s.db.QueryRow(`SELECT value FROM probe_setting WHERE key = ?`, key).Scan(&v)
|
|
if err == sql.ErrNoRows {
|
|
return "", false, nil
|
|
}
|
|
if err != nil {
|
|
return "", false, err
|
|
}
|
|
return v, true, nil
|
|
}
|
|
|
|
func (s *Store) setState(key, value string) error {
|
|
if value == "" {
|
|
_, err := s.db.Exec(`DELETE FROM probe_setting WHERE key = ?`, key)
|
|
return err
|
|
}
|
|
_, err := s.db.Exec(`INSERT OR REPLACE INTO probe_setting (key, value) VALUES (?, ?)`, key, value)
|
|
return err
|
|
}
|