Skip to content
Commit Detail

Commit b516bb1

Author
Kenton Varda <kenton@cloudflare.com> 2025-04-29 18:32:19 -0500
Parents
71f503c
Tree
6adfb68
Facets: Implement facets JavaScript API.

From the design doc:

```js
// The main interface to manage facets is on `ctx`.
let facets = this.ctx.facets;

// Each facet has a name, which identifies its respective slice of storage. Names are hierarchical:
// if the main facet creates a facet called "foo", and that facet in turn creates a facet called
// "bar", the latter facet's true name is "foo/bar". A facet cannot directly access its siblings,
// unless the common parent facet chooses to pass references explicitly.
//
// Names are limited to 128 characters and cannot contain control characters nor `/`.
let name = "foo";

// To use a facet, pass the name to `this.ctx.facets.get()`.
//
// The second parameter specifies information needed to start up the facet. If the facet is already
// running, and matches the given parameters, the already-running instance is returned. If the
// parameters have changed, then the existing instance will shut down and will reload using the
// new parameters.
//
// Like with regular Durable Objects, there is no explicit "create" operation for a facet. It is
// implicitly created when first used, and is implicitly deleted if it shuts down with nothing left
// in storage.
let facet = this.ctx.facets.get(name, {
  // The class to use. This is a facet binding, which points to a class that may be defined
  // in a different Worker. As usual, ctx.exports can be used to refer to other classes
  // exported by the current worker. Dynamic Dispatch can also look up facets using
  // `getFacetClass`.
  class: this.env.FOO_FACET_CLASS,

  // The value that the facet sees in `ctx.id`. This can be a real Durable Object ID or a plain
  // string. In this example, the parent uses the facet name as the ID, but this may or may not
  // make sense depending on the use case. If not specified, defaults to inheriting the parent's
  // ID.
  id: name
});

// `facet` acts like a DO stub, except all calls are local.
await facet.someRpcMethod();

// `facets.abort()` forcefully aborts the facet immediately. No further code will execute in the
// facet until it is started again. The next call to `facets.get()` is guaranteed to call the
// callback and start a new instance. `reason` is thrown by any outstanding or future RPC calls
// on existing stubs pointing into the facet.
//
// This also transitively aborts all children of the facet.
this.ctx.facets.abort(name, reason);

// Deleting a facet aborts the facet if it is running and then deletes its underlying storage. This
// applies transitively to all children as well.
this.ctx.facets.delete(name);

// Note that `storage.deleteAll()` deletes all facets in addition to regular storage.
this.ctx.storage.deleteAll();
```

Files changed