clone

a self-hosted multitenant nostr relay with sites, file storage, git hosting, and inbox and outbox delivery

feat/ui-updates
tinyrelay / internal / daemon / maintenance_integration_test.go
maintenance_integration_test.go 1.9K
1package daemon23import (4 "context"5 "errors"6 "testing"7 "time"8)910func TestMaintenanceWaitsForPublishAndResumesOperations(t *testing.T) {11 _, tenant := testTenant(t)12 ctx := context.Background()1314 // A publish holds the normal operation admission slot while the backup15 // 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 <- err30 return31 }32 maintenanceDone <- nil33 release()34 }()35 <-maintenanceReady3637 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 }5354 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 }6364 // The maintenance release is performed by the goroutine after it signals65 // 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 return72 }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}