From 1b6e5af87f0632a7cad8e421915b265bf77c7f3b Mon Sep 17 00:00:00 2001 From: Daniel Ponte Date: Sat, 22 Feb 2025 15:40:09 -0500 Subject: [PATCH 1/6] multiple files --- util/omitempty/omitempty.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/util/omitempty/omitempty.go b/util/omitempty/omitempty.go index 325d526..801c3d5 100644 --- a/util/omitempty/omitempty.go +++ b/util/omitempty/omitempty.go @@ -12,10 +12,19 @@ import ( "strings" ) -const filePath = "./pkg/database/models.go" +var filePaths = []string{ + "./pkg/database/models.go", + "./pkg/database/calls.sql.go", +} func main() { // Parse the source code + for _, v := range filePaths { + process(v) + } +} + +func process(filePath string) { fset := token.NewFileSet() f, err := parser.ParseFile(fset, filePath, nil, parser.ParseComments) if err != nil { From 78bd29b3165965c647a905571742254540277cea Mon Sep 17 00:00:00 2001 From: Daniel Ponte Date: Sat, 22 Feb 2025 15:41:18 -0500 Subject: [PATCH 2/6] Omitempty on calls queries --- pkg/database/calls.sql.go | 140 +++++++++++++++++++------------------- 1 file changed, 70 insertions(+), 70 deletions(-) diff --git a/pkg/database/calls.sql.go b/pkg/database/calls.sql.go index 3750009..b997780 100644 --- a/pkg/database/calls.sql.go +++ b/pkg/database/calls.sql.go @@ -28,14 +28,14 @@ VALUES ` type AddAlertParams struct { - Time pgtype.Timestamptz `json:"time"` - TGID int `json:"tgid"` - SystemID int `json:"systemId"` - Weight *float32 `json:"weight"` - Score *float32 `json:"score"` - OrigScore *float32 `json:"origScore"` - Notified bool `json:"notified"` - Metadata []byte `json:"metadata"` + Time pgtype.Timestamptz `json:"time,omitempty"` + TGID int `json:"tgid,omitempty"` + SystemID int `json:"systemId,omitempty"` + Weight *float32 `json:"weight,omitempty"` + Score *float32 `json:"score,omitempty"` + OrigScore *float32 `json:"origScore,omitempty"` + Notified bool `json:"notified,omitempty"` + Metadata []byte `json:"metadata,omitempty"` } func (q *Queries) AddAlert(ctx context.Context, arg AddAlertParams) error { @@ -95,24 +95,24 @@ $18 ` type AddCallParams struct { - ID uuid.UUID `json:"id"` - Submitter *int32 `json:"submitter"` - System int `json:"system"` - Talkgroup int `json:"talkgroup"` - CallDate pgtype.Timestamptz `json:"callDate"` - AudioName *string `json:"audioName"` - AudioBlob []byte `json:"audioBlob"` - AudioType *string `json:"audioType"` - AudioUrl *string `json:"audioUrl"` - Duration *int32 `json:"duration"` - 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"` - Source int `json:"source"` + ID uuid.UUID `json:"id,omitempty"` + Submitter *int32 `json:"submitter,omitempty"` + System int `json:"system,omitempty"` + Talkgroup int `json:"talkgroup,omitempty"` + CallDate pgtype.Timestamptz `json:"callDate,omitempty"` + AudioName *string `json:"audioName,omitempty"` + AudioBlob []byte `json:"audioBlob,omitempty"` + AudioType *string `json:"audioType,omitempty"` + AudioUrl *string `json:"audioUrl,omitempty"` + Duration *int32 `json:"duration,omitempty"` + 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"` + Source int `json:"source,omitempty"` } func (q *Queries) AddCall(ctx context.Context, arg AddCallParams) error { @@ -193,24 +193,24 @@ WHERE id = $1 ` type GetCallRow struct { - ID uuid.UUID `json:"id"` - Submitter *int32 `json:"submitter"` - System int `json:"system"` - Talkgroup int `json:"talkgroup"` - CallDate pgtype.Timestamptz `json:"callDate"` - AudioName *string `json:"audioName"` - AudioType *string `json:"audioType"` - AudioUrl *string `json:"audioUrl"` - Duration *int32 `json:"duration"` - 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"` - Source int `json:"source"` - Transcript *string `json:"transcript"` + ID uuid.UUID `json:"id,omitempty"` + Submitter *int32 `json:"submitter,omitempty"` + System int `json:"system,omitempty"` + Talkgroup int `json:"talkgroup,omitempty"` + CallDate pgtype.Timestamptz `json:"callDate,omitempty"` + AudioName *string `json:"audioName,omitempty"` + AudioType *string `json:"audioType,omitempty"` + AudioUrl *string `json:"audioUrl,omitempty"` + Duration *int32 `json:"duration,omitempty"` + 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"` + Source int `json:"source,omitempty"` + Transcript *string `json:"transcript,omitempty"` } func (q *Queries) GetCall(ctx context.Context, id uuid.UUID) (GetCallRow, error) { @@ -258,10 +258,10 @@ WHERE sc.id = $1 ` type GetCallAudioByIDRow struct { - CallDate pgtype.Timestamptz `json:"callDate"` - AudioName *string `json:"audioName"` - AudioType *string `json:"audioType"` - AudioBlob []byte `json:"audioBlob"` + CallDate pgtype.Timestamptz `json:"callDate,omitempty"` + AudioName *string `json:"audioName,omitempty"` + AudioType *string `json:"audioType,omitempty"` + AudioBlob []byte `json:"audioBlob,omitempty"` } func (q *Queries) GetCallAudioByID(ctx context.Context, id uuid.UUID) (GetCallAudioByIDRow, error) { @@ -323,12 +323,12 @@ CASE WHEN $4::TEXT[] IS NOT NULL THEN ` type ListCallsCountParams struct { - Start pgtype.Timestamptz `json:"start"` - End pgtype.Timestamptz `json:"end"` - TagsAny []string `json:"tagsAny"` - TagsNot []string `json:"tagsNot"` - TGFilter *string `json:"tgFilter"` - LongerThan pgtype.Numeric `json:"longerThan"` + Start pgtype.Timestamptz `json:"start,omitempty"` + End pgtype.Timestamptz `json:"end,omitempty"` + TagsAny []string `json:"tagsAny,omitempty"` + TagsNot []string `json:"tagsNot,omitempty"` + TGFilter *string `json:"tgFilter,omitempty"` + LongerThan pgtype.Numeric `json:"longerThan,omitempty"` } func (q *Queries) ListCallsCount(ctx context.Context, arg ListCallsCountParams) (int64, error) { @@ -384,25 +384,25 @@ FETCH NEXT $9 ROWS ONLY ` type ListCallsPParams struct { - Start pgtype.Timestamptz `json:"start"` - End pgtype.Timestamptz `json:"end"` - TagsAny []string `json:"tagsAny"` - TagsNot []string `json:"tagsNot"` - TGFilter *string `json:"tgFilter"` - LongerThan pgtype.Numeric `json:"longerThan"` - Direction string `json:"direction"` - Offset int32 `json:"offset"` - PerPage int32 `json:"perPage"` + Start pgtype.Timestamptz `json:"start,omitempty"` + End pgtype.Timestamptz `json:"end,omitempty"` + TagsAny []string `json:"tagsAny,omitempty"` + TagsNot []string `json:"tagsNot,omitempty"` + TGFilter *string `json:"tgFilter,omitempty"` + LongerThan pgtype.Numeric `json:"longerThan,omitempty"` + Direction string `json:"direction,omitempty"` + Offset int32 `json:"offset,omitempty"` + PerPage int32 `json:"perPage,omitempty"` } 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"` - TalkerAlias *string `json:"talkerAlias"` - Incidents int64 `json:"incidents"` + ID uuid.UUID `json:"id,omitempty"` + CallDate pgtype.Timestamptz `json:"callDate,omitempty"` + Duration *int32 `json:"duration,omitempty"` + SystemID int `json:"systemId,omitempty"` + TGID int `json:"tgid,omitempty"` + TalkerAlias *string `json:"talkerAlias,omitempty"` + Incidents int64 `json:"incidents,omitempty"` } func (q *Queries) ListCallsP(ctx context.Context, arg ListCallsPParams) ([]ListCallsPRow, error) { From cbe4bab78ff7a4beb2b07a201c44ded6d83bd7ab Mon Sep 17 00:00:00 2001 From: Daniel Ponte Date: Sat, 22 Feb 2025 15:53:45 -0500 Subject: [PATCH 3/6] Be selective --- pkg/database/calls.sql.go | 132 ++++++++++++++++++------------------ util/omitempty/omitempty.go | 42 ++++++++++-- 2 files changed, 102 insertions(+), 72 deletions(-) diff --git a/pkg/database/calls.sql.go b/pkg/database/calls.sql.go index b997780..45d1702 100644 --- a/pkg/database/calls.sql.go +++ b/pkg/database/calls.sql.go @@ -28,14 +28,14 @@ VALUES ` type AddAlertParams struct { - Time pgtype.Timestamptz `json:"time,omitempty"` - TGID int `json:"tgid,omitempty"` - SystemID int `json:"systemId,omitempty"` - Weight *float32 `json:"weight,omitempty"` - Score *float32 `json:"score,omitempty"` - OrigScore *float32 `json:"origScore,omitempty"` - Notified bool `json:"notified,omitempty"` - Metadata []byte `json:"metadata,omitempty"` + Time pgtype.Timestamptz `json:"time"` + TGID int `json:"tgid"` + SystemID int `json:"systemId"` + Weight *float32 `json:"weight"` + Score *float32 `json:"score"` + OrigScore *float32 `json:"origScore"` + Notified bool `json:"notified"` + Metadata []byte `json:"metadata"` } func (q *Queries) AddAlert(ctx context.Context, arg AddAlertParams) error { @@ -95,24 +95,24 @@ $18 ` type AddCallParams struct { - ID uuid.UUID `json:"id,omitempty"` - Submitter *int32 `json:"submitter,omitempty"` - System int `json:"system,omitempty"` - Talkgroup int `json:"talkgroup,omitempty"` - CallDate pgtype.Timestamptz `json:"callDate,omitempty"` - AudioName *string `json:"audioName,omitempty"` - AudioBlob []byte `json:"audioBlob,omitempty"` - AudioType *string `json:"audioType,omitempty"` - AudioUrl *string `json:"audioUrl,omitempty"` - Duration *int32 `json:"duration,omitempty"` - Frequency int `json:"frequency,omitempty"` - Frequencies []int `json:"frequencies,omitempty"` - Patches []int `json:"patches,omitempty"` + ID uuid.UUID `json:"id"` + Submitter *int32 `json:"submitter"` + System int `json:"system"` + Talkgroup int `json:"talkgroup"` + CallDate pgtype.Timestamptz `json:"callDate"` + AudioName *string `json:"audioName"` + AudioBlob []byte `json:"audioBlob"` + AudioType *string `json:"audioType"` + AudioUrl *string `json:"audioUrl"` + Duration *int32 `json:"duration"` + Frequency int `json:"frequency"` + Frequencies []int `json:"frequencies"` + Patches []int `json:"patches"` TalkerAlias *string `json:"talkerAlias,omitempty"` - TGLabel *string `json:"tgLabel,omitempty"` - TGAlphaTag *string `json:"tgAlphaTag,omitempty"` - TGGroup *string `json:"tgGroup,omitempty"` - Source int `json:"source,omitempty"` + TGLabel *string `json:"tgLabel"` + TGAlphaTag *string `json:"tgAlphaTag"` + TGGroup *string `json:"tgGroup"` + Source int `json:"source"` } func (q *Queries) AddCall(ctx context.Context, arg AddCallParams) error { @@ -193,24 +193,24 @@ WHERE id = $1 ` type GetCallRow struct { - ID uuid.UUID `json:"id,omitempty"` - Submitter *int32 `json:"submitter,omitempty"` - System int `json:"system,omitempty"` - Talkgroup int `json:"talkgroup,omitempty"` - CallDate pgtype.Timestamptz `json:"callDate,omitempty"` - AudioName *string `json:"audioName,omitempty"` - AudioType *string `json:"audioType,omitempty"` - AudioUrl *string `json:"audioUrl,omitempty"` - Duration *int32 `json:"duration,omitempty"` - Frequency int `json:"frequency,omitempty"` - Frequencies []int `json:"frequencies,omitempty"` - Patches []int `json:"patches,omitempty"` + ID uuid.UUID `json:"id"` + Submitter *int32 `json:"submitter"` + System int `json:"system"` + Talkgroup int `json:"talkgroup"` + CallDate pgtype.Timestamptz `json:"callDate"` + AudioName *string `json:"audioName"` + AudioType *string `json:"audioType"` + AudioUrl *string `json:"audioUrl"` + Duration *int32 `json:"duration"` + Frequency int `json:"frequency"` + Frequencies []int `json:"frequencies"` + Patches []int `json:"patches"` TalkerAlias *string `json:"talkerAlias,omitempty"` - TGLabel *string `json:"tgLabel,omitempty"` - TGAlphaTag *string `json:"tgAlphaTag,omitempty"` - TGGroup *string `json:"tgGroup,omitempty"` - Source int `json:"source,omitempty"` - Transcript *string `json:"transcript,omitempty"` + TGLabel *string `json:"tgLabel"` + TGAlphaTag *string `json:"tgAlphaTag"` + TGGroup *string `json:"tgGroup"` + Source int `json:"source"` + Transcript *string `json:"transcript"` } func (q *Queries) GetCall(ctx context.Context, id uuid.UUID) (GetCallRow, error) { @@ -258,10 +258,10 @@ WHERE sc.id = $1 ` type GetCallAudioByIDRow struct { - CallDate pgtype.Timestamptz `json:"callDate,omitempty"` - AudioName *string `json:"audioName,omitempty"` - AudioType *string `json:"audioType,omitempty"` - AudioBlob []byte `json:"audioBlob,omitempty"` + CallDate pgtype.Timestamptz `json:"callDate"` + AudioName *string `json:"audioName"` + AudioType *string `json:"audioType"` + AudioBlob []byte `json:"audioBlob"` } func (q *Queries) GetCallAudioByID(ctx context.Context, id uuid.UUID) (GetCallAudioByIDRow, error) { @@ -323,12 +323,12 @@ CASE WHEN $4::TEXT[] IS NOT NULL THEN ` type ListCallsCountParams struct { - Start pgtype.Timestamptz `json:"start,omitempty"` - End pgtype.Timestamptz `json:"end,omitempty"` - TagsAny []string `json:"tagsAny,omitempty"` - TagsNot []string `json:"tagsNot,omitempty"` - TGFilter *string `json:"tgFilter,omitempty"` - LongerThan pgtype.Numeric `json:"longerThan,omitempty"` + Start pgtype.Timestamptz `json:"start"` + End pgtype.Timestamptz `json:"end"` + TagsAny []string `json:"tagsAny"` + TagsNot []string `json:"tagsNot"` + TGFilter *string `json:"tgFilter"` + LongerThan pgtype.Numeric `json:"longerThan"` } func (q *Queries) ListCallsCount(ctx context.Context, arg ListCallsCountParams) (int64, error) { @@ -384,23 +384,23 @@ FETCH NEXT $9 ROWS ONLY ` type ListCallsPParams struct { - Start pgtype.Timestamptz `json:"start,omitempty"` - End pgtype.Timestamptz `json:"end,omitempty"` - TagsAny []string `json:"tagsAny,omitempty"` - TagsNot []string `json:"tagsNot,omitempty"` - TGFilter *string `json:"tgFilter,omitempty"` - LongerThan pgtype.Numeric `json:"longerThan,omitempty"` - Direction string `json:"direction,omitempty"` - Offset int32 `json:"offset,omitempty"` - PerPage int32 `json:"perPage,omitempty"` + Start pgtype.Timestamptz `json:"start"` + End pgtype.Timestamptz `json:"end"` + TagsAny []string `json:"tagsAny"` + TagsNot []string `json:"tagsNot"` + TGFilter *string `json:"tgFilter"` + LongerThan pgtype.Numeric `json:"longerThan"` + Direction string `json:"direction"` + Offset int32 `json:"offset"` + PerPage int32 `json:"perPage"` } type ListCallsPRow struct { - ID uuid.UUID `json:"id,omitempty"` - CallDate pgtype.Timestamptz `json:"callDate,omitempty"` - Duration *int32 `json:"duration,omitempty"` - SystemID int `json:"systemId,omitempty"` - TGID int `json:"tgid,omitempty"` + 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,omitempty"` Incidents int64 `json:"incidents,omitempty"` } diff --git a/util/omitempty/omitempty.go b/util/omitempty/omitempty.go index 801c3d5..4ecc0af 100644 --- a/util/omitempty/omitempty.go +++ b/util/omitempty/omitempty.go @@ -12,19 +12,46 @@ import ( "strings" ) -var filePaths = []string{ - "./pkg/database/models.go", - "./pkg/database/calls.sql.go", +type FileMap map[string]FieldDecider + +var filePaths = FileMap{ + "./pkg/database/models.go": AllFields{}, + "./pkg/database/calls.sql.go": FieldMap{ + "TalkerAlias": true, + "Incidents": true, + }, +} + +type FieldDecider interface { + Check(fields []*ast.Ident) bool +} + +type FieldMap map[string]bool + +func (fm FieldMap) Check(f []*ast.Ident) bool { + for _, v := range f { + if v != nil && fm[v.Name] { + return true + } + } + + return false +} + +type AllFields struct{} + +func (AllFields) Check(_ []*ast.Ident) bool { + return true } func main() { // Parse the source code - for _, v := range filePaths { - process(v) + for k, v := range filePaths { + process(k, v) } } -func process(filePath string) { +func process(filePath string, fd FieldDecider) { fset := token.NewFileSet() f, err := parser.ParseFile(fset, filePath, nil, parser.ParseComments) if err != nil { @@ -36,6 +63,9 @@ func process(filePath string) { switch x := n.(type) { case *ast.StructType: for _, field := range x.Fields.List { + if !fd.Check(field.Names) { + continue + } if field.Tag == nil { continue } From d5b5cb48938c546c8623164e7a77478586195001 Mon Sep 17 00:00:00 2001 From: Daniel Ponte Date: Tue, 18 Feb 2025 08:58:12 -0500 Subject: [PATCH 4/6] 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 ca1be29aa2d7740103ec619730dfd1b20d64de7d Mon Sep 17 00:00:00 2001 From: Daniel Ponte Date: Tue, 18 Feb 2025 09:02:39 -0500 Subject: [PATCH 5/6] 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 f28148064d8c2ebd98814db386e10c0d93b4e9c1 Mon Sep 17 00:00:00 2001 From: Daniel Ponte Date: Fri, 21 Feb 2025 20:59:08 -0500 Subject: [PATCH 6/6] 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 }