feat: use CF Service Bindings for logic components (no public network)
- Add 15 [[services]] bindings in cypher-executor wrangler.toml - component-loader now calls logic Workers via Service Binding (svc.fetch) instead of public URL fetch (which caused 522 timeout within same zone) - Fallback to public URL if binding not available (dev/testing) - Add ServiceBinding type to Bindings Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -21,23 +21,23 @@
|
||||
import { BUILTIN_COMPONENTS } from './constants';
|
||||
import type { Bindings, ComponentRunner } from '../types';
|
||||
|
||||
/** 邏輯零件 canonical_id → Worker URL */
|
||||
const LOGIC_COMPONENT_URLS: Record<string, string> = {
|
||||
if_control: 'https://if-control.arcrun.dev',
|
||||
switch: 'https://switch.arcrun.dev',
|
||||
foreach_control: 'https://foreach-control.arcrun.dev',
|
||||
filter: 'https://filter.arcrun.dev',
|
||||
merge: 'https://merge.arcrun.dev',
|
||||
try_catch: 'https://try-catch.arcrun.dev',
|
||||
wait: 'https://wait.arcrun.dev',
|
||||
set: 'https://set.arcrun.dev',
|
||||
array_ops: 'https://array-ops.arcrun.dev',
|
||||
string_ops: 'https://string-ops.arcrun.dev',
|
||||
number_ops: 'https://number-ops.arcrun.dev',
|
||||
date_ops: 'https://date-ops.arcrun.dev',
|
||||
validate_json: 'https://validate-json.arcrun.dev',
|
||||
ai_transform_compile:'https://ai-transform-compile.arcrun.dev',
|
||||
ai_transform_run: 'https://ai-transform-run.arcrun.dev',
|
||||
/** 邏輯零件 canonical_id → Service Binding key */
|
||||
const LOGIC_BINDING_MAP: Record<string, keyof import('../types').Bindings> = {
|
||||
if_control: 'SVC_IF_CONTROL',
|
||||
switch: 'SVC_SWITCH',
|
||||
foreach_control: 'SVC_FOREACH_CONTROL',
|
||||
filter: 'SVC_FILTER',
|
||||
merge: 'SVC_MERGE',
|
||||
try_catch: 'SVC_TRY_CATCH',
|
||||
wait: 'SVC_WAIT',
|
||||
set: 'SVC_SET',
|
||||
array_ops: 'SVC_ARRAY_OPS',
|
||||
string_ops: 'SVC_STRING_OPS',
|
||||
number_ops: 'SVC_NUMBER_OPS',
|
||||
date_ops: 'SVC_DATE_OPS',
|
||||
validate_json: 'SVC_VALIDATE_JSON',
|
||||
ai_transform_compile: 'SVC_AI_TRANSFORM_COMPILE',
|
||||
ai_transform_run: 'SVC_AI_TRANSFORM_RUN',
|
||||
};
|
||||
|
||||
/** API 零件 canonical_id → recipe(endpoint + 組裝邏輯)*/
|
||||
@@ -158,21 +158,35 @@ export function createComponentLoader(env: Bindings) {
|
||||
};
|
||||
}
|
||||
|
||||
// 3. 邏輯零件 Worker
|
||||
const logicUrl = LOGIC_COMPONENT_URLS[componentId];
|
||||
if (logicUrl) {
|
||||
// 3. 邏輯零件 → Service Binding(CF Workers 直接呼叫,不走公網)
|
||||
const bindingKey = LOGIC_BINDING_MAP[componentId];
|
||||
if (bindingKey) {
|
||||
const svc = env[bindingKey] as import('../types').ServiceBinding | undefined;
|
||||
if (svc) {
|
||||
return async (ctx: unknown) => {
|
||||
const res = await fetch(logicUrl, {
|
||||
const res = await svc.fetch(new Request('https://component/', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(ctx),
|
||||
}));
|
||||
if (!res.ok) {
|
||||
const text = await res.text();
|
||||
return { success: false, error: `${componentId} 回傳 ${res.status}: ${text.slice(0, 200)}` };
|
||||
}
|
||||
try { return await res.json(); }
|
||||
catch { return { success: false, error: `${componentId} 回傳非 JSON` }; }
|
||||
};
|
||||
}
|
||||
// Service Binding 未配置時 fallback 到公網 URL(開發環境)
|
||||
const fallbackUrl = `https://${componentId.replace(/_/g, '-')}.arcrun.dev`;
|
||||
return async (ctx: unknown) => {
|
||||
const res = await fetch(fallbackUrl, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(ctx),
|
||||
});
|
||||
if (!res.ok) {
|
||||
const text = await res.text();
|
||||
return { success: false, error: `${componentId} Worker 回傳 ${res.status}: ${text.slice(0, 200)}` };
|
||||
}
|
||||
try { return await res.json(); }
|
||||
catch { return { success: false, error: `${componentId} Worker 回傳非 JSON` }; }
|
||||
catch { return { success: false, error: `${componentId} fallback 失敗` }; }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,27 @@
|
||||
// arcrun cypher-executor 型別定義
|
||||
|
||||
// Service Binding 型別(CF Workers 直接呼叫,不走公網)
|
||||
export type ServiceBinding = {
|
||||
fetch(request: Request): Promise<Response>;
|
||||
};
|
||||
|
||||
export type Bindings = {
|
||||
// Logic component Service Bindings
|
||||
SVC_IF_CONTROL: ServiceBinding;
|
||||
SVC_SWITCH: ServiceBinding;
|
||||
SVC_FOREACH_CONTROL: ServiceBinding;
|
||||
SVC_FILTER: ServiceBinding;
|
||||
SVC_MERGE: ServiceBinding;
|
||||
SVC_TRY_CATCH: ServiceBinding;
|
||||
SVC_WAIT: ServiceBinding;
|
||||
SVC_SET: ServiceBinding;
|
||||
SVC_ARRAY_OPS: ServiceBinding;
|
||||
SVC_STRING_OPS: ServiceBinding;
|
||||
SVC_NUMBER_OPS: ServiceBinding;
|
||||
SVC_DATE_OPS: ServiceBinding;
|
||||
SVC_VALIDATE_JSON: ServiceBinding;
|
||||
SVC_AI_TRANSFORM_COMPILE: ServiceBinding;
|
||||
SVC_AI_TRANSFORM_RUN: ServiceBinding;
|
||||
// KV Context Store:節點 output 透過 KV 傳遞,解決同名欄位衝突
|
||||
EXEC_CONTEXT: KVNamespace;
|
||||
// Webhook Store:key = workflow name,value = Workflow JSON
|
||||
|
||||
@@ -26,6 +26,66 @@ bucket_name = "arcrun-wasm"
|
||||
[ai]
|
||||
binding = "AI"
|
||||
|
||||
[[services]]
|
||||
binding = "SVC_IF_CONTROL"
|
||||
service = "arcrun-if-control"
|
||||
|
||||
[[services]]
|
||||
binding = "SVC_SWITCH"
|
||||
service = "arcrun-switch"
|
||||
|
||||
[[services]]
|
||||
binding = "SVC_FOREACH_CONTROL"
|
||||
service = "arcrun-foreach-control"
|
||||
|
||||
[[services]]
|
||||
binding = "SVC_FILTER"
|
||||
service = "arcrun-filter"
|
||||
|
||||
[[services]]
|
||||
binding = "SVC_MERGE"
|
||||
service = "arcrun-merge"
|
||||
|
||||
[[services]]
|
||||
binding = "SVC_TRY_CATCH"
|
||||
service = "arcrun-try-catch"
|
||||
|
||||
[[services]]
|
||||
binding = "SVC_WAIT"
|
||||
service = "arcrun-wait"
|
||||
|
||||
[[services]]
|
||||
binding = "SVC_SET"
|
||||
service = "arcrun-set"
|
||||
|
||||
[[services]]
|
||||
binding = "SVC_ARRAY_OPS"
|
||||
service = "arcrun-array-ops"
|
||||
|
||||
[[services]]
|
||||
binding = "SVC_STRING_OPS"
|
||||
service = "arcrun-string-ops"
|
||||
|
||||
[[services]]
|
||||
binding = "SVC_NUMBER_OPS"
|
||||
service = "arcrun-number-ops"
|
||||
|
||||
[[services]]
|
||||
binding = "SVC_DATE_OPS"
|
||||
service = "arcrun-date-ops"
|
||||
|
||||
[[services]]
|
||||
binding = "SVC_VALIDATE_JSON"
|
||||
service = "arcrun-validate-json"
|
||||
|
||||
[[services]]
|
||||
binding = "SVC_AI_TRANSFORM_COMPILE"
|
||||
service = "arcrun-ai-transform-compile"
|
||||
|
||||
[[services]]
|
||||
binding = "SVC_AI_TRANSFORM_RUN"
|
||||
service = "arcrun-ai-transform-run"
|
||||
|
||||
[vars]
|
||||
ENVIRONMENT = "production"
|
||||
# MULTI_TENANT = "true"
|
||||
|
||||
Reference in New Issue
Block a user