From 9936f39771f8039da1135cbd76ee27805e857401 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Mathieu?= Date: Tue, 14 Jan 2025 12:14:05 +0100 Subject: [PATCH] feat(webserver, ui): avoid cancelled SSE connection from following exec Send a fake "start" event from the Execution following endpoint so that the UI didn't cancell it. I'm not sure when the UI would cancel the SSE connection but it can ocurs if any of the view that opens an SSE connection are left but no event are received yet. Sending a fake event immediatly lower the risk of occuring. --- ui/src/components/executions/ExecutionRoot.vue | 5 ++++- ui/src/components/executions/Topology.vue | 5 ++++- ui/src/components/logs/TaskRunDetails.vue | 5 ++++- .../webserver/controllers/api/ExecutionController.java | 5 ++++- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/ui/src/components/executions/ExecutionRoot.vue b/ui/src/components/executions/ExecutionRoot.vue index 768c50d8b13..adb8b144b55 100644 --- a/ui/src/components/executions/ExecutionRoot.vue +++ b/ui/src/components/executions/ExecutionRoot.vue @@ -125,7 +125,10 @@ if (isEnd) { this.closeSSE(); } - this.throttledExecutionUpdate(executionEvent); + // we are receiving a first "fake" event to force initializing the connection: ignoring it + if (executionEvent.lastEventId !== "start") { + this.throttledExecutionUpdate(executionEvent); + } if (isEnd) { this.throttledExecutionUpdate.flush(); } diff --git a/ui/src/components/executions/Topology.vue b/ui/src/components/executions/Topology.vue index abdf4a5e5d7..8cf21eb99b7 100644 --- a/ui/src/components/executions/Topology.vue +++ b/ui/src/components/executions/Topology.vue @@ -223,7 +223,10 @@ if (isEnd) { this.closeExecutionSSE(); } - this.throttledExecutionUpdate(subflow, executionEvent); + // we are receiving a first "fake" event to force initializing the connection: ignoring it + if (executionEvent.lastEventId !== "start") { + this.throttledExecutionUpdate(subflow, executionEvent); + } if (isEnd) { this.throttledExecutionUpdate.flush(); } diff --git a/ui/src/components/logs/TaskRunDetails.vue b/ui/src/components/logs/TaskRunDetails.vue index 1823a9f746c..f5e460c8bda 100644 --- a/ui/src/components/logs/TaskRunDetails.vue +++ b/ui/src/components/logs/TaskRunDetails.vue @@ -360,7 +360,10 @@ if (isEnd) { this.closeExecutionSSE(); } - this.throttledExecutionUpdate(executionEvent); + // we are receiving a first "fake" event to force initializing the connection: ignoring it + if (executionEvent.lastEventId !== "start") { + this.throttledExecutionUpdate(executionEvent); + } if (isEnd) { this.throttledExecutionUpdate.flush(); } diff --git a/webserver/src/main/java/io/kestra/webserver/controllers/api/ExecutionController.java b/webserver/src/main/java/io/kestra/webserver/controllers/api/ExecutionController.java index 31b7944d0a2..536df776155 100644 --- a/webserver/src/main/java/io/kestra/webserver/controllers/api/ExecutionController.java +++ b/webserver/src/main/java/io/kestra/webserver/controllers/api/ExecutionController.java @@ -1199,8 +1199,11 @@ public Flux> follow( return Flux .>create(emitter -> { + // send a first "empty" event so the SSE is correctly initialized in the frontend in case there are no logs + emitter.next(Event.of(Execution.builder().id(executionId).build()).id("start")); + // already finished execution - Execution execution = null; + Execution execution; try { execution = Await.until( () -> executionRepository.findById(tenantService.resolveTenant(), executionId).orElse(null),