tinyrelayfile
tinyrelay/internal/daemon/maintenance_integration_test.go/

internal/daemon/maintenance_integration_test.go raw
1package daemon
2
3import (
4 "context"
5 "errors"
6 "testing"
7 "time"
8)
9
10func TestMaintenanceWaitsForPublishAndResumesOperations(t *testing.T) {
11 _, tenant := testTenant(t)
12 ctx := context.Background()
13
14 // A publish holds the normal operation admission slot while the backup
15 // requests exclusive maintenance.
16 publishCtx, releasePublish, err := tenant.beginOperation(ctx)
17 if err != nil {
18 t.Fatal(err)
19 }
20 if publishCtx == nil {
21 t.Fatal("publish context is nil")
22 }
23 maintenanceReady := make(chan struct{})
24 maintenanceDone := make(chan error, 1)
25 go func() {
26 close(maintenanceReady)
27 _, release, err := tenant.beginMaintenance(ctx)
28 if err != nil {
29 maintenanceDone <- err
30 return
31 }
32 maintenanceDone <- nil
33 release()
34 }()
35 <-maintenanceReady
36
37 select {
38 case err := <-maintenanceDone:
39 t.Fatalf("maintenance passed active publish: %v", err)
40 case <-time.After(50 * time.Millisecond):
41 }
42 select {
43 case <-maintenanceDone:
44 t.Fatal("maintenance completed before active publish was released")
45 default:
46 }
47 if _, release, err := tenant.beginOperation(ctx); !errors.Is(err, ErrMaintenance) {
48 if release != nil {
49 release()
50 }
51 t.Fatalf("operation during maintenance = %v, want %v", err, ErrMaintenance)
52 }
53
54 releasePublish()
55 select {
56 case err := <-maintenanceDone:
57 if err != nil {
58 t.Fatal(err)
59 }
60 case <-time.After(time.Second):
61 t.Fatal("maintenance did not start after publish completed")
62 }
63
64 // The maintenance release is performed by the goroutine after it signals
65 // completion, so the next operation should be admitted shortly afterward.
66 deadline := time.Now().Add(time.Second)
67 for {
68 _, release, err := tenant.beginOperation(ctx)
69 if err == nil {
70 release()
71 return
72 }
73 if !errors.Is(err, ErrMaintenance) {
74 t.Fatalf("operation after maintenance = %v", err)
75 }
76 if time.Now().After(deadline) {
77 t.Fatal("normal operations did not resume")
78 }
79 time.Sleep(time.Millisecond)
80 }
81}

About

ownerc01503e8035f
visibilitypublic
headd730679639bf

Maintainers

  • c01503e8035f owner
  • ba1b5beed5b5 agent hermes

Clone

  • https://012.run/npub1cq2s86qrtadf36eqq3epm38wmhdynrrcwxf84eldk3f94dkv7ttsrulrz5/tinyrelay.git

Refs