fix(group): bound push pressure and synchronize load agents
This commit is contained in:
@@ -15,6 +15,7 @@ func TestCoordinatorResetsBarrierWhenConnectionCountDrops(t *testing.T) {
|
||||
start: StartInfo{RunID: "run-reset", Scenario: "group"}, startDelay: time.Minute,
|
||||
commitDelay: time.Second, expectedAgents: 2, ready: make(map[string]AgentReady),
|
||||
armed: make(map[string]bool), ledgers: make(map[string][]AcceptedMessage),
|
||||
started: make(map[string]time.Time),
|
||||
summaries: make(map[string]AgentSummary), complete: make(chan struct{}),
|
||||
}
|
||||
postReady := func(ready AgentReady) StartInfo {
|
||||
@@ -52,6 +53,7 @@ func TestCoordinatorClientWaitsForBothAgentsAndMergesLedger(t *testing.T) {
|
||||
commitDelay: 50 * time.Millisecond, expectedAgents: 2,
|
||||
ready: make(map[string]AgentReady), ledgers: make(map[string][]AcceptedMessage),
|
||||
armed: make(map[string]bool), summaries: make(map[string]AgentSummary), complete: make(chan struct{}),
|
||||
started: make(map[string]time.Time),
|
||||
}
|
||||
server := httptest.NewServer(testCoordinatorMux(state))
|
||||
defer server.Close()
|
||||
@@ -116,6 +118,7 @@ func testCoordinatorMux(state *coordinatorState) *http.ServeMux {
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/v1/ready", state.handleReady)
|
||||
mux.HandleFunc("/v1/start", state.handleStart)
|
||||
mux.HandleFunc("/v1/started", state.handleStarted)
|
||||
mux.HandleFunc("/v1/ledger", state.handleLedger)
|
||||
mux.HandleFunc("/v1/observed", state.handleObserved)
|
||||
mux.HandleFunc("/v1/history", state.handleHistory)
|
||||
@@ -123,3 +126,50 @@ func testCoordinatorMux(state *coordinatorState) *http.ServeMux {
|
||||
mux.HandleFunc("/v1/status", state.handleStatus)
|
||||
return mux
|
||||
}
|
||||
|
||||
func TestCoordinatorRejectsLateAgentForBothMachines(t *testing.T) {
|
||||
startAt := time.Now().Add(-maxAgentStartSkew - time.Second).UTC()
|
||||
state := &coordinatorState{
|
||||
start: StartInfo{RunID: "run-late", Scenario: "group", StartAt: startAt, Committed: true},
|
||||
expectedAgents: 2, started: make(map[string]time.Time),
|
||||
}
|
||||
server := httptest.NewServer(testCoordinatorMux(state))
|
||||
defer server.Close()
|
||||
client := newCoordinatorClient(server.URL)
|
||||
if err := client.started(context.Background(), "b", startAt); err == nil {
|
||||
t.Fatal("late agent must be rejected")
|
||||
}
|
||||
if err := client.started(context.Background(), "a", startAt); err == nil {
|
||||
t.Fatal("the other agent must observe the same rejected run")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCoordinatorReleasesAgentsOnlyAfterBothReachStart(t *testing.T) {
|
||||
startAt := time.Now().UTC()
|
||||
state := &coordinatorState{
|
||||
start: StartInfo{RunID: "run-synced", Scenario: "group", StartAt: startAt, Committed: true},
|
||||
expectedAgents: 2, started: make(map[string]time.Time),
|
||||
}
|
||||
server := httptest.NewServer(testCoordinatorMux(state))
|
||||
defer server.Close()
|
||||
client := newCoordinatorClient(server.URL)
|
||||
aDone := make(chan error, 1)
|
||||
go func() { aDone <- client.started(context.Background(), "a", startAt) }()
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
select {
|
||||
case err := <-aDone:
|
||||
t.Fatalf("machine A passed before B arrived: %v", err)
|
||||
default:
|
||||
}
|
||||
if err := client.started(context.Background(), "b", startAt); err != nil {
|
||||
t.Fatalf("machine B start: %v", err)
|
||||
}
|
||||
select {
|
||||
case err := <-aDone:
|
||||
if err != nil {
|
||||
t.Fatalf("machine A start: %v", err)
|
||||
}
|
||||
case <-time.After(time.Second):
|
||||
t.Fatal("machine A was not released")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user