Speed up Erxes executor provisioning - #3
Conversation
List-of-object fields were omitted from the default selection, so wrappers with totalCount succeeded with no rows. Short names from tools.search 404'd because the sandbox requires a five-segment address.
Use D1 batch inserts for tool catalog writes, skip redundant tool sync when a connection already has a fresh catalog, bundle offline GraphQL introspection for erxes-officenext, and enable global_fetch_strictly_public to avoid same-zone 301 loops.
Reviewer's GuideThe PR accelerates executor provisioning by batching D1 inserts, reusing fresh connection catalogs, and bundling OfficeNext GraphQL introspection at deploy time; it also adds signed Cloudflare OS provisioning routes, instance-aware deployment tooling, bounded GraphQL result shapes and selection guidance, and unique short-name MCP tool resolution. Sequence diagram for fast OfficeNext provisioningsequenceDiagram
participant OS as Cloudflare OS
participant Worker as Cloudflare Worker
participant Executor as Executor API
participant D1 as D1 Database
participant GraphQL as OfficeNext GraphQL
OS->>Worker: POST /os/provision
Worker->>Worker: verify Cloudflare OS JWT
Worker->>Worker: loadErxesIntrospection()
Worker->>Executor: GET /api/graphql/integrations/erxes-officenext
alt integration has no snapshot
Worker->>Executor: POST /api/graphql/integrations
Worker->>Executor: POST /api/graphql/integrations/erxes-officenext/introspection
end
Worker->>Executor: POST /api/connections
Executor->>D1: upsert connection
alt fresh healthy catalog exists
Executor->>D1: check existing tool row
Executor-->>Worker: reuse catalog and rotate credential
else catalog missing or stale
Executor->>GraphQL: introspect and produce tools
Executor->>D1: batch tool inserts
Executor-->>Worker: provisioned connection
end
Worker-->>OS: 200 response
Sequence diagram for GraphQL tool selection and invocationsequenceDiagram
participant Agent
participant MCP as MCP Tool Server
participant Executor
participant GraphQL as GraphQL API
Agent->>MCP: skills({ name: "graphql" })
MCP-->>Agent: selection guidance
Agent->>MCP: tools.describe.tool({ path })
MCP->>Executor: resolveSandboxToolPath(path)
Executor-->>MCP: qualified tool path and output shape
Agent->>MCP: tool({ select: "list { _id name } totalCount" })
MCP->>Executor: execute(address, args)
Executor->>GraphQL: query with explicit selection
GraphQL-->>Executor: bounded nested result
Executor-->>MCP: tool result
MCP-->>Agent: selected fields
Flow diagram for batched D1 tool insertionflowchart TD
Start[produceConnectionTools creates tool rows] --> Split[Split rows into batches of up to 500]
Split --> Limit[Group up to 1000 insert statements]
Limit --> Batch[Drizzle batch]
Batch --> D1[D1 single round trip per group]
D1 --> Results[Collect returned tool IDs]
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Hey - I've found 2 issues
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="apps/host-cloudflare/package.json" line_range="7" />
<code_context>
"scripts": {
- "build": "vite build && node scripts/assert-shell-asset.mjs",
+ "build": "node scripts/fetch-erxes-introspection.mjs && vite build && node scripts/assert-shell-asset.mjs && cp assets/erxes-introspection.json dist/erxes-introspection.json",
"deploy": "vite build && node scripts/assert-shell-asset.mjs && wrangler deploy",
"dev": "wrangler dev",
"dev:web": "vite dev",
</code_context>
<issue_to_address>
**issue (broader_impact):** The package `deploy` script still runs only `vite build` and does not fetch or copy `erxes-introspection.json` into `dist`, so deployments through `bun run deploy` omit the offline snapshot and first connection provisioning falls back to live GraphQL introspection.
**Triggers:** When the Worker is deployed through the package's `deploy` script rather than the bespoke `scripts/deploy.sh` flow.
**Suggested fix:** Make `deploy` invoke the same snapshot-fetching build or explicitly run `fetch-erxes-introspection.mjs` and copy the asset before `wrangler deploy`.
```suggestion
"deploy": "bun run build && wrangler deploy",
```
</issue_to_address>
### Comment 2
<location path="apps/host-cloudflare/src/worker.ts" line_range="111-122" />
<code_context>
+ return null;
+ }
+
+ const attached = await app(
+ executorRequest(
+ request,
+ `/api/graphql/integrations/${ERXES_INTEGRATION}/introspection`,
+ "POST",
+ {
+ introspectionJson,
+ },
+ ),
+ );
+ if (!attached.ok) return attached;
+ return null;
+};
+
</code_context>
<issue_to_address>
**issue (broader_impact):** When the existing `erxes-officenext` integration already exists, attaching the bundled snapshot does not update its endpoint from the current provision request. The connection is then created against `input.endpoint`, while generated GraphQL tools continue using the old integration endpoint.
**Triggers:** When the OfficeNext GraphQL endpoint changes between deployments or differs from the endpoint used by the first provision request.
**Suggested fix:** Update the integration endpoint when attaching the snapshot, or reject a conflicting endpoint explicitly.
</issue_to_address>Sourcery assessment
Needs a human reviewer. 2 findings to address first, and the new /os/* routes establish a separate HS256 bearer-token trust boundary and use its claims to authorize MCP access and persist user-provided Erxes cookies as connections; an error in that policy could allow forged identities or unauthorized access across the installation. Reverting the Worker would not revoke already-created connections or undo any access obtained while the route was active, and the deployment script also changes production resource and secret provisioning.
Blocking findings: apps/host-cloudflare/package.json:7, apps/host-cloudflare/src/worker.ts:122
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| "scripts": { | ||
| "build": "vite build && node scripts/assert-shell-asset.mjs", | ||
| "build": "node scripts/fetch-erxes-introspection.mjs && vite build && node scripts/assert-shell-asset.mjs && cp assets/erxes-introspection.json dist/erxes-introspection.json", | ||
| "deploy": "vite build && node scripts/assert-shell-asset.mjs && wrangler deploy", |
There was a problem hiding this comment.
issue (broader_impact): The package deploy script still runs only vite build and does not fetch or copy erxes-introspection.json into dist, so deployments through bun run deploy omit the offline snapshot and first connection provisioning falls back to live GraphQL introspection.
Triggers: When the Worker is deployed through the package's deploy script rather than the bespoke scripts/deploy.sh flow.
Suggested fix: Make deploy invoke the same snapshot-fetching build or explicitly run fetch-erxes-introspection.mjs and copy the asset before wrangler deploy.
| "deploy": "vite build && node scripts/assert-shell-asset.mjs && wrangler deploy", | |
| "deploy": "bun run build && wrangler deploy", |
| const attached = await app( | ||
| executorRequest( | ||
| request, | ||
| `/api/graphql/integrations/${ERXES_INTEGRATION}/introspection`, | ||
| "POST", | ||
| { | ||
| introspectionJson, | ||
| }, | ||
| ), | ||
| ); | ||
| if (!attached.ok) return attached; | ||
| return null; |
There was a problem hiding this comment.
issue (broader_impact): When the existing erxes-officenext integration already exists, attaching the bundled snapshot does not update its endpoint from the current provision request. The connection is then created against input.endpoint, while generated GraphQL tools continue using the old integration endpoint.
Triggers: When the OfficeNext GraphQL endpoint changes between deployments or differs from the endpoint used by the first provision request.
Suggested fix: Update the integration endpoint when attaching the snapshot, or reject a conflicting endpoint explicitly.
Summary
createManyinserts through Drizzle'sbatch()API so ~1,500 tool rows land in one round trip instead of ~227 sequential writesproduceConnectionToolson returning/os/provisionlogins when the connection already has a synced, healthy catalogglobal_fetch_strictly_publicon the Cloudflare host to stop same-zone 301 redirect loopsDeployed
executor.os.erxes.io— Worker versiona0a4972f-69c5-4065-9e70-1a8eade2ef08Test plan
curl -X POST https://executor.os.erxes.io/os/provisionwith valid gatekeeper token still returns 200Summary by Sourcery
Speed up Erxes executor provisioning by batching tool persistence, reusing healthy catalogs, and bundling GraphQL metadata ahead of first login.
New Features:
/os/provisionand/os/mcproutes for Erxes connections.Bug Fixes:
Enhancements:
Build:
Deployment:
Documentation:
Tests: