Skip to content

Commit 2d33862

Browse files
alicodingclaude
andauthored
build(deps): dbos-transact 1.2.0, kin-openapi 0.147.0, sqlite 1.57.0; run-duration guard tolerates DBOS ms quantization (#417)
Supersedes Dependabot #412, which failed CI on two independent axes: 1. go-get-proxied v1.4.1 raises its go directive to 1.26, dragging this module's directive past CI's pinned go-version '1.25' (GOTOOLCHAIN=local) and failing every Go job at package load. Held at v1.4.0 with a dependabot.yml ignore naming the lift condition (CI's Go moving to 1.26); the other three bumps keep go 1.25.7. 2. DBOS 1.2.0's faster completion timing exposes a storage-quantization artifact: sysdb stores created_at rounded to the nearest millisecond but completed_at truncated, so a sub-millisecond run can read as completing 1ms before it started. Mill's runDuration treated any negative span as clock skew and dropped the run from AvgDuration (SampleSize undercounted, ~1 in 20 locally at -count=20). runDuration now accepts up to 1ms negative span, clamped to zero, with the boundary pinned in TestRunDuration's table (1ms valid, 2ms invalid). go test ./... green; golangci-lint clean on both tag sets; TestHomeMetrics_AvgDurationAndLastTriggeredAt_WiredFromRealRuns green at -count=25 under DBOS 1.2.0. Claude-Session: https://claude.ai/code/session_012im1JxQQV2ahnXzZDdVmZq Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 parent 07b3a05 commit 2d33862

5 files changed

Lines changed: 33 additions & 12 deletions

File tree

.github/dependabot.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@ updates:
1818
interval: weekly
1919
day: monday
2020
open-pull-requests-limit: 5
21+
ignore:
22+
# go-get-proxied v1.4.1+ raises its go directive to 1.26, which
23+
# drags this module's go directive past CI's pinned go-version
24+
# '1.25' (GOTOOLCHAIN=local) and fails every Go job at package
25+
# load. Lift when CI's Go moves to 1.26.
26+
- dependency-name: github.com/rapid7/go-get-proxied
27+
versions: [">= 1.4.1"]
2128
groups:
2229
go-dependencies:
2330
update-types:

go.mod

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ require (
77
github.com/JohannesKaufmann/html-to-markdown/v2 v2.5.2
88
github.com/PuerkitoBio/goquery v1.12.0
99
github.com/andybalholm/cascadia v1.3.4
10-
github.com/dbos-inc/dbos-transact-golang v1.1.0
10+
github.com/dbos-inc/dbos-transact-golang v1.2.0
1111
github.com/expr-lang/expr v1.17.8
1212
github.com/fsnotify/fsnotify v1.10.1
13-
github.com/getkin/kin-openapi v0.146.0
13+
github.com/getkin/kin-openapi v0.147.0
1414
github.com/go-jose/go-jose/v4 v4.1.4
1515
github.com/google/uuid v1.6.0
1616
github.com/hashicorp/go-retryablehttp v0.7.8
@@ -30,7 +30,7 @@ require (
3030
golang.org/x/oauth2 v0.36.0
3131
golang.org/x/text v0.41.0
3232
gopkg.in/yaml.v3 v3.0.1
33-
modernc.org/sqlite v1.56.0
33+
modernc.org/sqlite v1.57.0
3434
)
3535

3636
require (

go.sum

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ github.com/danieljoos/wincred v1.2.3/go.mod h1:6qqX0WNrS4RzPZ1tnroDzq9kY3fu1KwE7
2121
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
2222
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
2323
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
24-
github.com/dbos-inc/dbos-transact-golang v1.1.0 h1:J2uSNUDdfNx1Qbxg67k0cwm3xZ6xbtJ4SXIIyu33RZ8=
25-
github.com/dbos-inc/dbos-transact-golang v1.1.0/go.mod h1:cOOJfxDEnhdZd39EpYWps4mva6JxKyyKztyWzGxXpCE=
24+
github.com/dbos-inc/dbos-transact-golang v1.2.0 h1:o1CaHn+E7FQSBXJ/rUP7vV+yTYZB7vhzd98dnyxLlMA=
25+
github.com/dbos-inc/dbos-transact-golang v1.2.0/go.mod h1:HEjtVW5wgpkpTIAp+FAIVldSr+oiiolyFZ+2RJda8gI=
2626
github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ=
2727
github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
2828
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
@@ -33,8 +33,8 @@ github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
3333
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
3434
github.com/fsnotify/fsnotify v1.10.1 h1:b0/UzAf9yR5rhf3RPm9gf3ehBPpf0oZKIjtpKrx59Ho=
3535
github.com/fsnotify/fsnotify v1.10.1/go.mod h1:TLheqan6HD6GBK6PrDWyDPBaEV8LspOxvPSjC+bVfgo=
36-
github.com/getkin/kin-openapi v0.146.0 h1:RA/1RdxrSJW4oc1+6IfnYB6AO9CaGy8GTKPh0k4Ordo=
37-
github.com/getkin/kin-openapi v0.146.0/go.mod h1:3BH9M9XDe/y9M5DSvEocVYAYq1w0qrhJHjC/vZi0AaY=
36+
github.com/getkin/kin-openapi v0.147.0 h1:s+Xsm9gUMPJbgCnABZ2to3zSQQ5A9dyj/zo62VVsldY=
37+
github.com/getkin/kin-openapi v0.147.0/go.mod h1:3BH9M9XDe/y9M5DSvEocVYAYq1w0qrhJHjC/vZi0AaY=
3838
github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA=
3939
github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=
4040
github.com/go-json-experiment/json v0.0.0-20251027170946-4849db3c2f7e h1:Lf/gRkoycfOBPa42vU2bbgPurFong6zXeFtPoxholzU=
@@ -216,8 +216,8 @@ modernc.org/opt v0.2.0 h1:tGyef5ApycA7FSEOMraay9SaTk5zmbx7Tu+cJs4QKZg=
216216
modernc.org/opt v0.2.0/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
217217
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
218218
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
219-
modernc.org/sqlite v1.56.0 h1:/D8e2RfFqoy/Zc6PuC76U28zFwmI/sYx1Kjm4yEn9e0=
220-
modernc.org/sqlite v1.56.0/go.mod h1:yCJ2cmAaIkHQ25oXWrF8H4O1lIfPYPR26yCEDj2P3pQ=
219+
modernc.org/sqlite v1.57.0 h1:qNQP6xnx5M0ISNtlnxoOX0+cD5bJ0/gr9aMmndFczzg=
220+
modernc.org/sqlite v1.57.0/go.mod h1:yCJ2cmAaIkHQ25oXWrF8H4O1lIfPYPR26yCEDj2P3pQ=
221221
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
222222
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
223223
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=

internal/services/executionsvc/executionservice_home.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -305,13 +305,22 @@ func (e *ExecutionService) timeSavedFor(runs []RunSummary) TimeSavedMetric {
305305
// zero. CompletedAt exactly equal to StartedAt is a real, valid
306306
// zero-duration result -- confirmed against real DBOS timing (a purely
307307
// local, no-I/O step can genuinely complete within the same recorded
308-
// millisecond) -- only CompletedAt strictly BEFORE StartedAt (clock
308+
// millisecond). CompletedAt up to 1ms BEFORE StartedAt is also valid,
309+
// clamped to zero: DBOS's sysdb stores created_at rounded to the
310+
// nearest millisecond (Round(time.Millisecond).UnixMilli()) but
311+
// completed_at truncated (UnixMilli()), so a run finishing within the
312+
// same half-millisecond it was created can read as completing 1ms
313+
// before it started. Only a gap beyond that quantization window (clock
309314
// skew, a checkpoint race) is treated as invalid.
310315
func runDuration(r RunSummary) (time.Duration, bool) {
311-
if r.CompletedAt.IsZero() || r.CompletedAt.Before(r.StartedAt) {
316+
if r.CompletedAt.IsZero() || r.CompletedAt.Before(r.StartedAt.Add(-time.Millisecond)) {
312317
return 0, false
313318
}
314-
return r.CompletedAt.Sub(r.StartedAt), true
319+
d := r.CompletedAt.Sub(r.StartedAt)
320+
if d < 0 {
321+
d = 0
322+
}
323+
return d, true
315324
}
316325

317326
func avgDurationFor(runs []RunSummary) AvgDurationMetric {

internal/services/executionsvc/executionservice_home_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,11 @@ func TestRunDuration_ExcludesInFlightAndNonPositiveSpans(t *testing.T) {
132132
{"completed", RunSummary{StartedAt: start, CompletedAt: start.Add(30 * time.Second)}, 30 * time.Second, true},
133133
{"still in flight (zero CompletedAt)", RunSummary{StartedAt: start}, 0, false},
134134
{"completed in the same instant (real, valid zero duration)", RunSummary{StartedAt: start, CompletedAt: start}, 0, true},
135+
// Regression: DBOS stores created_at rounded to the nearest ms but
136+
// completed_at truncated, so a sub-millisecond run can read as
137+
// completing 1ms before it started -- valid, clamped to zero.
138+
{"completed 1ms before started (DBOS ms quantization)", RunSummary{StartedAt: start, CompletedAt: start.Add(-time.Millisecond)}, 0, true},
139+
{"completed 2ms before started (beyond quantization: clock skew)", RunSummary{StartedAt: start, CompletedAt: start.Add(-2 * time.Millisecond)}, 0, false},
135140
{"completed before started (clock skew)", RunSummary{StartedAt: start, CompletedAt: start.Add(-time.Second)}, 0, false},
136141
}
137142
for _, c := range cases {

0 commit comments

Comments
 (0)