Skip to content

Commit 956244f

Browse files
committed
Wire up DO-attached container API.
No methods are implemented yet, but if a container capability is passed in when creating an actor, then `ctx.container` will be populated.
1 parent 2d5cada commit 956244f

File tree

8 files changed

+75
-8
lines changed

8 files changed

+75
-8
lines changed

src/workerd/api/actor-state.c++

+6-3
Original file line numberDiff line numberDiff line change
@@ -825,10 +825,13 @@ kj::OneOf<jsg::Ref<DurableObjectId>, kj::StringPtr> ActorState::getId() {
825825
KJ_UNREACHABLE;
826826
}
827827

828-
DurableObjectState::DurableObjectState(
829-
Worker::Actor::Id actorId, kj::Maybe<jsg::Ref<DurableObjectStorage>> storage)
828+
DurableObjectState::DurableObjectState(Worker::Actor::Id actorId,
829+
kj::Maybe<jsg::Ref<DurableObjectStorage>> storage,
830+
kj::Maybe<rpc::Container::Client> container)
830831
: id(kj::mv(actorId)),
831-
storage(kj::mv(storage)) {}
832+
storage(kj::mv(storage)),
833+
container(container.map(
834+
[&](rpc::Container::Client& cap) { return jsg::alloc<Container>(kj::mv(cap)); })) {}
832835

