From 3dc2232d67dc925d146631ac77f9dc36a57ffb55 Mon Sep 17 00:00:00 2001 From: Daniel Ponte Date: Sat, 22 Feb 2025 14:51:08 -0500 Subject: [PATCH 1/4] Implement talker alias --- pkg/calls/call.go | 3 + pkg/calls/callstore/store.go | 2 + pkg/database/calls.sql.go | 28 ++- pkg/database/incidents.sql.go | 5 + pkg/database/models.go | 2 + pkg/incidents/incstore/store.go | 1 + pkg/pb/stillbox.pb.go | 247 +++++++++++---------- pkg/pb/stillbox.proto | 13 +- pkg/sources/http.go | 2 + sql/postgres/migrations/001_initial.up.sql | 4 + sql/postgres/queries/calls.sql | 6 +- sql/postgres/queries/incidents.sql | 3 + 12 files changed, 182 insertions(+), 134 deletions(-) diff --git a/pkg/calls/call.go b/pkg/calls/call.go index 1639327..44f0702 100644 --- a/pkg/calls/call.go +++ b/pkg/calls/call.go @@ -76,6 +76,7 @@ type Call struct { System int `json:"systemId,omitempty" relayOut:"system,omitempty"` Submitter *users.UserID `json:"submitter,omitempty" relayOut:"submitter,omitempty"` SystemLabel string `json:"systemName,omitempty" relayOut:"systemLabel,omitempty"` + TalkerAlias *string `json:"talkerAlias,omitempty" relayOut:"talkerAlias,omitempty"` Talkgroup int `json:"tgid,omitempty" relayOut:"talkgroup,omitempty"` TalkgroupGroup *string `json:"talkgroupGroup,omitempty" relayOut:"talkgroupGroup,omitempty"` TalkgroupLabel *string `json:"talkgroupLabel,omitempty" relayOut:"talkgroupLabel,omitempty"` @@ -144,6 +145,8 @@ func (c *Call) ToPB() *pb.Call { DateTime: timestamppb.New(c.DateTime), System: int32(c.System), Talkgroup: int32(c.Talkgroup), + TalkerAlias: c.TalkerAlias, + Source: int32(c.Source), Frequency: int64(c.Frequency), Frequencies: toInt64Slice(c.Frequencies), diff --git a/pkg/calls/callstore/store.go b/pkg/calls/callstore/store.go index 5c09dbd..14e9716 100644 --- a/pkg/calls/callstore/store.go +++ b/pkg/calls/callstore/store.go @@ -88,6 +88,7 @@ func toAddCallParams(call *calls.Call) database.AddCallParams { Frequency: call.Frequency, Frequencies: call.Frequencies, Patches: call.Patches, + TalkerAlias: call.TalkerAlias, TGLabel: call.TalkgroupLabel, TGAlphaTag: call.TGAlphaTag, TGGroup: call.TalkgroupGroup, @@ -185,6 +186,7 @@ func (s *postgresStore) Call(ctx context.Context, id uuid.UUID) (*calls.Call, er Frequency: c.Frequency, Frequencies: c.Frequencies, Patches: c.Patches, + TalkerAlias: c.TalkerAlias, TalkgroupLabel: c.TGLabel, TalkgroupGroup: c.TGGroup, TGAlphaTag: c.TGAlphaTag, diff --git a/pkg/database/calls.sql.go b/pkg/database/calls.sql.go index 0d8c2d0..3750009 100644 --- a/pkg/database/calls.sql.go +++ b/pkg/database/calls.sql.go @@ -67,6 +67,7 @@ duration, frequency, frequencies, patches, +talker_alias, tg_label, tg_alpha_tag, tg_group, @@ -88,7 +89,8 @@ $13, $14, $15, $16, -$17 +$17, +$18 ) ` @@ -106,6 +108,7 @@ type AddCallParams struct { Frequency int `json:"frequency"` Frequencies []int `json:"frequencies"` Patches []int `json:"patches"` + TalkerAlias *string `json:"talkerAlias"` TGLabel *string `json:"tgLabel"` TGAlphaTag *string `json:"tgAlphaTag"` TGGroup *string `json:"tgGroup"` @@ -127,6 +130,7 @@ func (q *Queries) AddCall(ctx context.Context, arg AddCallParams) error { arg.Frequency, arg.Frequencies, arg.Patches, + arg.TalkerAlias, arg.TGLabel, arg.TGAlphaTag, arg.TGGroup, @@ -178,6 +182,7 @@ SELECT frequency, frequencies, patches, + talker_alias, tg_label, tg_alpha_tag, tg_group, @@ -200,6 +205,7 @@ type GetCallRow struct { Frequency int `json:"frequency"` Frequencies []int `json:"frequencies"` Patches []int `json:"patches"` + TalkerAlias *string `json:"talkerAlias"` TGLabel *string `json:"tgLabel"` TGAlphaTag *string `json:"tgAlphaTag"` TGGroup *string `json:"tgGroup"` @@ -223,6 +229,7 @@ func (q *Queries) GetCall(ctx context.Context, id uuid.UUID) (GetCallRow, error) &i.Frequency, &i.Frequencies, &i.Patches, + &i.TalkerAlias, &i.TGLabel, &i.TGAlphaTag, &i.TGGroup, @@ -345,6 +352,7 @@ c.call_date, c.duration, c.system system_id, c.talkgroup tgid, +c.talker_alias, COUNT(ic.incident_id) incidents FROM calls c JOIN talkgroups tgs ON c.talkgroup = tgs.tgid AND c.system = tgs.system_id @@ -388,12 +396,13 @@ type ListCallsPParams struct { } type ListCallsPRow struct { - ID uuid.UUID `json:"id"` - CallDate pgtype.Timestamptz `json:"callDate"` - Duration *int32 `json:"duration"` - SystemID int `json:"systemId"` - TGID int `json:"tgid"` - Incidents int64 `json:"incidents"` + ID uuid.UUID `json:"id"` + CallDate pgtype.Timestamptz `json:"callDate"` + Duration *int32 `json:"duration"` + SystemID int `json:"systemId"` + TGID int `json:"tgid"` + TalkerAlias *string `json:"talkerAlias"` + Incidents int64 `json:"incidents"` } func (q *Queries) ListCallsP(ctx context.Context, arg ListCallsPParams) ([]ListCallsPRow, error) { @@ -421,6 +430,7 @@ func (q *Queries) ListCallsP(ctx context.Context, arg ListCallsPParams) ([]ListC &i.Duration, &i.SystemID, &i.TGID, + &i.TalkerAlias, &i.Incidents, ); err != nil { return nil, err @@ -445,11 +455,11 @@ func (q *Queries) SetCallTranscript(ctx context.Context, iD uuid.UUID, transcrip const sweepCalls = `-- name: SweepCalls :execrows WITH to_sweep AS ( SELECT id, submitter, system, talkgroup, calls.call_date, audio_name, audio_blob, duration, audio_type, - audio_url, frequency, frequencies, patches, tg_label, tg_alpha_tag, tg_group, source, transcript + audio_url, frequency, frequencies, talker_alias, patches, tg_label, tg_alpha_tag, tg_group, source, transcript FROM calls JOIN incidents_calls ic ON ic.call_id = calls.id WHERE calls.call_date >= $1 AND calls.call_date < $2 -) INSERT INTO swept_calls SELECT id, submitter, system, talkgroup, call_date, audio_name, audio_blob, duration, audio_type, audio_url, frequency, frequencies, patches, tg_label, tg_alpha_tag, tg_group, source, transcript FROM to_sweep +) INSERT INTO swept_calls SELECT id, submitter, system, talkgroup, call_date, audio_name, audio_blob, duration, audio_type, audio_url, frequency, frequencies, talker_alias, patches, tg_label, tg_alpha_tag, tg_group, source, transcript FROM to_sweep ` // This is used to sweep calls that are part of an incident prior to pruning a partition. diff --git a/pkg/database/incidents.sql.go b/pkg/database/incidents.sql.go index 6e1491f..518f8b5 100644 --- a/pkg/database/incidents.sql.go +++ b/pkg/database/incidents.sql.go @@ -172,6 +172,7 @@ SELECT c.audio_url, c.frequency, c.frequencies, + c.talker_alias, c.patches, c.source, c.transcript @@ -186,6 +187,7 @@ FROM incidents_calls ic, LATERAL ( ca.audio_url, ca.frequency, ca.frequencies, + ca.talker_alias, ca.patches, ca.source, ca.transcript @@ -201,6 +203,7 @@ FROM incidents_calls ic, LATERAL ( sc.audio_url, sc.frequency, sc.frequencies, + c.talker_alias, sc.patches, sc.source, sc.transcript @@ -223,6 +226,7 @@ type GetIncidentCallsRow struct { AudioUrl *string `json:"audioUrl"` Frequency int `json:"frequency"` Frequencies []int `json:"frequencies"` + TalkerAlias *string `json:"talkerAlias"` Patches []int `json:"patches"` Source int `json:"source"` Transcript *string `json:"transcript"` @@ -250,6 +254,7 @@ func (q *Queries) GetIncidentCalls(ctx context.Context, id uuid.UUID) ([]GetInci &i.AudioUrl, &i.Frequency, &i.Frequencies, + &i.TalkerAlias, &i.Patches, &i.Source, &i.Transcript, diff --git a/pkg/database/models.go b/pkg/database/models.go index 0d80a21..1f29741 100644 --- a/pkg/database/models.go +++ b/pkg/database/models.go @@ -48,6 +48,7 @@ type Call struct { Frequency int `json:"frequency,omitempty"` Frequencies []int `json:"frequencies,omitempty"` Patches []int `json:"patches,omitempty"` + TalkerAlias *string `json:"talkerAlias,omitempty"` TGLabel *string `json:"tgLabel,omitempty"` TGAlphaTag *string `json:"tgAlphaTag,omitempty"` TGGroup *string `json:"tgGroup,omitempty"` @@ -105,6 +106,7 @@ type SweptCall struct { Frequency int `json:"frequency,omitempty"` Frequencies []int `json:"frequencies,omitempty"` Patches []int `json:"patches,omitempty"` + TalkerAlias *string `json:"talkerAlias,omitempty"` TGLabel *string `json:"tgLabel,omitempty"` TGAlphaTag *string `json:"tgAlphaTag,omitempty"` TGGroup *string `json:"tgGroup,omitempty"` diff --git a/pkg/incidents/incstore/store.go b/pkg/incidents/incstore/store.go index 5bddd5c..f1e774a 100644 --- a/pkg/incidents/incstore/store.go +++ b/pkg/incidents/incstore/store.go @@ -277,6 +277,7 @@ func fromDBCalls(d []database.GetIncidentCallsRow) []incidents.IncidentCall { Frequencies: v.Frequencies, Frequency: v.Frequency, Patches: v.Patches, + TalkerAlias: v.TalkerAlias, Source: v.Source, System: v.SystemID, Submitter: sub, diff --git a/pkg/pb/stillbox.pb.go b/pkg/pb/stillbox.pb.go index 2742bc8..e0bcc68 100644 --- a/pkg/pb/stillbox.pb.go +++ b/pkg/pb/stillbox.pb.go @@ -294,12 +294,13 @@ type Call struct { DateTime *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=date_time,json=dateTime,proto3" json:"date_time,omitempty"` System int32 `protobuf:"varint,5,opt,name=system,proto3" json:"system,omitempty"` Talkgroup int32 `protobuf:"varint,6,opt,name=talkgroup,proto3" json:"talkgroup,omitempty"` - Source int32 `protobuf:"varint,7,opt,name=source,proto3" json:"source,omitempty"` - Frequency int64 `protobuf:"varint,8,opt,name=frequency,proto3" json:"frequency,omitempty"` - Frequencies []int64 `protobuf:"varint,9,rep,packed,name=frequencies,proto3" json:"frequencies,omitempty"` - Patches []int32 `protobuf:"varint,10,rep,packed,name=patches,proto3" json:"patches,omitempty"` - Duration *int32 `protobuf:"varint,11,opt,name=duration,proto3,oneof" json:"duration,omitempty"` - Audio []byte `protobuf:"bytes,12,opt,name=audio,proto3" json:"audio,omitempty"` + TalkerAlias *string `protobuf:"bytes,7,opt,name=talker_alias,json=talkerAlias,proto3,oneof" json:"talker_alias,omitempty"` + Source int32 `protobuf:"varint,8,opt,name=source,proto3" json:"source,omitempty"` + Frequency int64 `protobuf:"varint,9,opt,name=frequency,proto3" json:"frequency,omitempty"` + Frequencies []int64 `protobuf:"varint,10,rep,packed,name=frequencies,proto3" json:"frequencies,omitempty"` + Patches []int32 `protobuf:"varint,11,rep,packed,name=patches,proto3" json:"patches,omitempty"` + Duration *int32 `protobuf:"varint,12,opt,name=duration,proto3,oneof" json:"duration,omitempty"` + Audio []byte `protobuf:"bytes,13,opt,name=audio,proto3" json:"audio,omitempty"` } func (x *Call) Reset() { @@ -376,6 +377,13 @@ func (x *Call) GetTalkgroup() int32 { return 0 } +func (x *Call) GetTalkerAlias() string { + if x != nil && x.TalkerAlias != nil { + return *x.TalkerAlias + } + return "" +} + func (x *Call) GetSource() int32 { if x != nil { return x.Source @@ -1187,7 +1195,7 @@ var file_stillbox_proto_rawDesc = []byte{ 0x6f, 0x75, 0x70, 0x49, 0x6e, 0x66, 0x6f, 0x48, 0x00, 0x52, 0x06, 0x74, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x42, 0x12, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, - 0x64, 0x5f, 0x69, 0x64, 0x22, 0xf7, 0x02, 0x0a, 0x04, 0x43, 0x61, 0x6c, 0x6c, 0x12, 0x0e, 0x0a, + 0x64, 0x5f, 0x69, 0x64, 0x22, 0xb0, 0x03, 0x0a, 0x04, 0x43, 0x61, 0x6c, 0x6c, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x61, @@ -1199,118 +1207,121 @@ var file_stillbox_proto_rawDesc = []byte{ 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x61, 0x6c, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x74, - 0x61, 0x6c, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x12, 0x1c, 0x0a, 0x09, 0x66, 0x72, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x09, 0x66, 0x72, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x20, - 0x0a, 0x0b, 0x66, 0x72, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x18, 0x09, 0x20, - 0x03, 0x28, 0x03, 0x52, 0x0b, 0x66, 0x72, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, - 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, - 0x05, 0x52, 0x07, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x12, 0x1f, 0x0a, 0x08, 0x64, 0x75, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x05, 0x48, 0x00, 0x52, 0x08, - 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x14, 0x0a, 0x05, 0x61, - 0x75, 0x64, 0x69, 0x6f, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x61, 0x75, 0x64, 0x69, - 0x6f, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, - 0x0a, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x12, 0x35, 0x0a, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x73, - 0x74, 0x69, 0x6c, 0x6c, 0x62, 0x6f, 0x78, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x49, 0x6e, - 0x66, 0x6f, 0x52, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x1d, - 0x0a, 0x09, 0x55, 0x73, 0x65, 0x72, 0x50, 0x6f, 0x70, 0x75, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x6d, - 0x73, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6d, 0x73, 0x67, 0x22, 0x4a, 0x0a, - 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x2b, 0x0a, 0x07, - 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, - 0x73, 0x74, 0x69, 0x6c, 0x6c, 0x62, 0x6f, 0x78, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, - 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x22, 0x78, 0x0a, 0x0c, 0x4e, 0x6f, 0x74, - 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x09, 0x64, 0x61, 0x74, - 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, - 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x64, 0x61, 0x74, 0x65, 0x54, 0x69, - 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x73, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x03, 0x6d, 0x73, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x75, - 0x72, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x55, 0x72, 0x6c, 0x22, 0xed, 0x01, 0x0a, 0x07, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, - 0x22, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x03, 0x48, 0x01, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x49, 0x64, - 0x88, 0x01, 0x01, 0x12, 0x33, 0x0a, 0x0c, 0x6c, 0x69, 0x76, 0x65, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, - 0x61, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x73, 0x74, 0x69, 0x6c, - 0x6c, 0x62, 0x6f, 0x78, 0x2e, 0x4c, 0x69, 0x76, 0x65, 0x48, 0x00, 0x52, 0x0b, 0x6c, 0x69, 0x76, - 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x39, 0x0a, 0x0e, 0x73, 0x65, 0x61, 0x72, - 0x63, 0x68, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x10, 0x2e, 0x73, 0x74, 0x69, 0x6c, 0x6c, 0x62, 0x6f, 0x78, 0x2e, 0x53, 0x65, 0x61, 0x72, - 0x63, 0x68, 0x48, 0x00, 0x52, 0x0d, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x43, 0x6f, 0x6d, 0x6d, - 0x61, 0x6e, 0x64, 0x12, 0x34, 0x0a, 0x0a, 0x74, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, - 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x74, 0x69, 0x6c, 0x6c, 0x62, - 0x6f, 0x78, 0x2e, 0x54, 0x61, 0x6c, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x48, 0x00, 0x52, 0x09, - 0x74, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x42, 0x09, 0x0a, 0x07, 0x63, 0x6f, 0x6d, - 0x6d, 0x61, 0x6e, 0x64, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, - 0x5f, 0x69, 0x64, 0x22, 0xf2, 0x02, 0x0a, 0x0d, 0x54, 0x61, 0x6c, 0x6b, 0x67, 0x72, 0x6f, 0x75, - 0x70, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x23, 0x0a, 0x02, 0x74, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x74, 0x69, 0x6c, 0x6c, 0x62, 0x6f, 0x78, 0x2e, 0x54, 0x61, 0x6c, - 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x02, 0x74, 0x67, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x79, - 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0a, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x17, 0x0a, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x88, 0x01, 0x01, 0x12, 0x19, 0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x88, 0x01, 0x01, 0x12, - 0x20, 0x0a, 0x09, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x09, 0x48, 0x02, 0x52, 0x08, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x54, 0x61, 0x67, 0x88, 0x01, - 0x01, 0x12, 0x21, 0x0a, 0x09, 0x66, 0x72, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x05, 0x48, 0x03, 0x52, 0x09, 0x66, 0x72, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, - 0x79, 0x88, 0x01, 0x01, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x07, 0x20, 0x03, - 0x28, 0x09, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x38, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, - 0x75, 0x63, 0x74, 0x48, 0x04, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x88, - 0x01, 0x01, 0x12, 0x18, 0x0a, 0x07, 0x6c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x18, 0x09, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x07, 0x6c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x42, 0x07, 0x0a, 0x05, - 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x42, - 0x0c, 0x0a, 0x0a, 0x5f, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x5f, 0x74, 0x61, 0x67, 0x42, 0x0c, 0x0a, - 0x0a, 0x5f, 0x66, 0x72, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x79, 0x42, 0x0b, 0x0a, 0x09, 0x5f, - 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x7a, 0x0a, 0x04, 0x4c, 0x69, 0x76, 0x65, - 0x12, 0x2e, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x13, 0x2e, 0x73, 0x74, 0x69, 0x6c, 0x6c, 0x62, 0x6f, 0x78, 0x2e, 0x4c, 0x69, 0x76, 0x65, 0x53, - 0x74, 0x61, 0x74, 0x65, 0x48, 0x00, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x88, 0x01, 0x01, - 0x12, 0x2d, 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x10, 0x2e, 0x73, 0x74, 0x69, 0x6c, 0x6c, 0x62, 0x6f, 0x78, 0x2e, 0x46, 0x69, 0x6c, 0x74, - 0x65, 0x72, 0x48, 0x01, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x88, 0x01, 0x01, 0x42, - 0x08, 0x0a, 0x06, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x66, 0x69, - 0x6c, 0x74, 0x65, 0x72, 0x22, 0x41, 0x0a, 0x09, 0x54, 0x61, 0x6c, 0x6b, 0x67, 0x72, 0x6f, 0x75, - 0x70, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x05, 0x52, 0x06, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x61, 0x6c, - 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x74, 0x61, - 0x6c, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x22, 0x83, 0x02, 0x0a, 0x06, 0x46, 0x69, 0x6c, 0x74, - 0x65, 0x72, 0x12, 0x33, 0x0a, 0x0a, 0x74, 0x61, 0x6c, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x74, 0x69, 0x6c, 0x6c, 0x62, 0x6f, - 0x78, 0x2e, 0x54, 0x61, 0x6c, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x0a, 0x74, 0x61, 0x6c, - 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x12, 0x3a, 0x0a, 0x0e, 0x74, 0x61, 0x6c, 0x6b, 0x67, - 0x72, 0x6f, 0x75, 0x70, 0x73, 0x5f, 0x6e, 0x6f, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x61, 0x6c, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x26, 0x0a, 0x0c, 0x74, 0x61, 0x6c, 0x6b, + 0x65, 0x72, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, + 0x52, 0x0b, 0x74, 0x61, 0x6c, 0x6b, 0x65, 0x72, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x88, 0x01, 0x01, + 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x66, 0x72, 0x65, 0x71, + 0x75, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x66, 0x72, 0x65, + 0x71, 0x75, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x20, 0x0a, 0x0b, 0x66, 0x72, 0x65, 0x71, 0x75, 0x65, + 0x6e, 0x63, 0x69, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x03, 0x52, 0x0b, 0x66, 0x72, 0x65, + 0x71, 0x75, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x74, 0x63, + 0x68, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x05, 0x52, 0x07, 0x70, 0x61, 0x74, 0x63, 0x68, + 0x65, 0x73, 0x12, 0x1f, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0c, + 0x20, 0x01, 0x28, 0x05, 0x48, 0x01, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x88, 0x01, 0x01, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x18, 0x0d, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x05, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x42, 0x0f, 0x0a, 0x0d, 0x5f, 0x74, 0x61, + 0x6c, 0x6b, 0x65, 0x72, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x64, + 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x0a, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f, + 0x12, 0x35, 0x0a, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x73, 0x74, 0x69, 0x6c, 0x6c, 0x62, 0x6f, 0x78, + 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x73, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x1d, 0x0a, 0x09, 0x55, 0x73, 0x65, 0x72, 0x50, + 0x6f, 0x70, 0x75, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x73, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x6d, 0x73, 0x67, 0x22, 0x4a, 0x0a, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, + 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x2b, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x73, 0x74, 0x69, 0x6c, 0x6c, 0x62, 0x6f, + 0x78, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, + 0x6e, 0x64, 0x22, 0x78, 0x0a, 0x0c, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x09, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, + 0x70, 0x52, 0x08, 0x64, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6d, + 0x73, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6d, 0x73, 0x67, 0x12, 0x1d, 0x0a, + 0x0a, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x72, 0x6c, 0x22, 0xed, 0x01, 0x0a, + 0x07, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x22, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, + 0x61, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x48, 0x01, 0x52, 0x09, + 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x33, 0x0a, 0x0c, + 0x6c, 0x69, 0x76, 0x65, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x73, 0x74, 0x69, 0x6c, 0x6c, 0x62, 0x6f, 0x78, 0x2e, 0x4c, 0x69, + 0x76, 0x65, 0x48, 0x00, 0x52, 0x0b, 0x6c, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, + 0x64, 0x12, 0x39, 0x0a, 0x0e, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, + 0x61, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x73, 0x74, 0x69, 0x6c, + 0x6c, 0x62, 0x6f, 0x78, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x48, 0x00, 0x52, 0x0d, 0x73, + 0x65, 0x61, 0x72, 0x63, 0x68, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x34, 0x0a, 0x0a, + 0x74, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x13, 0x2e, 0x73, 0x74, 0x69, 0x6c, 0x6c, 0x62, 0x6f, 0x78, 0x2e, 0x54, 0x61, 0x6c, 0x6b, + 0x67, 0x72, 0x6f, 0x75, 0x70, 0x48, 0x00, 0x52, 0x09, 0x74, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x61, + 0x6e, 0x64, 0x42, 0x09, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x42, 0x0d, 0x0a, + 0x0b, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x22, 0xf2, 0x02, 0x0a, + 0x0d, 0x54, 0x61, 0x6c, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x23, + 0x0a, 0x02, 0x74, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x74, 0x69, + 0x6c, 0x6c, 0x62, 0x6f, 0x78, 0x2e, 0x54, 0x61, 0x6c, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x52, + 0x02, 0x74, 0x67, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, + 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x17, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x48, 0x00, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x12, 0x19, 0x0a, + 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x05, + 0x67, 0x72, 0x6f, 0x75, 0x70, 0x88, 0x01, 0x01, 0x12, 0x20, 0x0a, 0x09, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x08, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x54, 0x61, 0x67, 0x88, 0x01, 0x01, 0x12, 0x21, 0x0a, 0x09, 0x66, 0x72, + 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x48, 0x03, 0x52, + 0x09, 0x66, 0x72, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x79, 0x88, 0x01, 0x01, 0x12, 0x12, 0x0a, + 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x74, 0x61, 0x67, + 0x73, 0x12, 0x38, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x08, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x48, 0x04, 0x52, 0x08, + 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x88, 0x01, 0x01, 0x12, 0x18, 0x0a, 0x07, 0x6c, + 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x6c, 0x65, + 0x61, 0x72, 0x6e, 0x65, 0x64, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x08, + 0x0a, 0x06, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x5f, 0x74, 0x61, 0x67, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x66, 0x72, 0x65, 0x71, 0x75, + 0x65, 0x6e, 0x63, 0x79, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0x22, 0x7a, 0x0a, 0x04, 0x4c, 0x69, 0x76, 0x65, 0x12, 0x2e, 0x0a, 0x05, 0x73, 0x74, 0x61, + 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x13, 0x2e, 0x73, 0x74, 0x69, 0x6c, 0x6c, + 0x62, 0x6f, 0x78, 0x2e, 0x4c, 0x69, 0x76, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x48, 0x00, 0x52, + 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x88, 0x01, 0x01, 0x12, 0x2d, 0x0a, 0x06, 0x66, 0x69, 0x6c, + 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x73, 0x74, 0x69, 0x6c, + 0x6c, 0x62, 0x6f, 0x78, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x48, 0x01, 0x52, 0x06, 0x66, + 0x69, 0x6c, 0x74, 0x65, 0x72, 0x88, 0x01, 0x01, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x73, 0x74, 0x61, + 0x74, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0x41, 0x0a, + 0x09, 0x54, 0x61, 0x6c, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x79, + 0x73, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x73, 0x79, 0x73, 0x74, + 0x65, 0x6d, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x61, 0x6c, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x74, 0x61, 0x6c, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, + 0x22, 0x83, 0x02, 0x0a, 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x33, 0x0a, 0x0a, 0x74, + 0x61, 0x6c, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x74, 0x69, 0x6c, 0x6c, 0x62, 0x6f, 0x78, 0x2e, 0x54, 0x61, 0x6c, 0x6b, 0x67, - 0x72, 0x6f, 0x75, 0x70, 0x52, 0x0d, 0x74, 0x61, 0x6c, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, - 0x4e, 0x6f, 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x74, 0x61, 0x6c, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, - 0x5f, 0x74, 0x61, 0x67, 0x73, 0x5f, 0x61, 0x6c, 0x6c, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x10, 0x74, 0x61, 0x6c, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x54, 0x61, 0x67, 0x73, 0x41, 0x6c, - 0x6c, 0x12, 0x2c, 0x0a, 0x12, 0x74, 0x61, 0x6c, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x74, - 0x61, 0x67, 0x73, 0x5f, 0x61, 0x6e, 0x79, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x74, - 0x61, 0x6c, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x54, 0x61, 0x67, 0x73, 0x41, 0x6e, 0x79, 0x12, - 0x2c, 0x0a, 0x12, 0x74, 0x61, 0x6c, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x74, 0x61, 0x67, - 0x73, 0x5f, 0x6e, 0x6f, 0x74, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x74, 0x61, 0x6c, - 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x54, 0x61, 0x67, 0x73, 0x4e, 0x6f, 0x74, 0x22, 0x08, 0x0a, - 0x06, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x22, 0x92, 0x01, 0x0a, 0x0a, 0x53, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, - 0x6f, 0x72, 0x6d, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, - 0x6f, 0x72, 0x6d, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x62, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x62, 0x53, 0x69, 0x7a, 0x65, 0x2a, 0x37, 0x0a, 0x09, - 0x4c, 0x69, 0x76, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x0a, 0x4c, 0x53, 0x5f, - 0x53, 0x54, 0x4f, 0x50, 0x50, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x4c, 0x53, 0x5f, - 0x4c, 0x49, 0x56, 0x45, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x53, 0x5f, 0x50, 0x41, 0x55, - 0x53, 0x45, 0x44, 0x10, 0x02, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x72, 0x6f, 0x75, 0x70, 0x52, 0x0a, 0x74, 0x61, 0x6c, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, + 0x12, 0x3a, 0x0a, 0x0e, 0x74, 0x61, 0x6c, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x5f, 0x6e, + 0x6f, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x74, 0x69, 0x6c, 0x6c, + 0x62, 0x6f, 0x78, 0x2e, 0x54, 0x61, 0x6c, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x0d, 0x74, + 0x61, 0x6c, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x4e, 0x6f, 0x74, 0x12, 0x2c, 0x0a, 0x12, + 0x74, 0x61, 0x6c, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x74, 0x61, 0x67, 0x73, 0x5f, 0x61, + 0x6c, 0x6c, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x74, 0x61, 0x6c, 0x6b, 0x67, 0x72, + 0x6f, 0x75, 0x70, 0x54, 0x61, 0x67, 0x73, 0x41, 0x6c, 0x6c, 0x12, 0x2c, 0x0a, 0x12, 0x74, 0x61, + 0x6c, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x74, 0x61, 0x67, 0x73, 0x5f, 0x61, 0x6e, 0x79, + 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x74, 0x61, 0x6c, 0x6b, 0x67, 0x72, 0x6f, 0x75, + 0x70, 0x54, 0x61, 0x67, 0x73, 0x41, 0x6e, 0x79, 0x12, 0x2c, 0x0a, 0x12, 0x74, 0x61, 0x6c, 0x6b, + 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x74, 0x61, 0x67, 0x73, 0x5f, 0x6e, 0x6f, 0x74, 0x18, 0x05, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x74, 0x61, 0x6c, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x54, + 0x61, 0x67, 0x73, 0x4e, 0x6f, 0x74, 0x22, 0x08, 0x0a, 0x06, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, + 0x22, 0x92, 0x01, 0x0a, 0x0a, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, + 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, + 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x75, + 0x69, 0x6c, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x62, 0x75, 0x69, 0x6c, 0x74, + 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x17, 0x0a, 0x07, + 0x64, 0x62, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, + 0x62, 0x53, 0x69, 0x7a, 0x65, 0x2a, 0x37, 0x0a, 0x09, 0x4c, 0x69, 0x76, 0x65, 0x53, 0x74, 0x61, + 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x0a, 0x4c, 0x53, 0x5f, 0x53, 0x54, 0x4f, 0x50, 0x50, 0x45, 0x44, + 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x4c, 0x53, 0x5f, 0x4c, 0x49, 0x56, 0x45, 0x10, 0x01, 0x12, + 0x0d, 0x0a, 0x09, 0x4c, 0x53, 0x5f, 0x50, 0x41, 0x55, 0x53, 0x45, 0x44, 0x10, 0x02, 0x42, 0x06, + 0x5a, 0x04, 0x2e, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/pkg/pb/stillbox.proto b/pkg/pb/stillbox.proto index 01751bd..d509028 100644 --- a/pkg/pb/stillbox.proto +++ b/pkg/pb/stillbox.proto @@ -30,12 +30,13 @@ message Call { google.protobuf.Timestamp date_time = 4; int32 system = 5; int32 talkgroup = 6; - int32 source = 7; - int64 frequency = 8; - repeated int64 frequencies = 9; - repeated int32 patches = 10; - optional int32 duration = 11; - bytes audio = 12; + optional string talker_alias = 7; + int32 source = 8; + int64 frequency = 9; + repeated int64 frequencies = 10; + repeated int32 patches = 11; + optional int32 duration = 12; + bytes audio = 13; } message Hello { diff --git a/pkg/sources/http.go b/pkg/sources/http.go index e004621..038b449 100644 --- a/pkg/sources/http.go +++ b/pkg/sources/http.go @@ -51,6 +51,7 @@ type CallUploadRequest struct { Source int `form:"source"` System int `form:"system"` SystemLabel string `form:"systemLabel"` + TalkerAlias string `form:"talkerAlias"` Talkgroup int `form:"talkgroup"` TalkgroupGroup string `form:"talkgroupGroup"` TalkgroupLabel string `form:"talkgroupLabel"` @@ -85,6 +86,7 @@ func (car *CallUploadRequest) ToCall(submitter users.UserID) (*calls.Call, error Frequency: car.Frequency, Frequencies: car.Frequencies, Patches: car.Patches, + TalkerAlias: common.NilIfZero(car.TalkerAlias), TalkgroupLabel: common.NilIfZero(car.TalkgroupLabel), TGAlphaTag: common.NilIfZero(car.TalkgroupTag), TalkgroupGroup: common.NilIfZero(car.TalkgroupGroup), diff --git a/sql/postgres/migrations/001_initial.up.sql b/sql/postgres/migrations/001_initial.up.sql index ea77bf7..ff6022b 100644 --- a/sql/postgres/migrations/001_initial.up.sql +++ b/sql/postgres/migrations/001_initial.up.sql @@ -94,6 +94,7 @@ CREATE TABLE IF NOT EXISTS calls( frequency INTEGER NOT NULL, frequencies INTEGER[], patches INTEGER[], + talker_alias TEXT, tg_label TEXT, tg_alpha_tag TEXT, tg_group TEXT, @@ -105,6 +106,7 @@ CREATE TABLE IF NOT EXISTS calls( CREATE INDEX IF NOT EXISTS calls_transcript_idx ON calls USING GIN (to_tsvector('english', transcript)); CREATE INDEX IF NOT EXISTS calls_call_date_tg_idx ON calls(call_date, talkgroup, system); +CREATE INDEX IF NOT EXISTS calls_talker_alias ON calls(talker_alias); CREATE TABLE swept_calls ( id UUID PRIMARY KEY, @@ -120,6 +122,7 @@ CREATE TABLE swept_calls ( frequency INTEGER NOT NULL, frequencies INTEGER[], patches INTEGER[], + talker_alias TEXT, tg_label TEXT, tg_alpha_tag TEXT, tg_group TEXT, @@ -130,6 +133,7 @@ CREATE TABLE swept_calls ( CREATE INDEX IF NOT EXISTS swept_calls_transcript_idx ON swept_calls USING GIN (to_tsvector('english', transcript)); CREATE INDEX IF NOT EXISTS swept_calls_call_date_tg_idx ON swept_calls(system, talkgroup, call_date); +CREATE INDEX IF NOT EXISTS swept_calls_talker_alias ON calls(talker_alias); CREATE TABLE IF NOT EXISTS settings( diff --git a/sql/postgres/queries/calls.sql b/sql/postgres/queries/calls.sql index 8496475..0898863 100644 --- a/sql/postgres/queries/calls.sql +++ b/sql/postgres/queries/calls.sql @@ -13,6 +13,7 @@ duration, frequency, frequencies, patches, +talker_alias, tg_label, tg_alpha_tag, tg_group, @@ -31,6 +32,7 @@ source @frequency, @frequencies, @patches, +@talker_alias, @tg_label, @tg_alpha_tag, @tg_group, @@ -79,7 +81,7 @@ SELECT pg_size_pretty(pg_database_size(current_database())); -- This is used to sweep calls that are part of an incident prior to pruning a partition. WITH to_sweep AS ( SELECT id, submitter, system, talkgroup, calls.call_date, audio_name, audio_blob, duration, audio_type, - audio_url, frequency, frequencies, patches, tg_label, tg_alpha_tag, tg_group, source, transcript + audio_url, frequency, frequencies, talker_alias, patches, tg_label, tg_alpha_tag, tg_group, source, transcript FROM calls JOIN incidents_calls ic ON ic.call_id = calls.id WHERE calls.call_date >= @range_start AND calls.call_date < @range_end @@ -103,6 +105,7 @@ c.call_date, c.duration, c.system system_id, c.talkgroup tgid, +c.talker_alias, COUNT(ic.incident_id) incidents FROM calls c JOIN talkgroups tgs ON c.talkgroup = tgs.tgid AND c.system = tgs.system_id @@ -177,6 +180,7 @@ SELECT frequency, frequencies, patches, + talker_alias, tg_label, tg_alpha_tag, tg_group, diff --git a/sql/postgres/queries/incidents.sql b/sql/postgres/queries/incidents.sql index 9dca9f6..dc3591d 100644 --- a/sql/postgres/queries/incidents.sql +++ b/sql/postgres/queries/incidents.sql @@ -120,6 +120,7 @@ SELECT c.audio_url, c.frequency, c.frequencies, + c.talker_alias, c.patches, c.source, c.transcript @@ -134,6 +135,7 @@ FROM incidents_calls ic, LATERAL ( ca.audio_url, ca.frequency, ca.frequencies, + ca.talker_alias, ca.patches, ca.source, ca.transcript @@ -149,6 +151,7 @@ FROM incidents_calls ic, LATERAL ( sc.audio_url, sc.frequency, sc.frequencies, + c.talker_alias, sc.patches, sc.source, sc.transcript From ef1784c806d5501ba2a17b957654bc9daad12683 Mon Sep 17 00:00:00 2001 From: Daniel Ponte Date: Tue, 18 Feb 2025 08:58:12 -0500 Subject: [PATCH 2/4] break intervals out --- internal/common/intervals.go | 84 +++++++++++++++++++++++++++++++ pkg/database/partman/intervals.go | 73 +++++++++------------------ pkg/database/partman/partman.go | 20 +------- pkg/database/stats.sql.go | 4 +- pkg/stats/stats.go | 13 ++++- sql/postgres/queries/stats.sql | 4 +- 6 files changed, 125 insertions(+), 73 deletions(-) create mode 100644 internal/common/intervals.go diff --git a/internal/common/intervals.go b/internal/common/intervals.go new file mode 100644 index 0000000..0458f3c --- /dev/null +++ b/internal/common/intervals.go @@ -0,0 +1,84 @@ +package common + +import ( + "time" +) + +const ( + DaysInWeek = 7 + MonthsInQuarter = 3 +) + +type TimeBounder interface { + GetDailyBounds(date time.Time) (lowerBound, upperBound time.Time) + GetWeeklyBounds(date time.Time) (lowerBound, upperBound time.Time) + GetMonthlyBounds(date time.Time) (lowerBound, upperBound time.Time) + GetQuarterlyBounds(date time.Time) (lowerBound, upperBound time.Time) + GetYearlyBounds(date time.Time) (lowerBound, upperBound time.Time) +} + +type tbOpt func(*timeBounder) + +func WithLocation(l *time.Location) tbOpt { + return func(tb *timeBounder) { + tb.loc = l + } +} + +func NewTimeBounder(opts ...tbOpt) timeBounder { + tb := timeBounder{} + + for _, opt := range opts { + opt(&tb) + } + + if tb.loc == nil { + tb.loc = time.UTC + } + + return tb +} + +type timeBounder struct { + loc *time.Location +} + +func (tb timeBounder) GetDailyBounds(date time.Time) (lowerBound, upperBound time.Time) { + lowerBound = time.Date(date.Year(), date.Month(), date.Day(), 0, 0, 0, 0, tb.loc) + upperBound = lowerBound.AddDate(0, 0, 1) + + return +} + +func (tb timeBounder) GetWeeklyBounds(date time.Time) (lowerBound, upperBound time.Time) { + lowerBound = time.Date(date.Year(), date.Month(), date.Day(), 0, 0, 0, 0, tb.loc).AddDate(0, 0, -int(date.Weekday()-time.Monday)) + upperBound = lowerBound.AddDate(0, 0, DaysInWeek) + + return +} + +func (tb timeBounder) GetMonthlyBounds(date time.Time) (lowerBound, upperBound time.Time) { + lowerBound = time.Date(date.Year(), date.Month(), 1, 0, 0, 0, 0, tb.loc) + upperBound = lowerBound.AddDate(0, 1, 0) + + return +} + +func (tb *timeBounder) GetQuarterlyBounds(date time.Time) (lowerBound, upperBound time.Time) { + year, _, _ := date.Date() + + quarter := (int(date.Month()) - 1) / MonthsInQuarter + firstMonthOfTheQuarter := time.Month(quarter*MonthsInQuarter + 1) + + lowerBound = time.Date(year, firstMonthOfTheQuarter, 1, 0, 0, 0, 0, tb.loc) + upperBound = lowerBound.AddDate(0, MonthsInQuarter, 0) + + return +} + +func (tb timeBounder) GetYearlyBounds(date time.Time) (lowerBound, upperBound time.Time) { + lowerBound = time.Date(date.Year(), 1, 1, 0, 0, 0, 0, tb.loc) + upperBound = lowerBound.AddDate(1, 0, 0) + + return +} diff --git a/pkg/database/partman/intervals.go b/pkg/database/partman/intervals.go index 0252302..e040b02 100644 --- a/pkg/database/partman/intervals.go +++ b/pkg/database/partman/intervals.go @@ -3,66 +3,23 @@ package partman import ( "fmt" "time" + + "dynatron.me/x/stillbox/internal/common" ) -const ( - daysInWeek = 7 - monthsInQuarter = 3 -) - -func getDailyBounds(date time.Time) (lowerBound, upperBound time.Time) { - lowerBound = time.Date(date.Year(), date.Month(), date.Day(), 0, 0, 0, 0, time.UTC) - upperBound = lowerBound.AddDate(0, 0, 1) - - return -} - -func getWeeklyBounds(date time.Time) (lowerBound, upperBound time.Time) { - lowerBound = time.Date(date.Year(), date.Month(), date.Day(), 0, 0, 0, 0, time.UTC).AddDate(0, 0, -int(date.Weekday()-time.Monday)) - upperBound = lowerBound.AddDate(0, 0, daysInWeek) - - return -} - -func getMonthlyBounds(date time.Time) (lowerBound, upperBound time.Time) { - lowerBound = time.Date(date.Year(), date.Month(), 1, 0, 0, 0, 0, time.UTC) - upperBound = lowerBound.AddDate(0, 1, 0) - - return -} - -func getQuarterlyBounds(date time.Time) (lowerBound, upperBound time.Time) { - year, _, _ := date.Date() - - quarter := (int(date.Month()) - 1) / monthsInQuarter - firstMonthOfTheQuarter := time.Month(quarter*monthsInQuarter + 1) - - lowerBound = time.Date(year, firstMonthOfTheQuarter, 1, 0, 0, 0, 0, time.UTC) - upperBound = lowerBound.AddDate(0, monthsInQuarter, 0) - - return -} - -func getYearlyBounds(date time.Time) (lowerBound, upperBound time.Time) { - lowerBound = time.Date(date.Year(), 1, 1, 0, 0, 0, 0, time.UTC) - upperBound = lowerBound.AddDate(1, 0, 0) - - return -} - func (p Partition) Next(i int) Partition { var t time.Time switch p.Interval { case Daily: t = p.Time.AddDate(0, 0, i) case Weekly: - t = p.Time.AddDate(0, 0, i*daysInWeek) + t = p.Time.AddDate(0, 0, i*common.DaysInWeek) case Monthly: year, month, _ := p.Time.Date() t = time.Date(year, month+time.Month(i), 1, 0, 0, 0, 0, p.Time.Location()) case Quarterly: - t = p.Time.AddDate(0, i*monthsInQuarter, 0) + t = p.Time.AddDate(0, i*common.MonthsInQuarter, 0) case Yearly: year, _, _ := p.Time.Date() @@ -125,13 +82,13 @@ func (p Partition) Prev(i int) Partition { case Daily: t = p.Time.AddDate(0, 0, -i) case Weekly: - t = p.Time.AddDate(0, 0, -i*daysInWeek) + t = p.Time.AddDate(0, 0, -i*common.DaysInWeek) case Monthly: year, month, _ := p.Time.Date() t = time.Date(year, month-time.Month(i), 1, 0, 0, 0, 0, p.Time.Location()) case Quarterly: - t = p.Time.AddDate(0, -i*monthsInQuarter, 0) + t = p.Time.AddDate(0, -i*common.MonthsInQuarter, 0) case Yearly: year, _, _ := p.Time.Date() @@ -150,3 +107,21 @@ func (p Partition) Prev(i int) Partition { return pp } + +func (p Partition) Range() (time.Time, time.Time) { + b := common.NewTimeBounder() + switch p.Interval { + case Daily: + return b.GetDailyBounds(p.Time) + case Weekly: + return b.GetWeeklyBounds(p.Time) + case Monthly: + return b.GetMonthlyBounds(p.Time) + case Quarterly: + return b.GetQuarterlyBounds(p.Time) + case Yearly: + return b.GetYearlyBounds(p.Time) + } + + panic("unknown interval!") +} diff --git a/pkg/database/partman/partman.go b/pkg/database/partman/partman.go index 9b7afcd..461d67b 100644 --- a/pkg/database/partman/partman.go +++ b/pkg/database/partman/partman.go @@ -10,6 +10,7 @@ import ( "strings" "time" + "dynatron.me/x/stillbox/internal/common" "dynatron.me/x/stillbox/internal/isoweek" "dynatron.me/x/stillbox/pkg/config" "dynatron.me/x/stillbox/pkg/database" @@ -325,23 +326,6 @@ func (pm *partman) Check(ctx context.Context, now time.Time) error { }, pgx.TxOptions{}) } -func (p Partition) Range() (time.Time, time.Time) { - switch p.Interval { - case Daily: - return getDailyBounds(p.Time) - case Weekly: - return getWeeklyBounds(p.Time) - case Monthly: - return getMonthlyBounds(p.Time) - case Quarterly: - return getQuarterlyBounds(p.Time) - case Yearly: - return getYearlyBounds(p.Time) - } - - panic("unknown interval!") -} - func (p Partition) PartitionName() string { return p.Name } @@ -423,7 +407,7 @@ func (pm *partman) verifyPartName(pr database.PartitionResult) (p Partition, err if quarterNum > 4 { return p, PartitionError(pn, errors.New("invalid quarter")) } - firstMonthOfTheQuarter := time.Month((quarterNum-1)*monthsInQuarter + 1) + firstMonthOfTheQuarter := time.Month((quarterNum-1)*common.MonthsInQuarter + 1) parsed := time.Date(year, firstMonthOfTheQuarter, 1, 0, 0, 0, 0, time.UTC) if parsed != p.Time { return p, PartitionError(pn, ParsedIntvlErr{parsed: parsed, start: p.Time}) diff --git a/pkg/database/stats.sql.go b/pkg/database/stats.sql.go index 3db6ae8..6a54683 100644 --- a/pkg/database/stats.sql.go +++ b/pkg/database/stats.sql.go @@ -20,7 +20,7 @@ WHERE CASE WHEN $2::TIMESTAMPTZ IS NOT NULL THEN c.call_date >= $2 ELSE TRUE END AND CASE WHEN $3::TIMESTAMPTZ IS NOT NULL THEN - c.call_date <= $3 ELSE TRUE END + c.call_date < $3 ELSE TRUE END GROUP BY date ORDER BY date DESC ` @@ -61,7 +61,7 @@ WHERE CASE WHEN $2::TIMESTAMPTZ IS NOT NULL THEN c.call_date >= $2 ELSE TRUE END AND CASE WHEN $3::TIMESTAMPTZ IS NOT NULL THEN - c.call_date <= $3 ELSE TRUE END + c.call_date < $3 ELSE TRUE END GROUP BY 2, 3, 4 ORDER BY 4 DESC ` diff --git a/pkg/stats/stats.go b/pkg/stats/stats.go index b1e03bd..e8c4d31 100644 --- a/pkg/stats/stats.go +++ b/pkg/stats/stats.go @@ -5,10 +5,12 @@ import ( "time" "dynatron.me/x/stillbox/internal/cache" + "dynatron.me/x/stillbox/internal/common" "dynatron.me/x/stillbox/internal/jsontypes" "dynatron.me/x/stillbox/pkg/calls" "dynatron.me/x/stillbox/pkg/calls/callstore" "dynatron.me/x/stillbox/pkg/services" + "github.com/rs/zerolog/log" ) const DefaultExpiration = 5 * time.Minute @@ -56,20 +58,27 @@ func (s *stats) GetCallStats(ctx context.Context, interval calls.StatsInterval) var start time.Time now := time.Now() + end := now + bnd := common.NewTimeBounder(common.WithLocation(now.Location())) + switch interval { case calls.IntervalHour: start = now.Add(-24 * time.Hour) // one day case calls.IntervalDay: start = now.Add(-7 * 24 * time.Hour) // one week case calls.IntervalWeek: - start = now.Add(-30 * 24 * time.Hour) // one month + start, end = bnd.GetMonthlyBounds(now) + start, _ = bnd.GetWeeklyBounds(start) + _, end = bnd.GetWeeklyBounds(end) case calls.IntervalMonth: start = now.Add(-365 * 24 * time.Hour) // one year default: return nil, calls.ErrInvalidInterval } - st, err := s.cs.CallStats(ctx, interval, jsontypes.Time(start), jsontypes.Time(now)) + log.Debug().Str("start", start.String()).Str("end", end.String()).Msg("bound") + + st, err := s.cs.CallStats(ctx, interval, jsontypes.Time(start), jsontypes.Time(end)) if err != nil { return nil, err } diff --git a/sql/postgres/queries/stats.sql b/sql/postgres/queries/stats.sql index e201da8..32538c7 100644 --- a/sql/postgres/queries/stats.sql +++ b/sql/postgres/queries/stats.sql @@ -9,7 +9,7 @@ WHERE CASE WHEN sqlc.narg('start')::TIMESTAMPTZ IS NOT NULL THEN c.call_date >= @start ELSE TRUE END AND CASE WHEN sqlc.narg('end')::TIMESTAMPTZ IS NOT NULL THEN - c.call_date <= sqlc.narg('end') ELSE TRUE END + c.call_date < sqlc.narg('end') ELSE TRUE END GROUP BY 2, 3, 4 ORDER BY 4 DESC; @@ -22,6 +22,6 @@ WHERE CASE WHEN sqlc.narg('start')::TIMESTAMPTZ IS NOT NULL THEN c.call_date >= @start ELSE TRUE END AND CASE WHEN sqlc.narg('end')::TIMESTAMPTZ IS NOT NULL THEN - c.call_date <= sqlc.narg('end') ELSE TRUE END + c.call_date < sqlc.narg('end') ELSE TRUE END GROUP BY date ORDER BY date DESC; From f9a3133a363ae4ba66f33d306bc3cff100c5609e Mon Sep 17 00:00:00 2001 From: Daniel Ponte Date: Tue, 18 Feb 2025 09:02:39 -0500 Subject: [PATCH 3/4] remove bound log --- pkg/stats/stats.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/pkg/stats/stats.go b/pkg/stats/stats.go index e8c4d31..5504935 100644 --- a/pkg/stats/stats.go +++ b/pkg/stats/stats.go @@ -76,8 +76,6 @@ func (s *stats) GetCallStats(ctx context.Context, interval calls.StatsInterval) return nil, calls.ErrInvalidInterval } - log.Debug().Str("start", start.String()).Str("end", end.String()).Msg("bound") - st, err := s.cs.CallStats(ctx, interval, jsontypes.Time(start), jsontypes.Time(end)) if err != nil { return nil, err From 88655a5d6ceeaf32af0410f52145e304a2a0aded Mon Sep 17 00:00:00 2001 From: Daniel Ponte Date: Fri, 21 Feb 2025 20:59:08 -0500 Subject: [PATCH 4/4] make it debug, emit the tg id --- pkg/alerting/alerting.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/alerting/alerting.go b/pkg/alerting/alerting.go index 72b39e8..6247669 100644 --- a/pkg/alerting/alerting.go +++ b/pkg/alerting/alerting.go @@ -182,7 +182,7 @@ func (as *alerter) eval(ctx context.Context, now time.Time, testMode bool) ([]al origScore := s.Score tgr, err := as.tgCache.TG(ctx, s.ID) if err != nil { - log.Error().Err(err).Msg("alerting eval tg get") + log.Debug().Str("tg", s.ID.String()).Err(err).Msg("alerting eval tg get") continue }