Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: barebones cloudflare packages #43

Draft
wants to merge 46 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
3c3d943
feat: allow calling multiople workflows
Nov 21, 2022
d1fb22e
Merge branch 'main' into sam/call-workflow
Nov 21, 2022
74631a6
feat: update transpiler
Nov 21, 2022
7034f8d
feat: implement plumbing
Nov 21, 2022
4ede43a
chore: rename start to scheduled
Nov 21, 2022
72bdf69
feat: add workflowName to StartWorkflowRequest
Nov 21, 2022
a5b85e7
stash
Nov 23, 2022
1ca1b11
Merge branch 'main' into sam/call-workflow
Nov 23, 2022
e49435f
Merge branch 'main' into sam/call-workflow
Nov 23, 2022
e646ba3
stash
Nov 23, 2022
2fedfbb
fix: lookup workflowName from dynamodb
Nov 23, 2022
5869a8b
fix: pass through parent execution id and seq
Nov 23, 2022
d6b88ee
fix: encode workflow name in ID
Nov 23, 2022
61c33ae
chore: feedback
Nov 23, 2022
b64d0b1
fix: make completion idempotent
Nov 23, 2022
e0d1e20
fix: feedback
Nov 23, 2022
e65ebcc
fix: tsc
Nov 23, 2022
a3226f1
fix: add context into workflow
Nov 23, 2022
bee8e83
fix: add context into workflow
Nov 23, 2022
22cd195
docs
Nov 23, 2022
ffb24b5
feat: workflow handler type
Nov 23, 2022
d6d2c91
fix tests
Nov 23, 2022
9ba9559
chore
Nov 23, 2022
47add26
Merge branch 'main' into sam/call-workflow
Nov 23, 2022
feb6f02
fix:
Nov 23, 2022
9382151
bug still exists
Nov 23, 2022
e1212aa
Merge branch 'main' into sam/call-workflow
Nov 23, 2022
67aaec7
feat: barebones of cloudflare
Nov 23, 2022
a8af120
fix: stash
Nov 23, 2022
8528d81
Merge branch 'main' into sam/cloudflare
Nov 24, 2022
528043c
feat: set up webhook function url with itty router
Nov 24, 2022
4c94d8a
feat: runtime client interfaces and webhook router
Nov 25, 2022
de01f0f
feat: bundle webhooks
Nov 25, 2022
37dc16a
fix: parse web hooks
Nov 25, 2022
212d82f
chore: clean
Nov 25, 2022
1996fdb
chore: clean
Nov 25, 2022
8b45843
chore: move global
Nov 25, 2022
6c979a0
fix: standardize request interface for workflow runtime client
Nov 26, 2022
1057822
chore: feedback
Nov 26, 2022
a9ea104
chore: feedback
Nov 26, 2022
c0eae28
chore: add webhookEndpointUrl
Nov 26, 2022
6500fdc
chore: feedback
Nov 26, 2022
41a2434
chore: feedback
Nov 26, 2022
3ba5868
Merge branch 'sam/webhook' into sam/cloudflare
Nov 26, 2022
0d924e8
feat: CFWorkflowClient
Nov 26, 2022
c79a6a1
fet: add parentExecutionId and seq
Nov 27, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions apps/test-app-cloudflare/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "test-app-cloudflare",
"version": "0.0.0",
"dependencies": {
"@eventual/cloudflare-runtime": "workspace:^"
},
"devDependencies": {
"@cloudflare/workers-types": "^4.20221111.1",
"typescript": "^4.9.3",
"wrangler": "2.4.4"
},
"private": true,
"scripts": {
"start": "wrangler dev",
"deploy": "wrangler publish"
}
}
30 changes: 30 additions & 0 deletions apps/test-app-cloudflare/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* Welcome to Cloudflare Workers! This is your first worker.
*
* - Run `wrangler dev src/index.ts` in your terminal to start a development server
* - Open a browser tab at http://localhost:8787/ to see your worker in action
* - Run `wrangler publish src/index.ts --name my-worker` to publish your worker
*
* Learn more at https://developers.cloudflare.com/workers/
*/

export interface Env {
// Example binding to KV. Learn more at https://developers.cloudflare.com/workers/runtime-apis/kv/
// MY_KV_NAMESPACE: KVNamespace;
//
// Example binding to Durable Object. Learn more at https://developers.cloudflare.com/workers/runtime-apis/durable-objects/
// MY_DURABLE_OBJECT: DurableObjectNamespace;
//
// Example binding to R2. Learn more at https://developers.cloudflare.com/workers/runtime-apis/r2/
// MY_BUCKET: R2Bucket;
}

