chore: import upstream snapshot with attribution
Deploy (to testing) and Test Playground Preview Worker / Deploy Playground Preview Worker (testing) (push) Has been skipped
Deploy Workers Shared Staging / Deploy Workers Shared Staging (push) Failing after 0s
Prerelease / build (push) Has been skipped
Handle Changesets / Handle Changesets (push) Has been cancelled
Semgrep OSS scan / semgrep-oss (push) Has been cancelled
Deploy (to testing) and Test Playground Preview Worker / Deploy Playground Preview Worker (testing) (push) Has been skipped
Deploy Workers Shared Staging / Deploy Workers Shared Staging (push) Failing after 0s
Prerelease / build (push) Has been skipped
Handle Changesets / Handle Changesets (push) Has been cancelled
Semgrep OSS scan / semgrep-oss (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"module": "ESNext",
|
||||
"lib": ["ES2020"],
|
||||
"types": ["@cloudflare/workers-types"],
|
||||
"moduleResolution": "node",
|
||||
"noEmit": true,
|
||||
"skipLibCheck": true
|
||||
},
|
||||
"include": ["**/*.ts"],
|
||||
"exclude": ["tests"]
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
FROM node:22-alpine
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
RUN echo '{"name": "simple-node-app", "version": "1.0.0"}' > package.json
|
||||
RUN npm install
|
||||
|
||||
RUN echo 'const { createServer } = require("http");\
|
||||
\
|
||||
const server = createServer(function (req, res) {\
|
||||
res.writeHead(200, { "Content-Type": "text/plain" });\
|
||||
res.write("Hello from Container A");\
|
||||
res.end();\
|
||||
});\
|
||||
\
|
||||
server.listen(8080);\
|
||||
' > app.js
|
||||
|
||||
EXPOSE 8080
|
||||
@@ -0,0 +1,38 @@
|
||||
import { DurableObject } from "cloudflare:workers";
|
||||
|
||||
export class FixtureTestContainerA extends DurableObject<Env> {
|
||||
container: globalThis.Container;
|
||||
|
||||
constructor(ctx: DurableObjectState, env: Env) {
|
||||
super(ctx, env);
|
||||
this.container = ctx.container;
|
||||
}
|
||||
|
||||
async fetch(req: Request) {
|
||||
if (!this.container.running) {
|
||||
this.container.start({
|
||||
entrypoint: ["node", "app.js"],
|
||||
enableInternet: false,
|
||||
});
|
||||
// On the first request we simply start the container and return,
|
||||
// on the following requests the container can actually be accessed.
|
||||
// Note that we do this this way because container.start is not awaitable
|
||||
// meaning that we can't simply wait here for the container to be ready
|
||||
return new Response("Container started");
|
||||
}
|
||||
return this.container
|
||||
.getTcpPort(8080)
|
||||
.fetch("http://foo/bar/baz", { method: "POST", body: "hello" });
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
async fetch(request, env): Promise<Response> {
|
||||
const id = env.CONTAINER_A.idFromName("container");
|
||||
const stub = env.CONTAINER_A.get(id);
|
||||
return Response.json({
|
||||
containerAText: await (await stub.fetch(request)).text(),
|
||||
containerBText: await (await env.WORKER_B.fetch(request)).text(),
|
||||
});
|
||||
},
|
||||
} satisfies ExportedHandler<Env>;
|
||||
Vendored
+14
@@ -0,0 +1,14 @@
|
||||
/* eslint-disable */
|
||||
// Generated by Wrangler by running `wrangler types ./multi-workers-containers-app/workerA/worker-configuration.d.ts -c ./multi-workers-containers-app/workerA/wrangler.jsonc --no-include-runtime` (hash: e414ffcd6be2e270f12de677a3fccaaf)
|
||||
interface __BaseEnv_Env {
|
||||
CONTAINER_A: DurableObjectNamespace<import("./index").FixtureTestContainerA>;
|
||||
WORKER_B: Fetcher /* worker-b */;
|
||||
}
|
||||
declare namespace Cloudflare {
|
||||
interface GlobalProps {
|
||||
mainModule: typeof import("./index");
|
||||
durableNamespaces: "FixtureTestContainerA";
|
||||
}
|
||||
interface Env extends __BaseEnv_Env {}
|
||||
}
|
||||
interface Env extends __BaseEnv_Env {}
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"name": "worker-a",
|
||||
"main": "index.ts",
|
||||
"compatibility_date": "2025-04-03",
|
||||
"services": [{ "binding": "WORKER_B", "service": "worker-b" }],
|
||||
"containers": [
|
||||
{
|
||||
"image": "./Dockerfile",
|
||||
"class_name": "FixtureTestContainerA",
|
||||
"name": "container",
|
||||
"max_instances": 2,
|
||||
},
|
||||
],
|
||||
"durable_objects": {
|
||||
"bindings": [
|
||||
{
|
||||
"class_name": "FixtureTestContainerA",
|
||||
"name": "CONTAINER_A",
|
||||
},
|
||||
],
|
||||
},
|
||||
"migrations": [
|
||||
{
|
||||
"tag": "v1",
|
||||
"new_sqlite_classes": ["FixtureTestContainerA"],
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
FROM node:22-alpine
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
RUN echo '{"name": "simple-node-app", "version": "1.0.0"}' > package.json
|
||||
RUN npm install
|
||||
|
||||
RUN echo 'const { createServer } = require("http");\
|
||||
\
|
||||
const server = createServer(function (req, res) {\
|
||||
res.writeHead(200, { "Content-Type": "text/plain" });\
|
||||
res.write("Hello from Container B");\
|
||||
res.end();\
|
||||
});\
|
||||
\
|
||||
server.listen(8080);\
|
||||
' > app.js
|
||||
|
||||
EXPOSE 8080
|
||||
@@ -0,0 +1,35 @@
|
||||
import { DurableObject } from "cloudflare:workers";
|
||||
|
||||
export class FixtureTestContainerB extends DurableObject<Env> {
|
||||
container: globalThis.Container;
|
||||
|
||||
constructor(ctx: DurableObjectState, env: Env) {
|
||||
super(ctx, env);
|
||||
this.container = ctx.container;
|
||||
}
|
||||
|
||||
async fetch(req: Request) {
|
||||
if (!this.container.running) {
|
||||
this.container.start({
|
||||
entrypoint: ["node", "app.js"],
|
||||
enableInternet: false,
|
||||
});
|
||||
// On the first request we simply start the container and return,
|
||||
// on the following requests the container can actually be accessed.
|
||||
// Note that we do this this way because container.start is not awaitable
|
||||
// meaning that we can't simply wait here for the container to be ready
|
||||
return new Response("Container started");
|
||||
}
|
||||
return this.container
|
||||
.getTcpPort(8080)
|
||||
.fetch("http://foo/bar/baz", { method: "POST", body: "hello" });
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
async fetch(request, env): Promise<Response> {
|
||||
const id = env.CONTAINER_B.idFromName("container");
|
||||
const stub = env.CONTAINER_B.get(id);
|
||||
return stub.fetch(request);
|
||||
},
|
||||
} satisfies ExportedHandler<Env>;
|
||||
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
/* eslint-disable */
|
||||
// Generated by Wrangler by running `wrangler types ./multi-workers-containers-app/workerB/worker-configuration.d.ts -c ./multi-workers-containers-app/workerB/wrangler.jsonc --no-include-runtime` (hash: ffbf775a9ee9c3d83577a68a6b563542)
|
||||
interface __BaseEnv_Env {
|
||||
CONTAINER_B: DurableObjectNamespace<import("./index").FixtureTestContainerB>;
|
||||
}
|
||||
declare namespace Cloudflare {
|
||||
interface GlobalProps {
|
||||
mainModule: typeof import("./index");
|
||||
durableNamespaces: "FixtureTestContainerB";
|
||||
}
|
||||
interface Env extends __BaseEnv_Env {}
|
||||
}
|
||||
interface Env extends __BaseEnv_Env {}
|
||||
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"name": "worker-b",
|
||||
"main": "index.ts",
|
||||
"compatibility_date": "2025-04-03",
|
||||
"containers": [
|
||||
{
|
||||
"image": "./Dockerfile",
|
||||
"class_name": "FixtureTestContainerB",
|
||||
"name": "container",
|
||||
"max_instances": 2,
|
||||
},
|
||||
],
|
||||
"durable_objects": {
|
||||
"bindings": [
|
||||
{
|
||||
"class_name": "FixtureTestContainerB",
|
||||
"name": "CONTAINER_B",
|
||||
},
|
||||
],
|
||||
},
|
||||
"migrations": [
|
||||
{
|
||||
"tag": "v1",
|
||||
"new_classes": ["FixtureTestContainerB"],
|
||||
},
|
||||
],
|
||||
}
|
||||
Reference in New Issue
Block a user