Очередь job получила lease и fencing, телеметрия и прогресс deploy сохраняются, ревизия пишет manifest входов. Обновление префиксов не переписывает неизменённый снимок, большие наборы идут через COPY, а устаревшая ревизия не попадает в deploy. Бандл ноды кэшируется, prune и постановка job больше не держат горячий путь. Co-authored-by: Cursor <[email protected]>
60 lines
1.8 KiB
Go
60 lines
1.8 KiB
Go
package store
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestMemoryModuleSnapshotLockCancellationAndCleanup(t *testing.T) {
|
|
m := NewMemory()
|
|
first, err := m.lockModuleSnapshot(context.Background(), "tenant-a", "module-a")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Millisecond)
|
|
defer cancel()
|
|
second, err := m.lockModuleSnapshot(ctx, "tenant-a", "module-a")
|
|
if second != nil || !errors.Is(err, context.DeadlineExceeded) {
|
|
t.Fatalf("waiter not cancelled: unlock=%v err=%v", second != nil, err)
|
|
}
|
|
if len(m.snapshotLocks) != 1 || m.snapshotLocks[moduleSnapshotKey("tenant-a", "module-a")].refs != 1 {
|
|
t.Fatalf("waiter leaked lock ref: %+v", m.snapshotLocks)
|
|
}
|
|
first()
|
|
first()
|
|
if len(m.snapshotLocks) != 0 {
|
|
t.Fatalf("idle lock leaked: %+v", m.snapshotLocks)
|
|
}
|
|
third, err := m.lockModuleSnapshot(context.Background(), "tenant-a", "module-a")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
third()
|
|
}
|
|
|
|
func TestMemoryModuleSnapshotLockScopesTenantAndModule(t *testing.T) {
|
|
m := NewMemory()
|
|
first, err := m.lockModuleSnapshot(context.Background(), "tenant-a", "module-x")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer first()
|
|
for _, pair := range [][2]string{{"tenant-b", "module-x"}, {"tenant-a", "module-y"}} {
|
|
ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond)
|
|
unlock, err := m.lockModuleSnapshot(ctx, pair[0], pair[1])
|
|
cancel()
|
|
if err != nil {
|
|
t.Fatalf("unrelated key blocked %v: %v", pair, err)
|
|
}
|
|
unlock()
|
|
}
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
cancel()
|
|
unlock, err := m.lockModuleSnapshot(ctx, "tenant-a", "module-x")
|
|
if unlock != nil || !errors.Is(err, context.Canceled) {
|
|
t.Fatalf("cancelled context acquired: unlock=%v err=%v", unlock != nil, err)
|
|
}
|
|
}
|