History

cleanup

Tim Smart committed 8 months ago

Commit fd988351 parent c6dc7c62 files · +26 −66Browse files

Unified · Split

2 files
  1. apps/server/src/provider/Layers/ProviderHealth.ts +6 −49
  2. apps/server/src/wsServer.ts +20 −17
apps/server/src/provider/Layers/ProviderHealth.ts+6−49
@@ -13,7 +13,7 @@ import type { · 12 unmodified lines
13 ServerProviderStatus,13 ServerProviderStatus,
14 ServerProviderStatusState,14 ServerProviderStatusState,
15} from "@t3tools/contracts";15} from "@t3tools/contracts";
16import { Effect, Layer, Option, Result, Stream } from "effect";16import { Array, Effect, Fiber, Layer, Option, Result, Stream } from "effect";
17import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process";17import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process";
18 18
19import {19import {
@@ -312,56 +312,13 @@ export const checkCodexProviderStatus: Effect.Effect< · 292 unmodified lines
312export const ProviderHealthLive = Layer.effect(312export const ProviderHealthLive = Layer.effect(
313 ProviderHealth,313 ProviderHealth,
314 Effect.gen(function* () {314 Effect.gen(function* () {
315 const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;315 const codexStatusFiber = yield* checkCodexProviderStatus.pipe(
316 let cachedStatuses: ReadonlyArray<ServerProviderStatus> = [316 Effect.map(Array.of),
317 {317 Effect.forkScoped,
318 provider: CODEX_PROVIDER,318 );
319 status: "warning",
320 available: false,
321 authStatus: "unknown",
322 checkedAt: new Date().toISOString(),
323 message: "Checking Codex CLI availability...",
324 },
325 ];
326
327 let readyListeners: Array<(statuses: ReadonlyArray<ServerProviderStatus>) => void> = [];
328 let resolved = false;
329
330 const notifyReady = (statuses: ReadonlyArray<ServerProviderStatus>) => {
331 resolved = true;
332 cachedStatuses = statuses;
333 for (const cb of readyListeners) cb(statuses);
334 readyListeners = [];
335 };
336
337 // Run health checks in the background so they don't block server startup.
338 checkCodexProviderStatus.pipe(
339 Effect.provideService(ChildProcessSpawner.ChildProcessSpawner, spawner),
340 Effect.runPromise,
341 ).then((status) => {
342 notifyReady([status]);
343 }).catch(() => {
344 notifyReady([
345 {
346 provider: CODEX_PROVIDER,
347 status: "error",
348 available: false,
349 authStatus: "unknown",
350 checkedAt: new Date().toISOString(),
351 message: "Failed to check Codex CLI status.",
352 },
353 ]);
354 });
355 319
356 return {320 return {
357 getStatuses: Effect.sync(() => cachedStatuses),321 getStatuses: Fiber.join(codexStatusFiber),
358 onReady: (cb) => {
359 if (resolved) {
360 cb(cachedStatuses);
361 } else {
362 readyListeners.push(cb);
363 }
364 },
365 } satisfies ProviderHealthShape;322 } satisfies ProviderHealthShape;
366 }),323 }),
367);324);
apps/server/src/wsServer.ts+20−17
@@ -26,6 +26,7 @@ import { · 25 unmodified lines
26 WebSocketRequest,26 WebSocketRequest,
27 WsPush,27 WsPush,
28 WsResponse,28 WsResponse,
29 ServerProviderStatus,
29} from "@t3tools/contracts";30} from "@t3tools/contracts";
30import * as NodeHttpServer from "@effect/platform-node/NodeHttpServer";31import * as NodeHttpServer from "@effect/platform-node/NodeHttpServer";
31import {32import {
@@ -268,9 +269,6 @@ export const createServer = Effect.fn(function* (): Effect.fn.Return< · 236 unmodified lines
268 ),269 ),
269 );270 );
270 271
271 // Read provider statuses lazily so background health checks are reflected.
272 const getProviderStatuses = () => Effect.runSync(providerHealth.getStatuses);
273
274 const clients = yield* Ref.make(new Set<WebSocket>());272 const clients = yield* Ref.make(new Set<WebSocket>());
275 const logger = createLogger("ws");273 const logger = createLogger("ws");
276 274
@@ -618,6 +616,23 @@ export const createServer = Effect.fn(function* (): Effect.fn.Return< · 341 unmodified lines
618 const subscriptionsScope = yield* Scope.make("sequential");616 const subscriptionsScope = yield* Scope.make("sequential");
619 yield* Effect.addFinalizer(() => Scope.close(subscriptionsScope, Exit.void));617 yield* Effect.addFinalizer(() => Scope.close(subscriptionsScope, Exit.void));
620 618
619 // Push updated provider statuses to connected clients once background health checks finish.
620 let providers: ReadonlyArray<ServerProviderStatus> = [];
621 yield* providerHealth.getStatuses.pipe(
622 Effect.flatMap((statuses) => {
623 providers = statuses;
624 return broadcastPush({
625 type: "push",
626 channel: WS_CHANNELS.serverConfigUpdated,
627 data: {
628 issues: [],
629 providers: statuses,
630 },
631 });
632 }),
633 Effect.forkIn(subscriptionsScope),
634 );
635
621 yield* Stream.runForEach(orchestrationEngine.streamDomainEvents, (event) =>636 yield* Stream.runForEach(orchestrationEngine.streamDomainEvents, (event) =>
622 broadcastPush({637 broadcastPush({
623 type: "push",638 type: "push",
@@ -632,23 +647,11 @@ export const createServer = Effect.fn(function* (): Effect.fn.Return< · 8 unmodified lines
632 channel: WS_CHANNELS.serverConfigUpdated,647 channel: WS_CHANNELS.serverConfigUpdated,
633 data: {648 data: {
634 issues: event.issues,649 issues: event.issues,
635 providers: getProviderStatuses(),650 providers,
636 },651 },
637 }),652 }),
638 ).pipe(Effect.forkIn(subscriptionsScope));653 ).pipe(Effect.forkIn(subscriptionsScope));
639 654
640 // Push updated provider statuses to connected clients once background health checks finish.
641 providerHealth.onReady((statuses) => {
642 broadcastPush({
643 type: "push",
644 channel: WS_CHANNELS.serverConfigUpdated,
645 data: {
646 issues: [],
647 providers: statuses,
648 },
649 }).pipe(Effect.runPromise).catch(() => {});
650 });
651
652 yield* Scope.provide(orchestrationReactor.start, subscriptionsScope);655 yield* Scope.provide(orchestrationReactor.start, subscriptionsScope);
653 656
654 let welcomeBootstrapProjectId: ProjectId | undefined;657 let welcomeBootstrapProjectId: ProjectId | undefined;
@@ -896,7 +899,7 @@ export const createServer = Effect.fn(function* (): Effect.fn.Return< · 241 unmodified lines
896 keybindingsConfigPath,899 keybindingsConfigPath,
897 keybindings: keybindingsConfig.keybindings,900 keybindings: keybindingsConfig.keybindings,
898 issues: keybindingsConfig.issues,901 issues: keybindingsConfig.issues,
899 providers: getProviderStatuses(),902 providers,
900 availableEditors,903 availableEditors,
901 };904 };
902 905