Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
16 changes: 15 additions & 1 deletion src/workerd/api/worker-loader-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,21 @@ export let isolateUniqueness = {
assert.strictEqual(await anonymousAgain.increment(), 2);
assert.strictEqual(await anonymousAgain.increment(), 3);

assert.strictEqual(loadCount, 5);
// Test that null/undefined name parameter creates unique isolates each time
// Each call should generate a unique name internally.
let noName1 = env.loader.get(null, loadCodeCallback).getEntrypoint();
let noName2 = env.loader.get(undefined, loadCodeCallback).getEntrypoint();
let noName3 = env.loader.get(undefined, loadCodeCallback).getEntrypoint();

// Each should be a different isolate
assert.strictEqual(await noName1.increment(), 0);
assert.strictEqual(await noName1.increment(), 1);
assert.strictEqual(await noName2.increment(), 0);
assert.strictEqual(await noName2.increment(), 1);
assert.strictEqual(await noName3.increment(), 0);
assert.strictEqual(await noName3.increment(), 1);

assert.strictEqual(loadCount, 8);
},
};

Expand Down
2 changes: 1 addition & 1 deletion src/workerd/api/worker-loader.c++
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ jsg::Ref<DurableObjectClass> WorkerStub::getDurableObjectClass(jsg::Lock& js,
}

