Skip to content

chore: update to coder/quartz v0.2.0 #18007

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 27, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions agent/agentcontainers/api_test.go
Original file line number Diff line number Diff line change
@@ -257,7 +257,7 @@ func TestAPI(t *testing.T) {

// Make sure the ticker function has been registered
// before advancing the clock.
tickerTrap.MustWait(ctx).Release()
tickerTrap.MustWait(ctx).MustRelease(ctx)
tickerTrap.Close()

// Initial request returns the initial data.
@@ -432,7 +432,7 @@ func TestAPI(t *testing.T) {

// Make sure the ticker function has been registered
// before advancing the clock.
tickerTrap.MustWait(ctx).Release()
tickerTrap.MustWait(ctx).MustRelease(ctx)
tickerTrap.Close()

for i := range tt.wantStatus {
@@ -486,7 +486,7 @@ func TestAPI(t *testing.T) {
nowRecreateSuccessTrap.Close()
// The timestamp for the error will be stored, which gives
// us a good anchor point to know when to do our request.
nowRecreateErrorTrap.MustWait(ctx).Release()
nowRecreateErrorTrap.MustWait(ctx).MustRelease(ctx)
nowRecreateErrorTrap.Close()

// Advance the clock to run the devcontainer state update routine.
@@ -507,7 +507,7 @@ func TestAPI(t *testing.T) {
}

// Ensure the devcontainer ends up in success state.
nowRecreateSuccessTrap.MustWait(ctx).Release()
nowRecreateSuccessTrap.MustWait(ctx).MustRelease(ctx)
nowRecreateSuccessTrap.Close()

// Advance the clock to run the devcontainer state update routine.
@@ -911,7 +911,7 @@ func TestAPI(t *testing.T) {

// Make sure the ticker function has been registered
// before advancing any use of mClock.Advance.
tickerTrap.MustWait(ctx).Release()
tickerTrap.MustWait(ctx).MustRelease(ctx)
tickerTrap.Close()

// Make sure the start loop has been called.
@@ -1007,7 +1007,7 @@ func TestAPI(t *testing.T) {

// Make sure the ticker function has been registered
// before advancing any use of mClock.Advance.
tickerTrap.MustWait(ctx).Release()
tickerTrap.MustWait(ctx).MustRelease(ctx)
tickerTrap.Close()

// Call the list endpoint first to ensure config files are
18 changes: 9 additions & 9 deletions agent/apphealth_test.go
Original file line number Diff line number Diff line change
@@ -78,7 +78,7 @@ func TestAppHealth_Healthy(t *testing.T) {
healthchecksStarted := make([]string, 2)
for i := 0; i < 2; i++ {
c := healthcheckTrap.MustWait(ctx)
c.Release()
c.MustRelease(ctx)
healthchecksStarted[i] = c.Tags[1]
}
slices.Sort(healthchecksStarted)
@@ -87,7 +87,7 @@ func TestAppHealth_Healthy(t *testing.T) {
// advance the clock 1ms before the report ticker starts, so that it's not
// simultaneous with the checks.
mClock.Advance(time.Millisecond).MustWait(ctx)
reportTrap.MustWait(ctx).Release()
reportTrap.MustWait(ctx).MustRelease(ctx)

mClock.Advance(999 * time.Millisecond).MustWait(ctx) // app2 is now healthy

@@ -143,11 +143,11 @@ func TestAppHealth_500(t *testing.T) {

fakeAPI, closeFn := setupAppReporter(ctx, t, slices.Clone(apps), handlers, mClock)
defer closeFn()
healthcheckTrap.MustWait(ctx).Release()
healthcheckTrap.MustWait(ctx).MustRelease(ctx)
// advance the clock 1ms before the report ticker starts, so that it's not
// simultaneous with the checks.
mClock.Advance(time.Millisecond).MustWait(ctx)
reportTrap.MustWait(ctx).Release()
reportTrap.MustWait(ctx).MustRelease(ctx)

mClock.Advance(999 * time.Millisecond).MustWait(ctx) // check gets triggered
mClock.Advance(time.Millisecond).MustWait(ctx) // report gets triggered, but unsent since we are at the threshold
@@ -202,25 +202,25 @@ func TestAppHealth_Timeout(t *testing.T) {

fakeAPI, closeFn := setupAppReporter(ctx, t, apps, handlers, mClock)
defer closeFn()
healthcheckTrap.MustWait(ctx).Release()
healthcheckTrap.MustWait(ctx).MustRelease(ctx)
// advance the clock 1ms before the report ticker starts, so that it's not
// simultaneous with the checks.
mClock.Set(ms(1)).MustWait(ctx)
reportTrap.MustWait(ctx).Release()
reportTrap.MustWait(ctx).MustRelease(ctx)

w := mClock.Set(ms(1000)) // 1st check starts
timeoutTrap.MustWait(ctx).Release()
timeoutTrap.MustWait(ctx).MustRelease(ctx)
mClock.Set(ms(1001)).MustWait(ctx) // report tick, no change
mClock.Set(ms(1999)) // timeout pops
w.MustWait(ctx) // 1st check finished
w = mClock.Set(ms(2000)) // 2nd check starts
timeoutTrap.MustWait(ctx).Release()
timeoutTrap.MustWait(ctx).MustRelease(ctx)
mClock.Set(ms(2001)).MustWait(ctx) // report tick, no change
mClock.Set(ms(2999)) // timeout pops
w.MustWait(ctx) // 2nd check finished
// app is now unhealthy after 2 timeouts
mClock.Set(ms(3000)) // 3rd check starts
timeoutTrap.MustWait(ctx).Release()
timeoutTrap.MustWait(ctx).MustRelease(ctx)
mClock.Set(ms(3001)).MustWait(ctx) // report tick, sends changes

update := testutil.TryReceive(ctx, t, fakeAPI.AppHealthCh())
2 changes: 1 addition & 1 deletion cli/ssh_internal_test.go
Original file line number Diff line number Diff line change
@@ -206,7 +206,7 @@ func TestCloserStack_Timeout(t *testing.T) {
defer close(closed)
uut.close(nil)
}()
trap.MustWait(ctx).Release()
trap.MustWait(ctx).MustRelease(ctx)
// top starts right away, but it hangs
testutil.TryReceive(ctx, t, ac[2].started)
// timer pops and we start the middle one
2 changes: 1 addition & 1 deletion coderd/autobuild/notify/notifier_test.go
Original file line number Diff line number Diff line change
@@ -104,7 +104,7 @@ func TestNotifier(t *testing.T) {
n := notify.New(cond, testCase.PollInterval, testCase.Countdown, notify.WithTestClock(mClock))
defer n.Close()

trap.MustWait(ctx).Release() // ensure ticker started
trap.MustWait(ctx).MustRelease(ctx) // ensure ticker started
for i := 0; i < testCase.NTicks; i++ {
interval, w := mClock.AdvanceNext()
w.MustWait(ctx)
2 changes: 1 addition & 1 deletion coderd/cryptokeys/cache_test.go
Original file line number Diff line number Diff line change
@@ -423,7 +423,7 @@ func TestCryptoKeyCache(t *testing.T) {
require.Equal(t, 2, ff.called)
require.Equal(t, decodedSecret(t, newKey), key)

trapped.Release()
trapped.MustRelease(ctx)
wait.MustWait(ctx)
require.Equal(t, 2, ff.called)
trap.Close()
2 changes: 1 addition & 1 deletion coderd/cryptokeys/rotate_test.go
Original file line number Diff line number Diff line change
@@ -72,7 +72,7 @@ func TestRotator(t *testing.T) {
require.Len(t, dbkeys, initialKeyLen)
requireContainsAllFeatures(t, dbkeys)

trap.MustWait(ctx).Release()
trap.MustWait(ctx).MustRelease(ctx)
_, wait := clock.AdvanceNext()
wait.MustWait(ctx)

6 changes: 3 additions & 3 deletions coderd/database/dbpurge/dbpurge_test.go
Original file line number Diff line number Diff line change
@@ -279,18 +279,18 @@ func awaitDoTick(ctx context.Context, t *testing.T, clk *quartz.Mock) chan struc
defer trapStop.Close()
defer trapNow.Close()
// Wait for the initial tick signified by a call to Now().
trapNow.MustWait(ctx).Release()
trapNow.MustWait(ctx).MustRelease(ctx)
// doTick runs here. Wait for the next
// ticker reset event that signifies it's completed.
trapReset.MustWait(ctx).Release()
trapReset.MustWait(ctx).MustRelease(ctx)
// Ensure that the next tick happens in 10 minutes from start.
d, w := clk.AdvanceNext()
if !assert.Equal(t, 10*time.Minute, d) {
return
}
w.MustWait(ctx)
// Wait for the ticker stop event.
trapStop.MustWait(ctx).Release()
trapStop.MustWait(ctx).MustRelease(ctx)
}()

return ch
6 changes: 3 additions & 3 deletions coderd/database/pubsub/watchdog_test.go
Original file line number Diff line number Diff line change
@@ -32,7 +32,7 @@ func TestWatchdog_NoTimeout(t *testing.T) {
// right baseline time.
pc, err := pubTrap.Wait(ctx)
require.NoError(t, err)
pc.Release()
pc.MustRelease(ctx)
require.Equal(t, 15*time.Second, pc.Duration)

// we subscribe after starting the timer, so we know the timer also starts
@@ -66,7 +66,7 @@ func TestWatchdog_NoTimeout(t *testing.T) {
}()
sc, err := subTrap.Wait(ctx) // timer.Stop() called
require.NoError(t, err)
sc.Release()
sc.MustRelease(ctx)
err = testutil.TryReceive(ctx, t, errCh)
require.NoError(t, err)
}
@@ -88,7 +88,7 @@ func TestWatchdog_Timeout(t *testing.T) {
// right baseline time.
pc, err := pubTrap.Wait(ctx)
require.NoError(t, err)
pc.Release()
pc.MustRelease(ctx)
require.Equal(t, 15*time.Second, pc.Duration)

// we subscribe after starting the timer, so we know the timer also starts
4 changes: 2 additions & 2 deletions coderd/notifications/metrics_test.go
Original file line number Diff line number Diff line change
@@ -276,8 +276,8 @@ func TestPendingUpdatesMetric(t *testing.T) {
require.NoError(t, err)

mgr.Run(ctx)
trap.MustWait(ctx).Release() // ensures ticker has been set
fetchTrap.MustWait(ctx).Release()
trap.MustWait(ctx).MustRelease(ctx) // ensures ticker has been set
fetchTrap.MustWait(ctx).MustRelease(ctx)

// Advance to the first fetch
mClock.Advance(cfg.FetchInterval.Value()).MustWait(ctx)
4 changes: 2 additions & 2 deletions coderd/notifications/notifications_test.go
Original file line number Diff line number Diff line change
@@ -341,8 +341,8 @@ func TestBackpressure(t *testing.T) {

// Start the notifier.
mgr.Run(ctx)
syncTrap.MustWait(ctx).Release()
fetchTrap.MustWait(ctx).Release()
syncTrap.MustWait(ctx).MustRelease(ctx)
fetchTrap.MustWait(ctx).MustRelease(ctx)

// THEN:

2 changes: 1 addition & 1 deletion enterprise/coderd/prebuilds/reconcile_test.go
Original file line number Diff line number Diff line change
@@ -1137,7 +1137,7 @@ func TestRunLoop(t *testing.T) {
trap := clock.Trap().NewTicker()
go reconciler.Run(ctx)
// wait until ticker is initialized
trap.MustWait(ctx).Release()
trap.MustWait(ctx).MustRelease(ctx)
// start 1st iteration of ReconciliationLoop
// NOTE: at this point MustWait waits that iteration is started (ReconcileAll is called), but it doesn't wait until it completes
clock.Advance(cfg.ReconciliationInterval.Value()).MustWait(ctx)
13 changes: 6 additions & 7 deletions enterprise/tailnet/pgcoord_internal_test.go
Original file line number Diff line number Diff line change
@@ -63,9 +63,8 @@ func TestHeartbeats_Cleanup(t *testing.T) {
uut.wg.Add(1)
go uut.cleanupLoop()

call, err := trap.Wait(ctx)
require.NoError(t, err)
call.Release()
call := trap.MustWait(ctx)
call.MustRelease(ctx)
require.Equal(t, cleanupPeriod, call.Duration)
mClock.Advance(cleanupPeriod).MustWait(ctx)
}
@@ -99,7 +98,7 @@ func TestHeartbeats_recvBeat_resetSkew(t *testing.T) {
// coord 3 heartbeat comes very soon after
mClock.Advance(time.Millisecond).MustWait(ctx)
go uut.listen(ctx, []byte(coord3.String()), nil)
trap.MustWait(ctx).Release()
trap.MustWait(ctx).MustRelease(ctx)

// both coordinators are present
uut.lock.RLock()
@@ -112,11 +111,11 @@ func TestHeartbeats_recvBeat_resetSkew(t *testing.T) {
// however, several ms pass between expiring 2 and computing the time until 3 expires
c := trap.MustWait(ctx)
mClock.Advance(2 * time.Millisecond).MustWait(ctx) // 3 has now expired _in the past_
c.Release()
c.MustRelease(ctx)
w.MustWait(ctx)

// expired in the past means we immediately reschedule checkExpiry, so we get another call
trap.MustWait(ctx).Release()
trap.MustWait(ctx).MustRelease(ctx)

uut.lock.RLock()
require.NotContains(t, uut.coordinators, coord2)
@@ -411,7 +410,7 @@ func TestPGCoordinatorUnhealthy(t *testing.T) {
expectedPeriod := HeartbeatPeriod
tfCall, err := tfTrap.Wait(ctx)
require.NoError(t, err)
tfCall.Release()
tfCall.MustRelease(ctx)
require.Equal(t, expectedPeriod, tfCall.Duration)

// Now that the ticker has started, we can advance 2 more beats to get to 3
10 changes: 5 additions & 5 deletions enterprise/tailnet/pgcoord_test.go
Original file line number Diff line number Diff line change
@@ -286,7 +286,7 @@ func TestPGCoordinatorSingle_MissedHeartbeats(t *testing.T) {
}

fCoord2.heartbeat()
afTrap.MustWait(ctx).Release() // heartbeat timeout started
afTrap.MustWait(ctx).MustRelease(ctx) // heartbeat timeout started

fCoord2.agentNode(agent.ID, &agpl.Node{PreferredDERP: 12})
client.AssertEventuallyHasDERP(agent.ID, 12)
@@ -298,20 +298,20 @@ func TestPGCoordinatorSingle_MissedHeartbeats(t *testing.T) {
id: uuid.New(),
}
fCoord3.heartbeat()
rstTrap.MustWait(ctx).Release() // timeout gets reset
rstTrap.MustWait(ctx).MustRelease(ctx) // timeout gets reset
fCoord3.agentNode(agent.ID, &agpl.Node{PreferredDERP: 13})
client.AssertEventuallyHasDERP(agent.ID, 13)

// fCoord2 sends in a second heartbeat, one period later (on time)
mClock.Advance(tailnet.HeartbeatPeriod).MustWait(ctx)
fCoord2.heartbeat()
rstTrap.MustWait(ctx).Release() // timeout gets reset
rstTrap.MustWait(ctx).MustRelease(ctx) // timeout gets reset

// when the fCoord3 misses enough heartbeats, the real coordinator should send an update with the
// node from fCoord2 for the agent.
mClock.Advance(tailnet.HeartbeatPeriod).MustWait(ctx)
w := mClock.Advance(tailnet.HeartbeatPeriod)
rstTrap.MustWait(ctx).Release()
rstTrap.MustWait(ctx).MustRelease(ctx)
w.MustWait(ctx)
client.AssertEventuallyHasDERP(agent.ID, 12)

@@ -323,7 +323,7 @@ func TestPGCoordinatorSingle_MissedHeartbeats(t *testing.T) {

// send fCoord3 heartbeat, which should trigger us to consider that mapping valid again.
fCoord3.heartbeat()
rstTrap.MustWait(ctx).Release() // timeout gets reset
rstTrap.MustWait(ctx).MustRelease(ctx) // timeout gets reset
client.AssertEventuallyHasDERP(agent.ID, 13)

agent.UngracefulDisconnect(ctx)
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -98,7 +98,7 @@ require (
github.com/coder/flog v1.1.0
github.com/coder/guts v1.5.0
github.com/coder/pretty v0.0.0-20230908205945-e89ba86370e0
github.com/coder/quartz v0.1.3
github.com/coder/quartz v0.2.1-0.20250527113331-b71761ce32df
github.com/coder/retry v1.5.1
github.com/coder/serpent v0.10.0
github.com/coder/terraform-provider-coder/v2 v2.5.0
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -913,8 +913,8 @@ github.com/coder/pretty v0.0.0-20230908205945-e89ba86370e0 h1:3A0ES21Ke+FxEM8CXx
github.com/coder/pretty v0.0.0-20230908205945-e89ba86370e0/go.mod h1:5UuS2Ts+nTToAMeOjNlnHFkPahrtDkmpydBen/3wgZc=
github.com/coder/preview v0.0.2-0.20250521212114-e6a60ffa74f2 h1:D52yPPupcbNWppZzWAjZJG5L34TGpNyKj7vG1VT13FU=
github.com/coder/preview v0.0.2-0.20250521212114-e6a60ffa74f2/go.mod h1:9bwyhQSVDjcxAWuFFaG6/qBqhaiW5oqF5PEQMhevKLs=
github.com/coder/quartz v0.1.3 h1:hA2nI8uUA2fNN9uhXv2I4xZD4aHkA7oH3g2t03v4xf8=
github.com/coder/quartz v0.1.3/go.mod h1:vsiCc+AHViMKH2CQpGIpFgdHIEQsxwm8yCscqKmzbRA=
github.com/coder/quartz v0.2.1-0.20250527113331-b71761ce32df h1:o6lpiSrGKVopPv6Fnh3S+FrI5ntRE0eSUo6Bqpzpkgo=
github.com/coder/quartz v0.2.1-0.20250527113331-b71761ce32df/go.mod h1:vsiCc+AHViMKH2CQpGIpFgdHIEQsxwm8yCscqKmzbRA=
github.com/coder/retry v1.5.1 h1:iWu8YnD8YqHs3XwqrqsjoBTAVqT9ml6z9ViJ2wlMiqc=
github.com/coder/retry v1.5.1/go.mod h1:blHMk9vs6LkoRT9ZHyuZo360cufXEhrxqvEzeMtRGoY=
github.com/coder/serpent v0.10.0 h1:ofVk9FJXSek+SmL3yVE3GoArP83M+1tX+H7S4t8BSuM=
8 changes: 4 additions & 4 deletions tailnet/controllers_test.go
Original file line number Diff line number Diff line change
@@ -828,7 +828,7 @@ func TestBasicResumeTokenController_Mainline(t *testing.T) {
RefreshIn: durationpb.New(100 * time.Second),
ExpiresAt: timestamppb.New(mClock.Now().Add(200 * time.Second)),
})
trp.MustWait(ctx).Release() // initial refresh done
trp.MustWait(ctx).MustRelease(ctx) // initial refresh done
token, ok := uut.Token()
require.True(t, ok)
require.Equal(t, "test token 1", token)
@@ -843,7 +843,7 @@ func TestBasicResumeTokenController_Mainline(t *testing.T) {
})
resetCall := trp.MustWait(ctx)
require.Equal(t, resetCall.Duration, 50*time.Second)
resetCall.Release()
resetCall.MustRelease(ctx)
w.MustWait(ctx)
token, ok = uut.Token()
require.True(t, ok)
@@ -903,7 +903,7 @@ func TestBasicResumeTokenController_NewWhileRefreshing(t *testing.T) {
ExpiresAt: timestamppb.New(mClock.Now().Add(200 * time.Second)),
})

trp.MustWait(ctx).Release()
trp.MustWait(ctx).MustRelease(ctx)

token, ok := uut.Token()
require.True(t, ok)
@@ -923,7 +923,7 @@ func TestBasicResumeTokenController_NewWhileRefreshing(t *testing.T) {
})
resetCall := trp.MustWait(ctx)
require.Equal(t, resetCall.Duration, 50*time.Second)
resetCall.Release()
resetCall.MustRelease(ctx)
w.MustWait(ctx)
token, ok = uut.Token()
require.True(t, ok)
2 changes: 1 addition & 1 deletion vpn/tunnel_internal_test.go
Original file line number Diff line number Diff line change
@@ -724,7 +724,7 @@ func setupTunnel(t *testing.T, ctx context.Context, client *fakeClient, mClock *
require.NoError(t, err)
mgr.start()
// We're releasing the trap to allow the clock to advance the ticker.
trap.MustWait(ctx).Release()
trap.MustWait(ctx).MustRelease(ctx)
return tun, mgr
}

PHP-Proxy

PHP-Proxy

Error accessing resource: 404 - Not Found