diff --git a/dashboard/event.go b/dashboard/event.go index 0eecf47..5ae30d8 100644 --- a/dashboard/event.go +++ b/dashboard/event.go @@ -9,7 +9,7 @@ package dashboard type eventListener interface { onEvent(event string, data interface{}) onStart() error - onStop() error + onStop(reason error) error } type eventSource struct { @@ -36,9 +36,9 @@ func (src *eventSource) fireStart() error { return nil } -func (src *eventSource) fireStop() error { +func (src *eventSource) fireStop(reason error) error { for _, e := range src.listeners { - if err := e.onStop(); err != nil { + if err := e.onStop(reason); err != nil { return err } } diff --git a/dashboard/event_test.go b/dashboard/event_test.go index 4c0484b..1ec44c1 100644 --- a/dashboard/event_test.go +++ b/dashboard/event_test.go @@ -20,7 +20,7 @@ func (*errorEventListener) onStart() error { return assert.AnError } -func (*errorEventListener) onStop() error { +func (*errorEventListener) onStop(_ error) error { return assert.AnError } @@ -32,5 +32,5 @@ func Test_eventSource_error(t *testing.T) { src.addEventListener(new(errorEventListener)) assert.Error(t, src.fireStart()) - assert.Error(t, src.fireStop()) + assert.Error(t, src.fireStop(nil)) } diff --git a/dashboard/extension.go b/dashboard/extension.go index f92e9e5..e5895e5 100644 --- a/dashboard/extension.go +++ b/dashboard/extension.go @@ -152,7 +152,14 @@ func (ext *extension) Start() error { } // Stop flushes any remaining metrics and stops the extension. +// k6 core will call WithStopWithTestError instead of this one. func (ext *extension) Stop() error { + return ext.StopWithTestError(nil) +} + +// WithStopWithTestError allows output to receive the error value that the test finished with. +// Flushes any remaining metrics and stops the extension. +func (ext *extension) StopWithTestError(testRunErr error) error { ext.noFlush.Store(true) ext.flusher.Stop() @@ -161,7 +168,7 @@ func (ext *extension) Stop() error { ext.updateAndSend(nil, newMeter(ext.period, now, ext.options.Tags), stopEvent, now) - err := ext.fireStop() + err := ext.fireStop(testRunErr) if err != nil { return err } diff --git a/dashboard/record.go b/dashboard/record.go index 84219a7..287bb4a 100644 --- a/dashboard/record.go +++ b/dashboard/record.go @@ -48,7 +48,7 @@ func (rec *recorder) onStart() error { return nil } -func (rec *recorder) onStop() error { +func (rec *recorder) onStop(_ error) error { return rec.writer.Close() } diff --git a/dashboard/record_test.go b/dashboard/record_test.go index 82ecf45..ace4ad5 100644 --- a/dashboard/record_test.go +++ b/dashboard/record_test.go @@ -40,7 +40,7 @@ func Test_recorder_onStart(t *testing.T) { assert.True(t, exists(th.proc.fs, "foo")) - assert.NoError(t, rec.onStop()) + assert.NoError(t, rec.onStop(nil)) } func Test_recorder_onStart_error(t *testing.T) { @@ -66,7 +66,7 @@ func Test_recorder_onEvent_config(t *testing.T) { rec.onEvent("config", data) - assert.NoError(t, rec.onStop()) + assert.NoError(t, rec.onStop(nil)) file, err := th.proc.fs.Open("out") @@ -92,7 +92,7 @@ func Test_recorder_onEvent(t *testing.T) { rec.onEvent("dummy", data) - assert.NoError(t, rec.onStop()) + assert.NoError(t, rec.onStop(nil)) file, err := th.proc.fs.Open("out.gz") @@ -137,5 +137,5 @@ func Test_recorder_onEvent_error(t *testing.T) { assert.NotNil(t, entry) assert.Equal(t, logrus.WarnLevel, entry.Level) - assert.NoError(t, rec.onStop()) + assert.NoError(t, rec.onStop(nil)) } diff --git a/dashboard/replay.go b/dashboard/replay.go index c62a33f..773befe 100644 --- a/dashboard/replay.go +++ b/dashboard/replay.go @@ -103,7 +103,7 @@ func (rep *replayer) run() error { rep.fireEvent(input.Name, input.Data) } - return rep.fireStop() + return rep.fireStop(nil) } type replayerEnvelope struct { diff --git a/dashboard/report.go b/dashboard/report.go index bc78a74..30b2a2e 100644 --- a/dashboard/report.go +++ b/dashboard/report.go @@ -46,7 +46,7 @@ func (rep *reporter) onStart() error { return nil } -func (rep *reporter) onStop() error { +func (rep *reporter) onStop(_ error) error { if len(rep.output) == 0 { return nil } diff --git a/dashboard/sse.go b/dashboard/sse.go index aec4959..9282025 100644 --- a/dashboard/sse.go +++ b/dashboard/sse.go @@ -8,6 +8,7 @@ package dashboard import ( "encoding/json" + "errors" "net/http" "strconv" "sync" @@ -15,6 +16,7 @@ import ( "github.com/r3labs/sse/v2" "github.com/sirupsen/logrus" + "go.k6.io/k6/errext" ) type eventEmitter struct { @@ -43,8 +45,12 @@ func (emitter *eventEmitter) onStart() error { return nil } -func (emitter *eventEmitter) onStop() error { - emitter.wait.Wait() +func (emitter *eventEmitter) onStop(reason error) error { + var err errext.HasAbortReason + + if !errors.As(reason, &err) { + emitter.wait.Wait() + } return nil } diff --git a/releases/v0.7.1.md b/releases/v0.7.1.md new file mode 100644 index 0000000..6789880 --- /dev/null +++ b/releases/v0.7.1.md @@ -0,0 +1,3 @@ +xk6-dashboard `v0.7.1` is here 🎉! This release includes: + +- fix: [#142](https://github.com/grafana/xk6-dashboard/issues/142) k6 does not stop in case of an abortion