(handlers: ServerHandlers)
| 55 | }).pipe(Effect.ignore); |
| 56 | |
| 57 | const closeServerHandlers = async (handlers: ServerHandlers): Promise<void> => { |
| 58 | await Effect.runPromise( |
| 59 | Effect.gen(function* () { |
| 60 | yield* Effect.all( |
| 61 | [ |
| 62 | ignoreDisposeFailure("api.dispose", () => handlers.api.dispose()), |
| 63 | ignoreDisposeFailure("mcp.close", () => handlers.mcp.close()), |
| 64 | ], |
| 65 | { concurrency: "unbounded" }, |
| 66 | ); |
| 67 | // The API/MCP handlers borrow the shared local executor handle. Release it |
| 68 | // after the surfaces are closed so server shutdown (and failed startup |
| 69 | // cleanup via disposeServerHandlers) releases the owned data-dir lock. |
| 70 | yield* ignoreDisposeFailure("disposeExecutor", () => disposeExecutor()); |
| 71 | }), |
| 72 | ); |
| 73 | }; |
| 74 | |
| 75 | export const createServerHandlers = async (token: string): Promise<ServerHandlers> => { |
| 76 | let apiHandler: ServerHandlers["api"] | null = null; |
no test coverage detected