History

Run deferred tool syncs off the request on local, self-host and cloudflare

Rhys Sullivan committed 3 months ago

Commit 936f95e1 parent d5459f43 files · +20 −2Browse files

Unified · Split

3 files
  1. apps/host-cloudflare/src/execution.ts +7 −1
  2. apps/host-selfhost/src/execution.ts +8 −1
  3. apps/local/src/executor.ts +5 −0
apps/host-cloudflare/src/execution.ts+7−1
@@ -12,7 +12,7 @@ import { · 11 unmodified lines
12} from "@executor-js/api/server";12} from "@executor-js/api/server";
13import { makeDynamicWorkerExecutor } from "@executor-js/runtime-dynamic-worker";13import { makeDynamicWorkerExecutor } from "@executor-js/runtime-dynamic-worker";
14import { makeQuickJsExecutor } from "@executor-js/runtime-quickjs";14import { makeQuickJsExecutor } from "@executor-js/runtime-quickjs";
15import { env } from "cloudflare:workers";15import { env, waitUntil } from "cloudflare:workers";
16 16
17import type { CloudflareConfig } from "./config";17import type { CloudflareConfig } from "./config";
18import { makeCloudflarePlugins } from "./plugins";18import { makeCloudflarePlugins } from "./plugins";
@@ -56,6 +56,12 @@ export const makeCloudflareHostConfig = (config: CloudflareConfig): Layer.Layer< · 37 unmodified lines
56 allowLocalNetwork: config.allowLocalNetwork,56 allowLocalNetwork: config.allowLocalNetwork,
57 webBaseUrl: config.webBaseUrl,57 webBaseUrl: config.webBaseUrl,
58 oauthCallbackPath: "/api/oauth/callback",58 oauthCallbackPath: "/api/oauth/callback",
59 // A Worker, so a tools read's speculative catalog refresh needs `waitUntil`
60 // to survive the response at all. Unlike cloud's Hyperdrive plane there is
61 // nothing to drain it before: the storage here is a D1 binding read
62 // straight off `env`, with no pool and no close finalizer, so a detached
63 // batch still has everything it needs after the response is written.
64 deferToolSync: (task) => Effect.sync(() => waitUntil(Effect.runPromise(task))),
59 });65 });
60 66
61/**67/**
apps/host-selfhost/src/execution.ts+8−1
@@ -1,4 +1,4 @@
1import { Layer } from "effect";1import { Effect, Layer } from "effect";
2 2
3import {3import {
4 CodeExecutorProvider,4 CodeExecutorProvider,
@@ -60,6 +60,13 @@ export const SelfHostHostConfig: Layer.Layer<HostConfig> = Layer.sync(HostConfig · 55 unmodified lines
60 event.kind === "added" ? "integration_added" : "integration_removed",60 event.kind === "added" ? "integration_added" : "integration_removed",
61 { plugin_key: event.pluginKey },61 { plugin_key: event.pluginKey },
62 ),62 ),
63 // Self-host is one long-lived process over one long-lived libSQL handle, so
64 // a speculative catalog refresh just goes to a detached fiber: the handle
65 // it needs outlives every request, and there is no isolate to keep alive.
66 // Detached, not `forkScoped` — the request scope this is called from closes
67 // as soon as the response is written, which is precisely what the work has
68 // to outlive. The task is total by contract, so nothing escapes the fork.
69 deferToolSync: (task) => Effect.asVoid(Effect.forkDetach(task)),
63 };70 };
64});71});
65 72
apps/local/src/executor.ts+5−0
@@ -201,6 +201,11 @@ const createLocalExecutorLayer = (options: LocalExecutorOptions = {}) => { · 200 unmodified lines
201 event.kind === "added" ? "integration_added" : "integration_removed",201 event.kind === "added" ? "integration_added" : "integration_removed",
202 { plugin_key: event.pluginKey },202 { plugin_key: event.pluginKey },
203 ),203 ),
204 // The daemon owns its sqlite handle for its whole lifetime, so a tools
205 // read's speculative catalog refresh goes to a detached fiber and the
206 // read answers without waiting on an MCP server's handshake. The task
207 // is total by contract, so nothing escapes the fork.
208 deferToolSync: (task) => Effect.asVoid(Effect.forkDetach(task)),
204 onElicitation: "accept-all",209 onElicitation: "accept-all",
205 oauthEndpointUrlPolicy: { allowHttp: true },210 oauthEndpointUrlPolicy: { allowHttp: true },
206 // EXPLICIT OAuth callback — the daemon serves the v2 `/api/oauth/callback`211 // EXPLICIT OAuth callback — the daemon serves the v2 `/api/oauth/callback`

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t