@@ -71,13 +71,27 @@ func (f *fakeExecutor) RunPrepared(ctx context.Context, _ *runners.PreparedWorkf
7171}
7272
7373type fakeKeysManager struct {
74- seed []taskverifier.SigningKey
75- snapshot []taskverifier.SigningKey
74+ seed []taskverifier.SigningKey
75+ snapshot []taskverifier.SigningKey
76+ readyGate <- chan struct {}
77+ waitStarted chan <- struct {}
7678}
7779
78- func (f * fakeKeysManager ) Start (context.Context ) {}
79- func (f * fakeKeysManager ) GetKey (string ) types.DecodedKey { return nil }
80- func (f * fakeKeysManager ) WaitForReady (context.Context ) error { return nil }
80+ func (f * fakeKeysManager ) Start (context.Context ) {}
81+ func (f * fakeKeysManager ) GetKey (string ) types.DecodedKey { return nil }
82+ func (f * fakeKeysManager ) WaitForReady (ctx context.Context ) error {
83+ if f .waitStarted != nil {
84+ f .waitStarted <- struct {}{}
85+ }
86+ if f .readyGate != nil {
87+ select {
88+ case <- f .readyGate :
89+ case <- ctx .Done ():
90+ return ctx .Err ()
91+ }
92+ }
93+ return nil
94+ }
8195func (f * fakeKeysManager ) Seed (keys []taskverifier.SigningKey ) error {
8296 f .seed = keys
8397 return nil
@@ -262,6 +276,34 @@ func TestServeSyncKeysSeedsAndReturnsCurrentSnapshot(t *testing.T) {
262276 require .True (t , health .GetReady ())
263277}
264278
279+ func TestSyncKeysSuppressesIdleExitWhileWaitingForKeys (t * testing.T ) {
280+ readyGate := make (chan struct {})
281+ waitStarted := make (chan struct {}, 1 )
282+ keysManager := & fakeKeysManager {readyGate : readyGate , waitStarted : waitStarted }
283+ srv := NewServer (& fakeExecutor {}, "test-version" , keysManager )
284+ mockClock := clock .NewMock ()
285+ srv .clock = mockClock
286+ srv .touch ()
287+
288+ done := make (chan error , 1 )
289+ go func () {
290+ _ , err := srv .SyncKeys (context .Background (), & pb.SyncKeysRequest {})
291+ done <- err
292+ }()
293+ <- waitStarted
294+
295+ mockClock .Add (2 * time .Minute )
296+ assert .Zero (t , srv .idleFor (), "key synchronization is executor activity" )
297+ health , err := srv .Health (context .Background (), & pb.HealthRequest {})
298+ require .NoError (t , err )
299+ assert .Zero (t , health .ActiveActions , "key synchronization is not an action" )
300+
301+ close (readyGate )
302+ require .NoError (t , <- done )
303+ mockClock .Add (time .Minute )
304+ assert .Equal (t , time .Minute , srv .idleFor ())
305+ }
306+
265307func TestServeRunActionStreamsOutputAndForwardsRawTask (t * testing.T ) {
266308 fake := & fakeExecutor {
267309 prepared : & runners.PreparedWorkflowTask {Task : & types.Task {}},
@@ -595,11 +637,13 @@ func TestIdleTracking(t *testing.T) {
595637 mockClock .Add (time .Second )
596638 assert .Equal (t , time .Second , srv .idleFor (), "health checks should not count as activity" )
597639
598- srv .active . Add ( 1 )
640+ finishActivity := srv .beginActivity ( )
599641 mockClock .Add (2 * timeout )
600- assert .Zero (t , srv .idleFor (), "an active action should suppress the idle state" )
601- srv .active .Add (- 1 )
602- srv .touch ()
642+ assert .Zero (t , srv .idleFor (), "activity should suppress the idle state" )
643+ health , err := srv .Health (context .Background (), & pb.HealthRequest {})
644+ require .NoError (t , err )
645+ assert .Zero (t , health .ActiveActions , "non-action activity must not affect action accounting" )
646+ finishActivity ()
603647
604648 mockClock .Add (timeout )
605649 assert .Equal (t , timeout , srv .idleFor ())
0 commit comments