Skip to content

Commit 6dcfdce

Browse files
committed
custom limits for dynamic workers
1 parent 3fc316d commit 6dcfdce

3 files changed

Lines changed: 30 additions & 8 deletions

File tree

src/workerd/api/worker-loader.c++

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,12 @@ jsg::Ref<Fetcher> WorkerStub::getEntrypoint(jsg::Lock& js,
1414
jsg::Optional<kj::Maybe<kj::String>> name,
1515
jsg::Optional<EntrypointOptions> options) {
1616
Frankenvalue props;
17-
17+
kj::Maybe<ResourceLimits> limits;
1818
KJ_IF_SOME(o, options) {
1919
KJ_IF_SOME(p, o.props) {
2020
props = Frankenvalue::fromJs(js, p.getHandle(js));
2121
}
22+
limits = o.limits;
2223
}
2324

2425
kj::Maybe<kj::String> entrypointName;
@@ -30,19 +31,20 @@ jsg::Ref<Fetcher> WorkerStub::getEntrypoint(jsg::Lock& js,
3031
}
3132
}
3233

33-
auto subreqChannel = channel->getEntrypoint(kj::mv(entrypointName), kj::mv(props));
34+
auto subreqChannel = channel->getEntrypoint(kj::mv(entrypointName), kj::mv(props), limits);
3435
return js.alloc<Fetcher>(IoContext::current().addObject(kj::mv(subreqChannel)));
3536
}
3637

3738
jsg::Ref<DurableObjectClass> WorkerStub::getDurableObjectClass(jsg::Lock& js,
3839
jsg::Optional<kj::Maybe<kj::String>> name,
3940
jsg::Optional<EntrypointOptions> options) {
4041
Frankenvalue props;
41-
42+
kj::Maybe<ResourceLimits> limits;
4243
KJ_IF_SOME(o, options) {
4344
KJ_IF_SOME(p, o.props) {
4445
props = Frankenvalue::fromJs(js, p.getHandle(js));
4546
}
47+
limits = o.limits;
4648
}
4749

4850
kj::Maybe<kj::String> entrypointName;
@@ -55,7 +57,7 @@ jsg::Ref<DurableObjectClass> WorkerStub::getDurableObjectClass(jsg::Lock& js,
5557
}
5658

5759
return js.alloc<DurableObjectClass>(IoContext::current().addObject(
58-
channel->getActorClass(kj::mv(entrypointName), kj::mv(props))));
60+
channel->getActorClass(kj::mv(entrypointName), kj::mv(props), limits)));
5961
}
6062

6163
jsg::Ref<WorkerStub> WorkerLoader::get(
@@ -157,6 +159,7 @@ DynamicWorkerSource WorkerLoader::toDynamicWorkerSource(jsg::Lock& js,
157159

158160
return {.source = kj::mv(extractedSource),
159161
.compatibilityFlags = compatFlags,
162+
.limits = code.limits,
160163
.env = kj::mv(env),
161164
.globalOutbound = kj::mv(globalOutbound),
162165
.tails = kj::mv(tailChannels),

src/workerd/api/worker-loader.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@ class WorkerStub: public jsg::Object {
2121

2222
struct EntrypointOptions {
2323
jsg::Optional<jsg::JsRef<jsg::JsObject>> props;
24+
jsg::Optional<ResourceLimits> limits;
2425

25-
JSG_STRUCT(props);
26+
JSG_STRUCT(props, limits);
2627
};
2728

2829
jsg::Ref<Fetcher> getEntrypoint(jsg::Lock& js,
@@ -90,6 +91,8 @@ class WorkerLoader: public jsg::Object {
9091
jsg::Optional<kj::Array<kj::String>> compatibilityFlags;
9192
jsg::Optional<bool> allowExperimental = false;
9293

94+
jsg::Optional<ResourceLimits> limits;
95+
9396
kj::String mainModule;
9497

9598
// Modules are specified as an object mapping names to content. If the content is just a
@@ -116,6 +119,7 @@ class WorkerLoader: public jsg::Object {
116119
JSG_STRUCT(compatibilityDate,
117120
compatibilityFlags,
118121
allowExperimental,
122+
limits,
119123
mainModule,
120124
modules,
121125
env,
@@ -156,6 +160,6 @@ class WorkerLoader: public jsg::Object {
156160

157161
#define EW_WORKER_LOADER_ISOLATE_TYPES \
158162
api::WorkerStub, api::WorkerStub::EntrypointOptions, api::WorkerLoader, \
159-
api::WorkerLoader::Module, api::WorkerLoader::WorkerCode
163+
api::WorkerLoader::Module, api::WorkerLoader::WorkerCode, workerd::ResourceLimits
160164

161165
} // namespace workerd::api

src/workerd/io/io-channels.h

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -297,17 +297,30 @@ class IoChannelFactory {
297297
ChannelTokenUsage usage, kj::ArrayPtr<const byte> token);
298298
};
299299

300+
// ResourceLimits provides a means to control the resource allocation for a worker stage via a
301+
// set of optionally overridden parameters.
302+
struct ResourceLimits {
303+
jsg::Optional<uint32_t> cpuMs;
304+
jsg::Optional<uint32_t> subRequests;
305+
306+
JSG_STRUCT(cpuMs, subRequests);
307+
308+
ResourceLimits clone() const {
309+
return {cpuMs, subRequests};
310+
}
311+
};
312+
300313
// Represents a dynamically-loaded Worker to which requests can be sent.
301314
//
302315
// This object is returned before the Worker actually loads, so if any errors occur while loading,
303316
// any requests sent to the Worker will fail, propagating the exception.
304317
class WorkerStubChannel {
305318
public:
306319
virtual kj::Own<IoChannelFactory::SubrequestChannel> getEntrypoint(
307-
kj::Maybe<kj::String> name, Frankenvalue props) = 0;
320+
kj::Maybe<kj::String> name, Frankenvalue props, kj::Maybe<ResourceLimits> limits) = 0;
308321

309322
virtual kj::Own<IoChannelFactory::ActorClassChannel> getActorClass(
310-
kj::Maybe<kj::String> name, Frankenvalue props) = 0;
323+
kj::Maybe<kj::String> name, Frankenvalue props, kj::Maybe<ResourceLimits> limits) = 0;
311324

312325
// TODO(someday): Allow caller to enumerate entrypoints?
313326
};
@@ -317,6 +330,8 @@ struct DynamicWorkerSource {
317330
WorkerSource source;
318331
CompatibilityFlags::Reader compatibilityFlags;
319332

333+
kj::Maybe<ResourceLimits> limits;
334+
320335
// `env` object to pass to the loaded worker. Can contain anything that can be serialized to
321336
// a `Frankenvalue` (which should eventually include all binding types, RPC stubs, etc.).
322337
Frankenvalue env;

0 commit comments

Comments
 (0)