jsg::Ref<WorkerStub> WorkerLoader::get(
jsg::Lock& js, kj::String name, jsg::Function<jsg::Promise<WorkerCode>()> getCode) {
jsg::Lock& js, kj::Maybe<kj::String> name, jsg::Function<jsg::Promise<WorkerCode>()> getCode) {
auto& ioctx = IoContext::current();

auto reenterAndGetCode = ioctx.makeReentryCallback(
Expand Down
2 changes: 1 addition & 1 deletion src/workerd/api/worker-loader.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ class WorkerLoader: public jsg::Object {
};

jsg::Ref<WorkerStub> get(
jsg::Lock& js, kj::String name, jsg::Function<jsg::Promise<WorkerCode>()> getCode);
jsg::Lock& js, kj::Maybe<kj::String> name, jsg::Function<jsg::Promise<WorkerCode>()> getCode);

JSG_RESOURCE_TYPE(WorkerLoader) {
JSG_METHOD(get);
Expand Down
6 changes: 2 additions & 4 deletions src/workerd/io/io-channels.h
Original file line number Diff line number Diff line change
Expand Up @@ -245,11 +245,9 @@ class IoChannelFactory {
KJ_UNIMPLEMENTED("Only implemented by single-tenant workerd runtime");
}

// Use a dynamic Worker loader binding to obtain an Worker by name. If the named Worker
// doesn't already exist, the callback will be called to fetch the source code from which the
// Worker should be created.
// Use a dynamic Worker loader binding to obtain an Worker by name. If name is null, or if the named Worker doesn't already exist, the callback will be called to fetch the source code from which the Worker should be created.
virtual kj::Own<WorkerStubChannel> loadIsolate(uint loaderChannel,
kj::String name,
kj::Maybe<kj::String> name,
kj::Function<kj::Promise<DynamicWorkerSource>()> fetchSource) {
JSG_FAIL_REQUIRE(Error, "Dynamic worker loading is not supported by this runtime.");
}
Expand Down
39 changes: 24 additions & 15 deletions src/workerd/server/server.c++
Original file line number Diff line number Diff line change
Expand Up @@ -3321,7 +3321,7 @@ class Server::WorkerService final: public Service,
}

kj::Own<WorkerStubChannel> loadIsolate(uint loaderChannel,
kj::String name,
kj::Maybe<kj::String> name,
kj::Function<kj::Promise<DynamicWorkerSource>()> fetchSource) override;

// ---------------------------------------------------------------------------
Expand Down Expand Up @@ -3865,19 +3865,24 @@ class Server::WorkerLoaderNamespace: public kj::Refcounted {
}

kj::Own<WorkerStubChannel> loadIsolate(
kj::String name, kj::Function<kj::Promise<DynamicWorkerSource>()> fetchSource) {
return isolates
.findOrCreate(name,
[&]() -> decltype(isolates)::Entry {
// This name isn't actually used in any maps nor is it ever revealed back to the app, but it
// may be used in error logs.
auto isolateName = kj::str(namespaceName, ':', name);

return {.key = kj::mv(name),
.value = kj::rc<WorkerStubImpl>(server, kj::mv(isolateName), kj::mv(fetchSource))};
})
.addRef()
.toOwn();
kj::Maybe<kj::String> name, kj::Function<kj::Promise<DynamicWorkerSource>()> fetchSource) {
KJ_IF_SOME(n, name) {
return isolates
.findOrCreate(n,
[&]() -> decltype(isolates)::Entry {
// This name isn't actually used in any maps nor is it ever revealed back to the app, but it
// may be used in error logs.
auto isolateName = kj::str(namespaceName, ':', n);

return {.key = kj::mv(n),
.value = kj::rc<WorkerStubImpl>(server, kj::mv(isolateName), kj::mv(fetchSource))};
})
.addRef()
.toOwn();
} else {
auto isolateName = kj::str(namespaceName, ":dynamic:", randomUUID(server.entropySource));
return kj::rc<WorkerStubImpl>(server, kj::mv(isolateName), kj::mv(fetchSource)).toOwn();
}
}

private:
Expand Down Expand Up @@ -3916,6 +3921,10 @@ class Server::WorkerLoaderNamespace: public kj::Refcounted {
kj::Function<kj::Promise<DynamicWorkerSource>()> fetchSource)
: startupTask(start(server, kj::mv(isolateName), kj::mv(fetchSource)).fork()) {}

~WorkerStubImpl() {
unlink();
}

void unlink() {
KJ_IF_SOME(s, service) {
s->unlink();
Expand Down Expand Up @@ -4147,7 +4156,7 @@ void Server::unlinkWorkerLoaders() {
}

kj::Own<WorkerStubChannel> Server::WorkerService::loadIsolate(uint loaderChannel,
kj::String name,
kj::Maybe<kj::String> name,
kj::Function<kj::Promise<DynamicWorkerSource>()> fetchSource) {
auto& channels =
KJ_REQUIRE_NONNULL(ioChannels.tryGet<LinkedIoChannels>(), "link() has not been called");
Expand Down
2 changes: 1 addition & 1 deletion types/generated-snapshot/experimental/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4112,7 +4112,7 @@ interface WorkerStubEntrypointOptions {
}
interface WorkerLoader {
get(
name: string,
name: string | null,
getCode: () => WorkerLoaderWorkerCode | Promise<WorkerLoaderWorkerCode>,
): WorkerStub;
}
Expand Down
2 changes: 1 addition & 1 deletion types/generated-snapshot/experimental/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4125,7 +4125,7 @@ export interface WorkerStubEntrypointOptions {
}
export interface WorkerLoader {
get(
name: string,
name: string | null,
getCode: () => WorkerLoaderWorkerCode | Promise<WorkerLoaderWorkerCode>,
): WorkerStub;
}
Expand Down
2 changes: 1 addition & 1 deletion types/generated-snapshot/latest/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3832,7 +3832,7 @@ interface WorkerStubEntrypointOptions {
}
interface WorkerLoader {
get(
name: string,
name: string | null,
getCode: () => WorkerLoaderWorkerCode | Promise<WorkerLoaderWorkerCode>,
): WorkerStub;
}
Expand Down
2 changes: 1 addition & 1 deletion types/generated-snapshot/latest/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3843,7 +3843,7 @@ export interface WorkerStubEntrypointOptions {
}
export interface WorkerLoader {
get(
name: string,
name: string | null,
getCode: () => WorkerLoaderWorkerCode | Promise<WorkerLoaderWorkerCode>,
): WorkerStub;
}
Expand Down
Loading