833836
void DurableObjectState::waitUntil(kj::Promise<void> promise) {
834837
IoContext::current().addWaitUntil(kj::mv(promise));

src/workerd/api/actor-state.h

+10-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// See actor.h for APIs used by other Workers to talk to Actors.
99

1010
#include <workerd/api/actor.h>
11+
#include <workerd/api/container.h>
1112
#include <workerd/io/actor-cache.h>
1213
#include <workerd/io/actor-id.h>
1314
#include <workerd/io/compatibility-date.capnp.h>
@@ -462,7 +463,9 @@ class WebSocketRequestResponsePair: public jsg::Object {
462463
// The type passed as the first parameter to durable object class's constructor.
463464
class DurableObjectState: public jsg::Object {
464465
public:
465-
DurableObjectState(Worker::Actor::Id actorId, kj::Maybe<jsg::Ref<DurableObjectStorage>> storage);
466+
DurableObjectState(Worker::Actor::Id actorId,
467+
kj::Maybe<jsg::Ref<DurableObjectStorage>> storage,
468+
kj::Maybe<rpc::Container::Client> container);
466469

467470
void waitUntil(kj::Promise<void> promise);
468471

@@ -472,6 +475,10 @@ class DurableObjectState: public jsg::Object {
472475
return storage.map([&](jsg::Ref<DurableObjectStorage>& p) { return p.addRef(); });
473476
}
474477

478+
jsg::Optional<jsg::Ref<Container>> getContainer() {
479+
return container.map([](jsg::Ref<Container>& c) { return c.addRef(); });
480+
}
481+
475482
jsg::Promise<jsg::JsRef<jsg::JsValue>> blockConcurrencyWhile(
476483
jsg::Lock& js, jsg::Function<jsg::Promise<jsg::JsRef<jsg::JsValue>>()> callback);
477484

@@ -536,6 +543,7 @@ class DurableObjectState: public jsg::Object {
536543
JSG_METHOD(waitUntil);
537544
JSG_READONLY_INSTANCE_PROPERTY(id, getId);
538545
JSG_READONLY_INSTANCE_PROPERTY(storage, getStorage);
546+
JSG_READONLY_INSTANCE_PROPERTY(container, getContainer);
539547
JSG_METHOD(blockConcurrencyWhile);
540548
JSG_METHOD(acceptWebSocket);
541549
JSG_METHOD(getWebSockets);
@@ -574,6 +582,7 @@ class DurableObjectState: public jsg::Object {
574582
private:
575583
Worker::Actor::Id id;
576584
kj::Maybe<jsg::Ref<DurableObjectStorage>> storage;
585+
kj::Maybe<jsg::Ref<Container>> container;
577586

578587
// Limits for Hibernatable WebSocket tags.
579588

src/workerd/api/container.c++

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright (c) 2025 Cloudflare, Inc.
2+
// Licensed under the Apache 2.0 license found in the LICENSE file or at:
3+
// https://opensource.org/licenses/Apache-2.0
4+
5+
#include "container.h"
6+
7+
#include <workerd/io/io-context.h>
8+
9+
namespace workerd::api {
10+
11+
Container::Container(rpc::Container::Client rpcClient)
12+
: rpcClient(IoContext::current().addObject(kj::heap(kj::mv(rpcClient)))) {}
13+
14+
} // namespace workerd::api

src/workerd/api/container.h

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright (c) 2025 Cloudflare, Inc.
2+
// Licensed under the Apache 2.0 license found in the LICENSE file or at:
3+
// https://opensource.org/licenses/Apache-2.0
4+
5+
#pragma once
6+
// APIs that an Actor (Durable Object) uses to access its own state.
7+
//
8+
// See actor.h for APIs used by other Workers to talk to Actors.
9+
10+
#include <workerd/io/container.capnp.h>
11+
#include <workerd/io/io-own.h>
12+
#include <workerd/jsg/jsg.h>
13+
14+
namespace workerd::api {
15+
16+
class Container: public jsg::Object {
17+
public:
18+
Container(rpc::Container::Client rpcClient);
19+
20+
JSG_RESOURCE_TYPE(Container) {
21+
// TODO(now): Implement the API.
22+
}
23+
24+
private:
25+
IoOwn<rpc::Container::Client> rpcClient;
26+
};
27+
28+
#define EW_CONTAINER_ISOLATE_TYPES api::Container
29+
30+
} // namespace workerd::api

src/workerd/io/BUILD.bazel

+1
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ wd_cc_library(
9898
":actor-id",
9999
":actor-storage_capnp",
100100
":cdp_capnp",
101+
":container_capnp",
101102
":frankenvalue",
102103
":io-gate",
103104
":io-helpers",

src/workerd/io/worker.c++

+9-3
Original file line numberDiff line numberDiff line change
@@ -3184,6 +3184,8 @@ struct Worker::Actor::Impl {
31843184
kj::Maybe<jsg::JsRef<jsg::JsValue>> transient;
31853185
kj::Maybe<kj::Own<ActorCacheInterface>> actorCache;
31863186

3187+
kj::Maybe<rpc::Container::Client> container;
3188+
31873189
struct NoClass {};
31883190
struct Initializing {};
31893191

@@ -3344,10 +3346,12 @@ struct Worker::Actor::Impl {
33443346
kj::Own<ActorObserver> metricsParam,
33453347
kj::Maybe<kj::Own<HibernationManager>> manager,
33463348
kj::Maybe<uint16_t>& hibernationEventType,
3349+
kj::Maybe<rpc::Container::Client> container,
33473350
kj::PromiseFulfillerPair<void> paf = kj::newPromiseAndFulfiller<void>())
33483351
: actorId(kj::mv(actorId)),
33493352
makeStorage(kj::mv(makeStorage)),
33503353
metrics(kj::mv(metricsParam)),
3354+
container(kj::mv(container)),
33513355
hooks(loopback->addRef(), timerChannel, *metrics),
33523356
inputGate(hooks),
33533357
outputGate(hooks),
@@ -3404,12 +3408,13 @@ Worker::Actor::Actor(const Worker& worker,
34043408
TimerChannel& timerChannel,
34053409
kj::Own<ActorObserver> metrics,
34063410
kj::Maybe<kj::Own<HibernationManager>> manager,
3407-
kj::Maybe<uint16_t> hibernationEventType)
3411+
kj::Maybe<uint16_t> hibernationEventType,
3412+
kj::Maybe<rpc::Container::Client> container)
34083413
: worker(kj::atomicAddRef(worker)),
34093414
tracker(tracker.map([](RequestTracker& tracker) { return tracker.addRef(); })) {
34103415
impl = kj::heap<Impl>(*this, lock, kj::mv(actorId), hasTransient, kj::mv(makeActorCache),
34113416
kj::mv(makeStorage), kj::mv(loopback), timerChannel, kj::mv(metrics), kj::mv(manager),
3412-
hibernationEventType);
3417+
hibernationEventType, kj::mv(container));
34133418

34143419
KJ_IF_SOME(c, className) {
34153420
KJ_IF_SOME(cls, lock.getWorker().impl->actorClasses.find(c)) {
@@ -3432,7 +3437,8 @@ void Worker::Actor::ensureConstructed(IoContext& context) {
34323437
KJ_IF_SOME(c, impl->actorCache) {
34333438
storage = impl->makeStorage(lock, worker->getIsolate().getApi(), *c);
34343439
}
3435-
auto handler = info.cls(lock, jsg::alloc<api::DurableObjectState>(cloneId(), kj::mv(storage)),
3440+
auto handler = info.cls(lock,
3441+
jsg::alloc<api::DurableObjectState>(cloneId(), kj::mv(storage), kj::mv(impl->container)),
34363442
KJ_ASSERT_NONNULL(lock.getWorker().impl->env).addRef(js));
34373443

34383444
// HACK: We set handler.env to undefined because we already passed the real env into the

src/workerd/io/worker.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <workerd/io/actor-cache.h> // because we can't forward-declare ActorCache::SharedLru.
99
#include <workerd/io/actor-id.h>
1010
#include <workerd/io/compatibility-date.capnp.h>
11+
#include <workerd/io/container.capnp.h>
1112
#include <workerd/io/frankenvalue.h>
1213
#include <workerd/io/io-channels.h>
1314
#include <workerd/io/limit-enforcer.h>
@@ -762,7 +763,8 @@ class Worker::Actor final: public kj::Refcounted {
762763
TimerChannel& timerChannel,
763764
kj::Own<ActorObserver> metrics,
764765
kj::Maybe<kj::Own<HibernationManager>> manager,
765-
kj::Maybe<uint16_t> hibernationEventType);
766+
kj::Maybe<uint16_t> hibernationEventType,
767+
kj::Maybe<rpc::Container::Client> container = kj::none);
766768

767769
~Actor() noexcept(false);
768770

src/workerd/server/workerd-api.c++

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <workerd/api/actor.h>
1111
#include <workerd/api/analytics-engine.h>
1212
#include <workerd/api/cache.h>
13+
#include <workerd/api/container.h>
1314
#include <workerd/api/crypto/impl.h>
1415
#include <workerd/api/encoding.h>
1516
#include <workerd/api/events.h>
@@ -84,6 +85,7 @@ JSG_DECLARE_ISOLATE_TYPE(JsgWorkerdIsolate,
8485
EW_BASICS_ISOLATE_TYPES,
8586
EW_BLOB_ISOLATE_TYPES,
8687
EW_CACHE_ISOLATE_TYPES,
88+
EW_CONTAINER_ISOLATE_TYPES,
8789
EW_CRYPTO_ISOLATE_TYPES,
8890
EW_ENCODING_ISOLATE_TYPES,
8991
EW_EVENTS_ISOLATE_TYPES,

0 commit comments

Comments
 (0)