export default {
async fetch(
request: Request,
env: Env,
ctx: ExecutionContext
): Promise<Response> {
return new Response("Hello World!");
},
};
15 changes: 15 additions & 0 deletions apps/test-app-cloudflare/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"extends": "../../tsconfig-base",
"compilerOptions": {
"outDir": "lib",
"declaration": true,
"inlineSourceMap": true,
"rootDir": "src",
"types": ["@cloudflare/workers-types"],
"typeRoots": ["./node_modules/@types"],
"allowJs": true
},
"include": ["src"],
"exclude": ["lib", "node_modules"],
"references": [{ "path": "../../packages/@eventual/core" }]
}
3 changes: 3 additions & 0 deletions apps/test-app-cloudflare/wrangler.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
name = "test-app-cloudflare"
main = "src/index.ts"
compatibility_date = "2022-11-23"
42 changes: 31 additions & 11 deletions apps/test-app-runtime/src/open-account.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { activity, workflow } from "@eventual/core";
import { activity, hook, workflow } from "@eventual/core";

import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import {
Expand Down Expand Up @@ -33,16 +33,19 @@ interface OpenAccountRequest {

type RollbackHandler = () => Promise<void>;

export default workflow("open-account", async (request: OpenAccountRequest) => {
try {
await createAccount(request.accountId);
} catch (err) {
console.error(err);
throw err;
}
export const openAccount = workflow(
"open-account",
async (request: OpenAccountRequest) => {
try {
await createAccount(request.accountId);
} catch (err) {
console.error(err);
throw err;
}

await associateAccountInformation(request);
});
await associateAccountInformation(request);
}
);

// sub-workflow for testing purposes
export const associateAccountInformation = workflow(
Expand All @@ -65,14 +68,31 @@ export const associateAccountInformation = workflow(
}
);

// register a web hook API route
hook((api) => {
api.post("/open-account", async (request) => {
const input = await request.json!();

const response = await openAccount.startExecution({
input,
});

return new Response(JSON.stringify(response), {
headers: {
"Content-Type": "application/json",
},
status: 200,
});
});
});

const TableName = process.env.TABLE_NAME!;

const dynamo = memoize(() =>
DynamoDBDocumentClient.from(new DynamoDBClient({}))
);

const createAccount = activity("createAccount", async (accountId: string) => {
console.log("processing", accountId);
await dynamo().send(
new PutCommand({
TableName,
Expand Down
11 changes: 8 additions & 3 deletions apps/test-app/open-account-input.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
{
"accountId": "4",
"address": { "address1": "Home" },
"accountId": "6",
"address": {
"address1": "Home"
},
"email": "[email protected]",
"bankDetails": {
"accountNumber": "123",
"accountType": "savings",
"personOwner": { "firstName": "John", "lastName": "Smith" },
"personOwner": {
"firstName": "John",
"lastName": "Smith"
},
"routingNumber": "345"
}
}
3 changes: 1 addition & 2 deletions apps/test-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@
"version": "0.0.0",
"main": "lib/index.js",
"scripts": {
"build": "cdk synth",
"cdk": "cdk",
"deploy": "cdk deploy --require-approval=never",
"hotswap": "cdk deploy --hotswap",
"hotswap": "cdk deploy --hotswap --require-approval=never",
"eventual": "eventual",
"start-my-workflow": "eventual start my-workflow --input '{\"name\": \"world\"}' --tail"
},
Expand Down
41 changes: 39 additions & 2 deletions packages/@eventual/aws-cdk/src/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import {
Code,
IFunction,
Runtime,
FunctionUrlAuthType,
FunctionUrl,
} from "aws-cdk-lib/aws-lambda";
import { Construct } from "constructs";
import { Bucket, IBucket } from "aws-cdk-lib/aws-s3";
Expand Down Expand Up @@ -43,6 +45,9 @@ export interface WorkflowProps {
}

export class Service extends Construct implements IGrantable {
/**
* Name of this Service.
*/
public readonly serviceName: string;
/**
* S3 bucket that contains events necessary to replay a workflow execution.
Expand Down Expand Up @@ -105,6 +110,14 @@ export class Service extends Construct implements IGrantable {
* Timers - When the EventBridge scheduler fails to invoke the Schedule Forwarder Lambda.
*/
public readonly dlq: Queue;
/**
* A Lambda Function for processing inbound webhook requests.
*/
public readonly webhookEndpoint: IFunction;
/**
* The URL of the webhook endpoint.
*/
public readonly webhookEndpointUrl: FunctionUrl;

readonly grantPrincipal: IPrincipal;

Expand Down Expand Up @@ -182,8 +195,8 @@ export class Service extends Construct implements IGrantable {

this.activityWorker = new Function(this, "Worker", {
architecture: Architecture.ARM_64,
code: Code.fromAsset(path.join(outDir, "activity-worker")),
// the bundler outputs activity-worker/index.js
code: Code.fromAsset(path.join(outDir, "activity")),
// the bundler outputs activity/index.js
handler: "index.default",
runtime: Runtime.NODEJS_16_X,
memorySize: 512,
Expand Down Expand Up @@ -373,5 +386,29 @@ export class Service extends Construct implements IGrantable {
},
}),
});

this.webhookEndpoint = new Function(this, "WebhookEndpoint", {
architecture: Architecture.ARM_64,
code: Code.fromAsset(path.join(outDir, "webhook")),
// the bundler outputs orchestrator/index.js
handler: "index.default",
runtime: Runtime.NODEJS_16_X,
memorySize: 512,
environment: {
NODE_OPTIONS: "--enable-source-maps",
[ENV_NAMES.TABLE_NAME]: this.table.tableName,
[ENV_NAMES.WORKFLOW_QUEUE_URL]: this.workflowQueue.queueUrl,
[ENV_NAMES.EVENTUAL_WEBHOOK]: "1",
},
});
this.webhookEndpointUrl = this.webhookEndpoint.addFunctionUrl({
authType: FunctionUrlAuthType.NONE,
});

// the webhook endpoint is allowed to run workflows
this.workflowQueue.grantSendMessages(this.webhookEndpoint);

// Enable creating history to start a workflow.
this.table.grantReadWriteData(this.webhookEndpoint);
}
}
9 changes: 6 additions & 3 deletions packages/@eventual/aws-runtime/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,28 @@
"aws-lambda": "^1.0.7",
"fast-equals": "^4.0.3",
"micro-memoize": "^4.0.11",
"node-fetch": "^3.3.0",
"ulidx": "^0.3.0"
},
"peerDependencies": {
"@aws-sdk/client-dynamodb": "^3.208.0",
"@aws-sdk/client-lambda": "^3.208.0",
"@aws-sdk/client-s3": "^3.208.0",
"@aws-sdk/client-sqs": "^3.208.0",
"@aws-sdk/client-scheduler": "^3.208.0",
"@types/aws-lambda": "8.10.108"
"@aws-sdk/client-sqs": "^3.208.0",
"@types/aws-lambda": "8.10.108",
"itty-router": "^2.6.6"
},
"devDependencies": {
"@aws-sdk/client-dynamodb": "3.214.0",
"@aws-sdk/client-lambda": "^3.213.0",
"@aws-sdk/client-s3": "3.213.0",
"@aws-sdk/client-sqs": "3.213.0",
"@aws-sdk/client-scheduler": "3.213.0",
"@aws-sdk/client-sqs": "3.213.0",
"@types/aws-lambda": "8.10.108",
"@types/jest": "^29",
"@types/node": "^16",
"itty-router": "2.6.6",
"jest": "^29",
"ts-jest": "^29",
"ts-node": "^10.9.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@ import {
DynamoDBClient,
PutItemCommand,
} from "@aws-sdk/client-dynamodb";
import { ScheduleActivityCommand } from "@eventual/core";
import type eventual from "@eventual/core";

export interface ActivityRuntimeClientProps {
export interface AWSActivityRuntimeClientProps {
dynamo: DynamoDBClient;
activityLockTableName: string;
}

export class ActivityRuntimeClient {
constructor(private props: ActivityRuntimeClientProps) {}
export class AWSActivityRuntimeClient
implements eventual.ActivityRuntimeClient
{
constructor(private props: AWSActivityRuntimeClientProps) {}

/**
* Claims a activity for an actor.
Expand All @@ -23,7 +25,7 @@ export class ActivityRuntimeClient {
**/
async requestExecutionActivityClaim(
executionId: string,
command: ScheduleActivityCommand,
command: eventual.ScheduleActivityCommand,
retry: number,
claimer?: string
) {
Expand Down Expand Up @@ -58,7 +60,7 @@ export namespace ActivityLockRecord {
export const PARTITION_KEY_PREFIX = `Activity$`;
export function key(
executionId: string,
command: ScheduleActivityCommand,
command: eventual.ScheduleActivityCommand,
retry: number
) {
return `${PARTITION_KEY_PREFIX}$${executionId}$${command.seq}${retry}`;
Expand Down
Loading