跳至正文
Wener Notes

Workflow

约 2 分钟阅读

Vercel Workflow

  • @workflow/vitest
  • @workflow/vite
  • @workflow/world-postgres
  • @workflow/world
  • 社区
    • @workflow-worlds/turso
    • @fantasticfour/world-nats-jetstream
  • 推荐 *.workflow.ts 命名
TypeScript
function workflow() {
  'use workflow';
  // 不可用
  // fs, path, http, https, net, dns, child_process, cluster, os, stream, crypto
  // fetch -> `import { fetch } from "workflow"`
  // setTimeout, setInterval, setImmediate, clear* -> sleep
  // Buffer -> Uint8Array
  //
  // 可用但固定
  // Math.random
  // Date / Date.now() / new Date()
  // crypto.getRandomValues(), crypto.randomUUID()
  // crypto.subtle.digest()
  //
  // WebAPI 可用
  // Headers
  // TextEncoder / TextDecoder
  // URL / URLSearchParams
  // Request / Response
  // console
  // structuredClone
  // atob / btoa
}
function step() {
  'use step';
  // 完整 Node 环境
}

Vitest

  • workflowTransformPlugin
    • 处理 use workflow, use step
TypeScript
import { workflow } from '@workflow/vitest';

export default defineConfig({
  plugins: [workflow()],
});
TypeScript
// globalSetup
await buildWorkflowTests();

beforeAll(async () => {
  await setupWorkflowTests();
});

afterAll(async () => {
  await teardownWorkflowTests();
});

另外的配置方式

TypeScript
import { workflowTransformPlugin } from '@workflow/rollup';
import { defineConfig } from 'vitest/config';

export default defineConfig({
  plugins: [workflowTransformPlugin()],
  test: {
    include: ['src/workflow/**/*.test.ts'],
    globalSetup: './vitest.workflow.global-setup.ts',
    setupFiles: ['./vitest.workflow.setup.ts'],
  },
});
TypeScript
import { buildWorkflowTests } from '@workflow/vitest';

export async function setup() {
  await buildWorkflowTests();
}
TypeScript
import { setupWorkflowTests, teardownWorkflowTests } from '@workflow/vitest';
import { afterAll } from 'vitest';

await setupWorkflowTests();

afterAll(async () => {
  await teardownWorkflowTests();
});

Transform

  • @workflow/serde
  • Internal
    • registerStepFunction
    • workflowEntrypoint

Workflow

TypeScript
export async function orderFood(input: Input) {
  'use workflow';
  return doSomething(input);
}
TypeScript
export async function orderFood(input: Input) {
  return doSomething(input);
}

orderFood.workflowId = 'workflow//./src/order-food//orderFood';

globalThis.__private_workflows.set(orderFood.workflowId, orderFood);
TypeScript
const run = await start(orderFood, [input]);
TypeScript
const workflowMetadata = {
  workflowId: 'workflow//app//orderFood',
};

const run = await start(workflowMetadata, [input], {
  world,
});

packages/core/src/runtime/start.ts

TypeScript
const workflowName = workflow?.workflowId;

if (!workflowName) {
  throw new WorkflowRuntimeError("'start' received an invalid workflow function...");
}

Step

TypeScript
export async function charge(amount: number) {
  'use step';
  return paymentProvider.charge(amount);
}

Proxy

TypeScript
export const charge = globalThis[Symbol.for('WORKFLOW_USE_STEP')]('step//./src/payment//charge');

Bundle

TypeScript
async function charge(amount: number) {
  return paymentProvider.charge(amount);
}

const StepRegistrySymbol = Symbol.for('@workflow/core//registeredSteps');

const registry = (globalThis[StepRegistrySymbol] ??= new Map());

registry.set('step//./src/payment//charge', charge);

charge.stepId = 'step//./src/payment//charge';

关联信息

反向链接、本文链接的其他页面和外部资料。

参考资料

GitHub1 条
最近更新commit 1c2aff3编辑