From 4651024548a71075f297e80b6fb506adb527869b Mon Sep 17 00:00:00 2001 From: Michael Matloka Date: Tue, 19 Nov 2024 23:21:50 +0100 Subject: [PATCH] Use `@microsoft/fetch-event-source` instead --- .../activity/live/liveEventsTableLogic.tsx | 67 +++++++++---------- package.json | 3 +- pnpm-lock.yaml | 22 ++---- 3 files changed, 41 insertions(+), 51 deletions(-) diff --git a/frontend/src/scenes/activity/live/liveEventsTableLogic.tsx b/frontend/src/scenes/activity/live/liveEventsTableLogic.tsx index 85599ea0144..afcd2bbd257 100644 --- a/frontend/src/scenes/activity/live/liveEventsTableLogic.tsx +++ b/frontend/src/scenes/activity/live/liveEventsTableLogic.tsx @@ -1,5 +1,5 @@ +import { fetchEventSource } from '@microsoft/fetch-event-source' import { lemonToast, Spinner } from '@posthog/lemon-ui' -import EventSource from 'eventsource' import { actions, connect, events, kea, listeners, path, props, reducers, selectors } from 'kea' import { liveEventsHostOrigin } from 'lib/utils/apiHost' import { teamLogic } from 'scenes/teamLogic' @@ -120,8 +120,8 @@ export const liveEventsTableLogic = kea([ actions.updateEventsConnection() }, updateEventsConnection: async () => { - if (cache.eventsSource) { - cache.eventsSource.close() + if (cache.eventSourceController) { + cache.eventSourceController.abort() } if (values.streamPaused) { @@ -138,41 +138,40 @@ export const liveEventsTableLogic = kea([ url.searchParams.append('eventType', eventType) } - const source = new EventSource(url.toString(), { + cache.batch = [] + cache.eventSourceController = new AbortController() + + await fetchEventSource(url.toString(), { headers: { Authorization: `Bearer ${values.currentTeam.live_events_token}`, }, + signal: cache.eventSourceController.signal, + onmessage: (event) => { + lemonToast.dismiss(ERROR_TOAST_ID) + const eventData = JSON.parse(event.data) + cache.batch.push(eventData) + // If the batch is 10 or more events, or if it's been more than 300ms since the last batch + if (cache.batch.length >= 10 || performance.now() - (values.lastBatchTimestamp || 0) > 300) { + actions.addEvents(cache.batch) + cache.batch.length = 0 + } + }, + onerror: (error) => { + if (!cache.hasShownLiveStreamErrorToast && props.showLiveStreamErrorToast) { + console.error('Failed to poll events. You likely have no events coming in.', error) + lemonToast.error(`No live events found. Continuing to retry in the background…`, { + icon: , + toastId: ERROR_TOAST_ID, + autoClose: false, + }) + cache.hasShownLiveStreamErrorToast = true // Only show once + } + }, }) - - cache.batch = [] - source.onmessage = function (event: any) { - lemonToast.dismiss(ERROR_TOAST_ID) - const eventData = JSON.parse(event.data) - cache.batch.push(eventData) - // If the batch is 10 or more events, or if it's been more than 300ms since the last batch - if (cache.batch.length >= 10 || performance.now() - (values.lastBatchTimestamp || 0) > 300) { - actions.addEvents(cache.batch) - cache.batch.length = 0 - } - } - - source.onerror = function (e) { - if (!cache.hasShownLiveStreamErrorToast && props.showLiveStreamErrorToast) { - console.error('Failed to poll events. You likely have no events coming in.', e) - lemonToast.error(`No live events found. Continuing to retry in the background…`, { - icon: , - toastId: ERROR_TOAST_ID, - autoClose: false, - }) - cache.hasShownLiveStreamErrorToast = true // Only show once - } - } - - cache.eventsSource = source }, pauseStream: () => { - if (cache.eventsSource) { - cache.eventsSource.close() + if (cache.eventSourceController) { + cache.eventSourceController.abort() } }, resumeStream: () => { @@ -215,8 +214,8 @@ export const liveEventsTableLogic = kea([ }, 1500) }, beforeUnmount: () => { - if (cache.eventsSource) { - cache.eventsSource.close() + if (cache.eventSourceController) { + cache.eventSourceController.abort() } if (cache.statsInterval) { clearInterval(cache.statsInterval) diff --git a/package.json b/package.json index 84e84387d3b..c58789400bb 100644 --- a/package.json +++ b/package.json @@ -75,6 +75,7 @@ "@lottiefiles/react-lottie-player": "^3.4.7", "@medv/finder": "^3.1.0", "@microlink/react-json-view": "^1.21.3", + "@microsoft/fetch-event-source": "^2.0.1", "@monaco-editor/react": "4.6.0", "@posthog/hogvm": "^1.0.59", "@posthog/icons": "0.9.1", @@ -124,7 +125,6 @@ "esbuild-plugin-less": "^1.3.1", "esbuild-plugin-polyfill-node": "^0.3.0", "esbuild-sass-plugin": "^3.0.0", - "eventsource": "^2.0.2", "eventsource-parser": "^3.0.0", "expr-eval": "^2.0.2", "express": "^4.17.1", @@ -232,7 +232,6 @@ "@types/d3": "^7.4.0", "@types/d3-sankey": "^0.12.1", "@types/dompurify": "^3.0.3", - "@types/eventsource": "^1.1.15", "@types/heatmap.js": "^2.0.41", "@types/image-blob-reduce": "^4.1.1", "@types/jest": "^29.5.12", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7a96c0128f6..d98fc19935f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -46,6 +46,9 @@ dependencies: '@microlink/react-json-view': specifier: ^1.21.3 version: 1.22.2(@types/react@17.0.52)(react-dom@18.2.0)(react@18.2.0) + '@microsoft/fetch-event-source': + specifier: ^2.0.1 + version: 2.0.1 '@monaco-editor/react': specifier: 4.6.0 version: 4.6.0(monaco-editor@0.49.0)(react-dom@18.2.0)(react@18.2.0) @@ -193,9 +196,6 @@ dependencies: esbuild-sass-plugin: specifier: ^3.0.0 version: 3.0.0(esbuild@0.19.8) - eventsource: - specifier: ^2.0.2 - version: 2.0.2 eventsource-parser: specifier: ^3.0.0 version: 3.0.0 @@ -515,9 +515,6 @@ devDependencies: '@types/dompurify': specifier: ^3.0.3 version: 3.0.3 - '@types/eventsource': - specifier: ^1.1.15 - version: 1.1.15 '@types/heatmap.js': specifier: ^2.0.41 version: 2.0.41 @@ -5290,6 +5287,10 @@ packages: - encoding dev: false + /@microsoft/fetch-event-source@2.0.1: + resolution: {integrity: sha512-W6CLUJ2eBMw3Rec70qrsEW0jOm/3twwJv21mrmj2yORiaVmVYGS4sSS5yUwvQc1ZlDLYGPnClVWmUUMagKNsfA==} + dev: false + /@monaco-editor/loader@1.4.0(monaco-editor@0.49.0): resolution: {integrity: sha512-00ioBig0x642hytVspPl7DbQyaSWRaolYie/UFNjoTdvoKPzo6xrXLhTk9ixgIKcLH5b5vDOjVNiGyY+uDCUlg==} peerDependencies: @@ -8283,10 +8284,6 @@ packages: resolution: {integrity: sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==} dev: true - /@types/eventsource@1.1.15: - resolution: {integrity: sha512-XQmGcbnxUNa06HR3VBVkc9+A2Vpi9ZyLJcdS5dwaQQ/4ZMWFO+5c90FnMUpbtMZwB/FChoYHwuVg8TvkECacTA==} - dev: true - /@types/express-serve-static-core@4.17.41: resolution: {integrity: sha512-OaJ7XLaelTgrvlZD8/aa0vvvxZdUmlCn6MtWeB7TkiKW70BQLc9XEPpDLPdbo52ZhXUCrznlWdCHWxJWtdyajA==} dependencies: @@ -12547,11 +12544,6 @@ packages: engines: {node: '>=18.0.0'} dev: false - /eventsource@2.0.2: - resolution: {integrity: sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA==} - engines: {node: '>=12.0.0'} - dev: false - /execa@4.1.0: resolution: {integrity: sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==} engines: {node: '>=10'}