Documentation
¶
Overview ¶
Package storage persists GopherTrunk's runtime data to disk.
The default backend is SQLite via the pure-Go `modernc.org/sqlite` driver — CGO_ENABLED=0 stays true across the daemon and the daemon cross-compiles to linux/arm64 without toolchain gymnastics.
Layout:
sqlite.go Open + schema migrations. One-shot at startup.
calllog.go CallLog: subscribes to events.KindCallStart /
KindCallEnd from the trunking engine, writes rows
keyed by (device serial, started_at).
retention.go Background sweeper that deletes DB rows + the WAV /
raw files written by internal/voice older than a
configurable cutoff.
The API's /api/v1/calls/history endpoint reads through the `History` query helpers exposed here. There is no gRPC call-log service today (history is REST only).
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type CallLog ¶
type CallLog struct {
// contains filtered or unexported fields
}
CallLog persists trunking calls to the SQLite call_log table by subscribing to events.KindCallStart and events.KindCallEnd on the shared events bus.
Rows are keyed by (device_serial, started_at). On CallStart we INSERT with a NULL ended_at; on CallEnd we UPDATE the matching row with the ended_at, duration, and end-reason. The unique index in the schema keeps duplicate-start events idempotent.
func NewCallLog ¶
NewCallLog wires the call log to the bus. It subscribes immediately so callers can publish events before Run is called.
type CallRow ¶
type CallRow struct {
ID int64 `json:"id"`
System string `json:"system"`
Protocol string `json:"protocol"`
GroupID uint32 `json:"group_id"`
SourceID uint32 `json:"source_id"`
FrequencyHz uint32 `json:"frequency_hz"`
Encrypted bool `json:"encrypted"`
AlgorithmID uint8 `json:"algorithm_id"`
KeyID uint16 `json:"key_id"`
Emergency bool `json:"emergency"`
DataCall bool `json:"data_call"`
DeviceSerial string `json:"device_serial"`
StartedAt time.Time `json:"started_at"`
EndedAt time.Time `json:"ended_at,omitempty"` // zero if call still active
DurationMs int64 `json:"duration_ms,omitempty"`
EndReason string `json:"end_reason,omitempty"`
TalkgroupAlpha string `json:"talkgroup_alpha,omitempty"`
}
CallRow is one row from the call_log table.
type DB ¶
type DB struct {
// contains filtered or unexported fields
}
DB is a thin wrapper over *sql.DB that lets the call-log + retention helpers share a typed handle. The schema is migrated on Open.
func Open ¶
Open creates (or opens) a SQLite database at path and applies the embedded schema migrations. The path's parent directory is created if missing.
`:memory:` and the standard "file:..." DSN forms are passed through to the driver — useful for tests.
type HistoryFilter ¶
type HistoryFilter struct {
System string
GroupID uint32 // 0 = no filter
Since time.Time
Until time.Time
Limit int
OnlyEnded bool
}
HistoryFilter narrows a History query.
type Retention ¶
type Retention struct {
// contains filtered or unexported fields
}
Retention deletes old data on a schedule:
- call_log rows with started_at older than CallRowMaxAge.
- WAV / raw files under FilesRoot whose modification time is older than FilesMaxAge.
File deletion is opt-in by setting FilesRoot; an empty value skips the filesystem sweep. The sweeper is idempotent and safe to run concurrently with the call-log writer (SQLite serialises).
func NewRetention ¶
func NewRetention(opts RetentionOptions) (*Retention, error)
type RetentionOptions ¶
type RetentionOptions struct {
DB *DB
// FilesRoot is the directory the voice recorder writes WAV / raw
// files under. Empty disables the filesystem sweep.
FilesRoot string
// CallRowMaxAge: rows with started_at older than this are deleted.
// Zero (the default) disables row deletion.
CallRowMaxAge time.Duration
// FilesMaxAge: files older than this (mtime) are deleted. Zero
// disables file deletion.
FilesMaxAge time.Duration
// Interval between sweeps. Default 1 h.
Interval time.Duration
Log *slog.Logger
}
RetentionOptions configure a Retention sweeper.