Skip to content

Commit 3811728

Browse files
authored
[Elastic Agent] Improve GRPC stop to be more relaxed. (elastic#20118)
* Improve stop to be more relaxed. * Add changelog.
1 parent ea7c05f commit 3811728

File tree

3 files changed

+57
-2
lines changed

3 files changed

+57
-2
lines changed

x-pack/elastic-agent/CHANGELOG.asciidoc

+1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
- Fix issues with merging of elastic-agent.yml and fleet.yml {pull}20026[20026]
5454
- Unzip failures on Windows 8/Windows server 2012 {pull}20088[20088]
5555
- Fix failing unit tests on windows {pull}20127[20127]
56+
- Improve GRPC stop to be more relaxed {pull}20118[20118]
5657

5758
==== New features
5859

x-pack/elastic-agent/pkg/core/server/server.go

+5-2
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,7 @@ func (as *ApplicationState) WriteConnInfo(w io.Writer) error {
526526
// the application times out during stop and ErrApplication
527527
func (as *ApplicationState) Stop(timeout time.Duration) error {
528528
as.checkinLock.Lock()
529+
wasConn := as.checkinDone != nil
529530
cfgIdx := as.statusConfigIdx
530531
as.expected = proto.StateExpected_STOPPING
531532
as.checkinLock.Unlock()
@@ -548,8 +549,10 @@ func (as *ApplicationState) Stop(timeout time.Duration) error {
548549
s := as.status
549550
doneChan := as.checkinDone
550551
as.checkinLock.RUnlock()
551-
if s == proto.StateObserved_STOPPING && doneChan == nil {
552-
// sent stopping and now is disconnected (so its stopped)
552+
if (wasConn && doneChan == nil) || (!wasConn && s == proto.StateObserved_STOPPING && doneChan == nil) {
553+
// either occurred
554+
// * client was connected then disconnected on stop
555+
// * client was not connected; connected; received stopping; then disconnected
553556
as.Destroy()
554557
return nil
555558
}

x-pack/elastic-agent/pkg/core/server/server_test.go

+51
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,57 @@ func TestServer_Stop(t *testing.T) {
416416
assert.NoError(t, stopErr)
417417
}
418418

419+
func TestServer_StopJustDisconnect(t *testing.T) {
420+
initConfig := "initial_config"
421+
app := &StubApp{}
422+
srv := createAndStartServer(t, &StubHandler{})
423+
defer srv.Stop()
424+
as, err := srv.Register(app, initConfig)
425+
require.NoError(t, err)
426+
cImpl := &StubClientImpl{}
427+
c := newClientFromApplicationState(t, as, cImpl)
428+
require.NoError(t, c.Start(context.Background()))
429+
defer c.Stop()
430+
431+
// clients should get initial check-ins then set as healthy
432+
require.NoError(t, waitFor(func() error {
433+
if cImpl.Config() != initConfig {
434+
return fmt.Errorf("client never got intial config")
435+
}
436+
return nil
437+
}))
438+
c.Status(proto.StateObserved_HEALTHY, "Running", nil)
439+
assert.NoError(t, waitFor(func() error {
440+
if app.Status() != proto.StateObserved_HEALTHY {
441+
return fmt.Errorf("server never updated currect application state")
442+
}
443+
return nil
444+
}))
445+
446+
// send stop to the client
447+
done := make(chan bool)
448+
var stopErr error
449+
go func() {
450+
stopErr = as.Stop(time.Second * 5)
451+
close(done)
452+
}()
453+
454+
// process of testing the flow
455+
// 1. server sends stop
456+
// 2. client disconnects
457+
require.NoError(t, waitFor(func() error {
458+
if cImpl.Stop() == 0 {
459+
return fmt.Errorf("client never got expected stop")
460+
}
461+
return nil
462+
}))
463+
c.Stop()
464+
<-done
465+
466+
// no error on stop
467+
assert.NoError(t, stopErr)
468+
}
469+
419470
func TestServer_StopTimeout(t *testing.T) {
420471
initConfig := "initial_config"
421472
app := &StubApp{}

0 commit comments

Comments
 (0)