History

fix

Julius Marminge committed 8 months ago

Commit b211d051 parent 52681631 file · +39 −33Browse files

Showing the changes to apps/server/src/wsServer.ts (1 of 1 file). Show all

Unified · Split

apps/server/src/wsServer.ts+39−33
@@ -16,7 +16,7 @@ import { · 15 unmodified lines
16 WsResponse,16 WsResponse,
17} from "@t3tools/contracts";17} from "@t3tools/contracts";
18import { NodeHttpServer } from "@effect/platform-node";18import { NodeHttpServer } from "@effect/platform-node";
19import { Cause, Effect, Exit, Layer, Schema, Scope, ServiceMap, Stream, Struct } from "effect";19import { Cause, Effect, Exit, Layer, Ref, Schema, Scope, ServiceMap, Stream, Struct } from "effect";
20import { WebSocketServer, type WebSocket } from "ws";20import { WebSocketServer, type WebSocket } from "ws";
21 21
22import { createLogger } from "./logger";22import { createLogger } from "./logger";
@@ -171,7 +171,7 @@ export const createServer = Effect.fn(function* (options: ServerOptions = {}): E · 148 unmodified lines
171 const keybindingsManager = yield* Keybindings;171 const keybindingsManager = yield* Keybindings;
172 const git = yield* GitCore;172 const git = yield* GitCore;
173 173
174 const clients = new Set<WebSocket>();174 const clients = yield* Ref.make(new Set<WebSocket>());
175 const logger = createLogger("ws");175 const logger = createLogger("ws");
176 176
177 function logOutgoingPush(push: WsPush, recipients: number) {177 function logOutgoingPush(push: WsPush, recipients: number) {
@@ -183,22 +183,23 @@ export const createServer = Effect.fn(function* (options: ServerOptions = {}): E · 5 unmodified lines
183 });183 });
184 }184 }
185 185
186 const onTerminalEvent = (event: TerminalEvent) => {186 const onTerminalEvent = (event: TerminalEvent) =>
187 const push: WsPush = {187 Effect.gen(function* () {
188 type: "push",188 const push: WsPush = {
189 channel: WS_CHANNELS.terminalEvent,189 type: "push",
190 data: event,190 channel: WS_CHANNELS.terminalEvent,
191 };191 data: event,
192 const message = JSON.stringify(push);192 };
193 let recipients = 0;193 const message = yield* Schema.encodeEffect(Schema.fromJsonString(WsPush))(push);
194 for (const client of clients) {194 let recipients = 0;
195 if (client.readyState === client.OPEN) {195 for (const client of yield* Ref.get(clients)) {
196 client.send(message);196 if (client.readyState === client.OPEN) {
197 recipients += 1;197 client.send(message);
198 recipients += 1;
199 }
198 }200 }
199 }201 logOutgoingPush(push, recipients);
200 logOutgoingPush(push, recipients);202 }).pipe(Effect.runPromise);
201 };
202 203
203 // HTTP server — serves static files or redirects to Vite dev server204 // HTTP server — serves static files or redirects to Vite dev server
204 const httpServer = http.createServer((req, res) => {205 const httpServer = http.createServer((req, res) => {
@@ -273,12 +274,10 @@ export const createServer = Effect.fn(function* (options: ServerOptions = {}): E · 68 unmodified lines
273 });274 });
274 });275 });
275 276
276 const closeAllClients = () => {277 const closeAllClients = Ref.get(clients).pipe(
277 for (const client of clients) {278 Effect.flatMap(Effect.forEach((client) => Effect.sync(() => client.close()))),
278 client.close();279 Effect.flatMap(() => Ref.set(clients, new Set())),
279 }280 );
280 clients.clear();
281 };
282 281
283 const listenOptions = host ? { host, port } : { port };282 const listenOptions = host ? { host, port } : { port };
284 283
@@ -295,15 +294,15 @@ export const createServer = Effect.fn(function* (options: ServerOptions = {}): E · 10 unmodified lines
295 );294 );
296 295
297 yield* Stream.runForEach(orchestrationEngine.streamDomainEvents, (event) =>296 yield* Stream.runForEach(orchestrationEngine.streamDomainEvents, (event) =>
298 Effect.sync(() => {297 Effect.gen(function* () {
299 const push: WsPush = {298 const push: WsPush = {
300 type: "push",299 type: "push",
301 channel: ORCHESTRATION_WS_CHANNELS.domainEvent,300 channel: ORCHESTRATION_WS_CHANNELS.domainEvent,
302 data: event,301 data: event,
303 };302 };
304 const message = JSON.stringify(push);303 const message = yield* Schema.encodeEffect(Schema.fromJsonString(WsPush))(push);
305 let recipients = 0;304 let recipients = 0;
306 for (const client of clients) {305 for (const client of yield* Ref.get(clients)) {
307 if (client.readyState === client.OPEN) {306 if (client.readyState === client.OPEN) {
308 client.send(message);307 client.send(message);
309 recipients += 1;308 recipients += 1;
@@ -532,7 +531,7 @@ export const createServer = Effect.fn(function* (options: ServerOptions = {}): E · 222 unmodified lines
532 });531 });
533 532
534 wss.on("connection", (ws) => {533 wss.on("connection", (ws) => {
535 clients.add(ws);534 void Effect.runPromise(Ref.update(clients, (clients) => clients.add(ws)));
536 535
537 const segments = cwd.split(/[/\\]/).filter(Boolean);536 const segments = cwd.split(/[/\\]/).filter(Boolean);
538 const projectName = segments[segments.length - 1] ?? "project";537 const projectName = segments[segments.length - 1] ?? "project";
@@ -550,11 +549,21 @@ export const createServer = Effect.fn(function* (options: ServerOptions = {}): E · 11 unmodified lines
550 });549 });
551 550
552 ws.on("close", () => {551 ws.on("close", () => {
553 clients.delete(ws);552 void Effect.runPromise(
553 Ref.update(clients, (clients) => {
554 clients.delete(ws);
555 return clients;
556 }),
557 );
554 });558 });
555 559
556 ws.on("error", () => {560 ws.on("error", () => {
557 clients.delete(ws);561 void Effect.runPromise(
562 Ref.update(clients, (clients) => {
563 clients.delete(ws);
564 return clients;
565 }),
566 );
558 });567 });
559 });568 });
560 569
@@ -575,10 +584,7 @@ export const createServer = Effect.fn(function* (options: ServerOptions = {}): E · 14 unmodified lines
575 yield* NodeHttpServer.make(() => httpServer, listenOptions);584 yield* NodeHttpServer.make(() => httpServer, listenOptions);
576 585
577 yield* Effect.addFinalizer(() =>586 yield* Effect.addFinalizer(() =>
578 Effect.all([587 Effect.all([closeAllClients, closeWebSocketServer.pipe(Effect.orElseSucceed(() => undefined))]),
579 Effect.sync(() => closeAllClients()),
580 closeWebSocketServer.pipe(Effect.orElseSucceed(() => undefined)),
581 ]),
582 );588 );
583 589
584 return httpServer;590 return httpServer;