Skip to content

Commit 01e1adb

Browse files
committed
feat: setup event stream connection via web socket and display events
1 parent c29371d commit 01e1adb

File tree

4 files changed

+191
-14
lines changed

4 files changed

+191
-14
lines changed

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@
5252
"@rjsf/utils": "5.24.2",
5353
"@rjsf/validator-ajv8": "5.24.2",
5454
"@sentry/nextjs": "8.53.0",
55-
"@squonk/account-server-client": "4.1.0",
56-
"@squonk/data-manager-client": "3.3.0",
55+
"@squonk/account-server-client": "4.2.0-rc.3",
56+
"@squonk/data-manager-client": "3.3.1",
5757
"@squonk/mui-theme": "4.0.0",
5858
"@squonk/sdf-parser": "1.3.0",
5959
"@tanstack/match-sorter-utils": "8.19.4",
@@ -90,6 +90,7 @@
9090
"notistack": "3.0.2",
9191
"plotly.js-basic-dist": "2.35.3",
9292
"prismjs": "1.29.0",
93+
"protobufjs": "^7.4.0",
9394
"react": "19.0.0",
9495
"react-dom": "19.0.0",
9596
"react-dropzone": "14.3.5",

pnpm-lock.yaml

Lines changed: 92 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/components/EventStream.tsx

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import { useEffect, useState } from "react";
2+
3+
import {
4+
useCreateEventStream,
5+
useGetEventStream,
6+
} from "@squonk/account-server-client/event-stream";
7+
8+
import { useSnackbar } from "notistack";
9+
import * as protobuf from "protobufjs";
10+
11+
export const EventStream = () => {
12+
const [eventStreamId, setEventStreamId] = useState<number | null>(null);
13+
const [location, setLocation] = useState<string | null>(null);
14+
const [websocket, setWebsocket] = useState<WebSocket | null>(null);
15+
const [protoRoot, setProtoRoot] = useState<protobuf.Root | null>(null);
16+
const { enqueueSnackbar } = useSnackbar();
17+
const { data, error } = useGetEventStream();
18+
19+
useEffect(() => {
20+
// Initialize protobuf root
21+
const root = new protobuf.Root();
22+
// You would typically load your proto definitions here
23+
// For example: root.load("path/to/proto/file.proto", { keepCase: true })
24+
setProtoRoot(root);
25+
}, []);
26+
27+
useEffect(() => {
28+
if (data) {
29+
setEventStreamId(data.id);
30+
setLocation(data.location);
31+
}
32+
}, [data]);
33+
34+
const { mutate: createEventStream } = useCreateEventStream({
35+
mutation: {
36+
onSuccess: (data) => {
37+
setEventStreamId(data.id);
38+
setLocation(data.location);
39+
},
40+
},
41+
});
42+
43+
useEffect(() => {
44+
if (error?.response?.status === 404) {
45+
createEventStream();
46+
}
47+
}, [error, createEventStream]);
48+
49+
useEffect(() => {
50+
if (location && protoRoot) {
51+
// Create WebSocket connection
52+
const ws = new WebSocket(location);
53+
54+
ws.addEventListener("open", () => {
55+
enqueueSnackbar("Connected to event stream", {
56+
variant: "success",
57+
anchorOrigin: { horizontal: "right", vertical: "bottom" },
58+
});
59+
});
60+
61+
ws.addEventListener("error", () => {
62+
enqueueSnackbar("Failed to connect to event stream", {
63+
variant: "error",
64+
anchorOrigin: { horizontal: "right", vertical: "bottom" },
65+
});
66+
});
67+
68+
ws.addEventListener("close", () => {
69+
enqueueSnackbar("Disconnected from event stream", {
70+
variant: "warning",
71+
anchorOrigin: { horizontal: "right", vertical: "bottom" },
72+
});
73+
});
74+
75+
ws.addEventListener("message", (event) => {
76+
enqueueSnackbar(`Received event: ${event.data}`, {
77+
variant: "info",
78+
anchorOrigin: { horizontal: "right", vertical: "bottom" },
79+
});
80+
});
81+
82+
setWebsocket(ws);
83+
84+
return () => {
85+
ws.close();
86+
};
87+
}
88+
}, [location, protoRoot, enqueueSnackbar]);
89+
90+
console.log(eventStreamId);
91+
console.log(websocket);
92+
93+
return null;
94+
};

src/pages/_app.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { SnackbarProvider } from "notistack";
1717

1818
import { ThemeProviders } from "../components/app/ThemeProviders";
1919
import { TopLevelHooks } from "../components/app/TopLevelHooks";
20+
import { EventStream } from "../components/EventStream";
2021
import { openSansFont } from "../constants/fonts";
2122
import { AS_API_URL, DM_API_URL } from "../constants/proxies";
2223
import { MDXComponentProvider } from "../context/MDXComponentProvider";
@@ -65,6 +66,7 @@ const App = ({ Component, pageProps }: CustomAppProps) => {
6566
<QueryClientProvider client={queryClient}>
6667
<HydrationBoundary state={pageProps.dehydratedState}>
6768
<SnackbarProvider>
69+
<EventStream />
6870
<MDXComponentProvider>
6971
<TopLevelHooks>
7072
<Component {...pageProps} />

0 commit comments

Comments
 (0)