Skip to content

Commit

Permalink
Correct dispatcher
Browse files Browse the repository at this point in the history
  • Loading branch information
fabiancook committed Dec 24, 2023
1 parent 37f4ce6 commit 70d1785
Show file tree
Hide file tree
Showing 9 changed files with 93 additions and 57 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@ workerd-tests
workerd-tests.capnp
.cache
.vercel
kv.db
kv.db-shm
kv.db-wal
12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -240,20 +240,20 @@
"generate": "yarn build && node esnext/generate.js",
"test": "yarn build && yarn test:node",
"test:all": "yarn build && yarn test:node && yarn test:bun",
"test:node": "NODE_ENV=test TESTING=1 OTEL_SERVICE_NAME=logistics-tests node --env-file=.env.test --enable-source-maps esnext/tests/index.js",
"test:node:inspect": "yarn build && NODE_ENV=test TESTING=1 OTEL_SERVICE_NAME=logistics-tests node --env-file=.env.test --enable-source-maps --inspect-brk esnext/tests/index.js",
"test:node": "NODE_ENV=test TESTING=1 OTEL_SERVICE_NAME=logistics-tests node --no-warnings=DEP0040 --env-file=.env.test --enable-source-maps esnext/tests/index.js",
"test:node:inspect": "yarn build && NODE_ENV=test TESTING=1 OTEL_SERVICE_NAME=logistics-tests node --no-warnings=DEP0040 --env-file=.env.test --enable-source-maps --inspect-brk esnext/tests/index.js",
"test:bun": "NODE_ENV=test TESTING=1 OTEL_SERVICE_NAME=logistics-tests bun esnext/tests/index.js",
"coverage": "NODE_ENV=test TESTING=1 OTEL_SERVICE_NAME=logistics-tests c8 node --env-file=.env.test esnext/tests/index.js && yarn postbuild",
"start": "node --enable-source-maps --env-file=.env esnext/listen/main.js",
"start": "node --no-warnings=DEP0040 --enable-source-maps --env-file=.env esnext/listen/main.js",
"start:bun": "bun esnext/listen/main.js",
"start:nodemon": "nodemon --enable-source-maps --env-file=.env esnext/listen/main.js",
"start:nodemon": "nodemon --enable-source-maps --no-warnings=DEP0040 --env-file=.env esnext/listen/main.js",
"quick": "yarn build && yarn start",
"local": "yarn build && yarn seed && yarn start",
"seed": "node --enable-source-maps esnext/data/seed/main.js",
"seed": "node --enable-source-maps --no-warnings=DEP0040 esnext/data/seed/main.js",
"watch": "yarn build && concurrently --raw \"yarn start:nodemon\" \"yarn build:watch\" ",
"prettier:check": "prettier --check .",
"prettier": "prettier --write .",
"vork": "node ./esnext/worker/service-worker/configure/main.js",
"vork": "node --no-warnings=DEP0040 ./esnext/worker/service-worker/configure/main.js",
"bork": "bun ./esnext/worker/service-worker/configure/main.js"
},
"importmap": {
Expand Down
43 changes: 30 additions & 13 deletions src/events/dispatch/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {on, dispatchEvent} from "../schedule";
import type {DurableEventData, UnknownEvent} from "../../data";
import {isLike, ok} from "../../is";
import {getServiceWorkerModuleExports} from "../../worker/service-worker/worker-exports";
import {getDispatcherFunction} from "../schedule/schedule";

const DISPATCH = "dispatch" as const;
type DispatchEventType = typeof DISPATCH;
Expand Down Expand Up @@ -36,26 +37,42 @@ export async function onDispatchEvent(event: UnknownEvent) {
})));
return;
}
if (event.dispatch.type === "dispatch") {
let dispatching: DurableEventData;

if (typeof event.dispatch === "string") {
dispatching = {
type: event.dispatch
};
} else {
dispatching = {
...event.dispatch
};
}

if (dispatching.type === "dispatch") {
// This is to prevent infinite loops
console.warn("dispatch cannot be used to dispatch additional events");
return;
}
let dispatching: DurableEventData = {
...event.dispatch
};

const entrypointArguments = event.entrypointArguments;
async function dispatchEntrypointEvent(entrypoint: unknown) {
ok(typeof entrypoint === "function", "Expected entrypoint to be a function");
if (entrypointArguments) {
const dispatchArguments = entrypointArguments.map(
key => key === "$event" ? dispatching : dispatching[key]
);
return entrypoint(...dispatchArguments);
} else {
ok<typeof dispatchEvent>(entrypoint);
return entrypoint(dispatching);
const dispatcher = getDispatcherFunction({
event: dispatching
});
dispatcher.handler(dispatching, dispatch);

function dispatch(dispatching: DurableEventData) {
ok(typeof entrypoint === "function", "Expected entrypoint to be a function");
if (entrypointArguments) {
const dispatchArguments = entrypointArguments.map(
key => key === "$event" ? dispatching : dispatching[key]
);
return entrypoint(...dispatchArguments);
} else {
ok<typeof dispatchEvent>(entrypoint);
return entrypoint(dispatching);
}
}
}

Expand Down
52 changes: 29 additions & 23 deletions src/fetch/dispatch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
fromRequestResponse,
setDurableRequestForEvent
} from "../data";
import {dispatcher} from "../events/schedule/schedule";
import {dispatcher, getDispatcherFunction} from "../events/schedule/schedule";
import {v4} from "uuid";
import {caches} from "./cache";
import {dispatchEvent} from "../events/schedule/event";
Expand Down Expand Up @@ -236,35 +236,41 @@ export const removeFetchDispatcherFunction = dispatcher("fetch", async (event, d
const entrypointArguments = event.entrypointArguments;

async function dispatchServiceWorkerFnRequest(fn: unknown, fnError = "Expected entrypoint to be a function") {
ok(typeof fn === "function", fnError);

let returned;
if (entrypointArguments) {
const requestArguments = entrypointArguments.map(
key => key === "$event" ? requestEvent : requestEvent[key]
);
returned = fn(...requestArguments);
} else {
ok<ServiceWorkerFetchFn>(fn, fnError);
returned = fn(request, requestEvent);
}
if (isLike<Promise<unknown>>(returned) && typeof returned === "object" && "then" in returned) {
waitUntil(returned);
returned = await returned;
}
if (returned instanceof Response) {
respondWith(returned);
const dispatcher = getDispatcherFunction({
event: requestEvent
});
dispatcher.handler(requestEvent, dispatch);

async function dispatch(requestEvent: DurableEventData) {
ok(typeof fn === "function", fnError);
let returned;
if (entrypointArguments) {
const requestArguments = entrypointArguments.map(
key => key === "$event" ? requestEvent : requestEvent[key]
);
returned = fn(...requestArguments);
} else {
ok<ServiceWorkerFetchFn>(fn, fnError);
returned = fn(request, requestEvent);
}
if (isLike<Promise<unknown>>(returned) && typeof returned === "object" && "then" in returned) {
waitUntil(returned);
returned = await returned;
}
if (returned instanceof Response) {
respondWith(returned);
}
}
}

const serviceWorker = getServiceWorkerModuleExports();
if (event.entrypoint) {
const entrypoint = serviceWorker[event.entrypoint];
if (!entrypoint) {
const names = Object.keys(serviceWorker);
throw new Error(`Unknown entrypoint ${event.entrypoint}, expected one of ${names.join(", ")}`);
if (entrypoint) {
await dispatchServiceWorkerFnRequest(entrypoint);
} else {
await dispatch(requestEvent);
}
await dispatchServiceWorkerFnRequest(entrypoint);
} else if (typeof serviceWorker.fetch === "function") {
await dispatchServiceWorkerFnRequest(serviceWorker.fetch);
} else if (typeof serviceWorker.default === "function") {
Expand Down
4 changes: 3 additions & 1 deletion src/tests/worker/service-worker/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,11 @@ const worker = join(dirname(pathname), "./worker.js");
{
const registration = await serviceWorker.register(worker);

ok(registration.active, "Expected registration to be active");

const routes = await listRoutes(registration.durable.serviceWorkerId);

ok(routes.length);
ok(routes.length, "Expected routes to be initiated");

const fetch = await createRouter([
registration
Expand Down
3 changes: 2 additions & 1 deletion src/tests/worker/service-worker/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ declare var self: DurableServiceWorkerScope;
console.log("in test service worker");

self.addEventListener("install", event => {
console.log("Ran install", event);
event.addRoutes([
{
condition: {
Expand Down Expand Up @@ -36,7 +37,7 @@ self.addEventListener("activate", event => {
})

self.addEventListener("fetch", event => {
console.log("In fetch handler!", event.tag || "untagged");
console.log("In fetch handler!", event.tag || "untagged", event.respondWith);
event.respondWith(onFetchEvent(event));
});

Expand Down
28 changes: 17 additions & 11 deletions src/worker/service-worker/configure/import.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,17 +169,7 @@ export async function importConfiguration(source: string | URL | Config, { virtu
// This saves us from creating these values multiple times...
// ... is okay to use parse/stringify... isn't the best but that is okay
if (!noStringifyConfig) {
config = JSON.parse(
JSON.stringify(
config,
(key, value) => {
if (key === "url" && typeof value === "function") {
return getMaybeFunctionURL(value);
}
return value;
}
)
);
replaceFunctions(config);
}

const getService = await initialiseServices(config);
Expand Down Expand Up @@ -342,4 +332,20 @@ async function initialiseSocket(config: Config, socket: Socket, getService: Serv
hostname,
},
}, variableDispatch);
}

function replaceFunctions(value: unknown): void {
if (!value) return;
if (Array.isArray(value)) {
return value.forEach(replaceFunctions);
}
if (typeof value !== "object") return;
for (const [key, nextValue] of Object.entries(value)) {
if (key === "url" && typeof nextValue === "function") {
Object.assign(value, { [key]: getMaybeFunctionURL(nextValue) })
} else {
replaceFunctions(nextValue);
}
}

}
1 change: 1 addition & 0 deletions src/worker/service-worker/dispatchers/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
import "../../../dispatch";
export * from "./activate";
export * from "./install";
4 changes: 2 additions & 2 deletions src/worker/service-worker/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,12 @@ export async function onServiceWorkerWorkerData(data: ServiceWorkerWorkerData, i
Object.assign(globalThis, scope);

await import("./dispatchers");
await importWorkerExtensions(data.config, data.config.extensions, scope);
await importWorkerExtensions(data.config, data.config?.extensions, scope);
const url = new URL(registration.durable.url, registration.durable.baseURL);
url.searchParams.set("importCacheBust", Date.now().toString());
imported = await import(url.toString());

if (Array.isArray(data.service?.url)) {
if (data.config && Array.isArray(data.service?.url)) {
const rest = data.service.url.slice(1);
await importWorkerExtensions(data.config, rest, scope);
}
Expand Down

0 comments on commit 70d1785

Please sign in to comment.