Skip to content

Commit ddd5bf8

Browse files
bartlomiejurymagurotunajosh-collinsworthpiscisaureus
committed
v0.6.2
Upgrading from v0.6.1 can use a rolling update. - An output gate of a running handler is now admitted during a deploy swap. Before this change, the handler could block the swap until the swap's maximum age cancelled it. - A one-follower node-log ensemble now recruits a second follower when a peer becomes available. Before this change, it stayed at one follower. - When a handler fails on the node that owns a Durable Object, a forwarded `stub.fetch()` now rejects as it does for a local owner, and celld does not run the handler again. Before this change, the caller got a 500 response. - LTX capture now recovers a WAL with a torn header when a database opens. Before this change, a later write could hide the torn header. - An abandoned eviction no longer leaves background compaction paused for that cell, because the pause now ends with the handoff attempt. - Epoch GC now runs on bucket-durability nodes as well as fleet nodes. A newly seen cell now waits behind overdue cells in the GC queue. - WebSocket events now reach the Durable Object facet that accepted the socket. An outbound WebSocket that a facet opens now routes through the facet's root. - A Worker response that carries a WebSocket for a request that did not upgrade now fails with a 500 and a `TypeError`, as in workerd. - A fetch to a dynamically loaded Worker now honors the caller's `AbortSignal`. - `self` is now defined as the global scope. A plain class that extends no runtime base can now be started as a Durable Object facet. - A `celld dev` project without a `.dev.vars` file now reads Worker variables from `.env` and then `.env.local`, as `wrangler dev` does. The dotenv parser now accepts `export NAME=value` lines and quoted values that span several lines. - The container image now includes `LICENSE` and a new `NOTICE` file under `/usr/share/doc/celld/`. Co-authored-by: Ryan Dahl <ry@tinyclouds.org> Co-authored-by: Yusuke "Taka" Tanaka <yusuktan@maguro.dev> Co-authored-by: Josh Collinsworth <joshuajcollinsworth@gmail.com> Co-authored-by: Bert Belder <bertbelder@gmail.com>
1 parent f2bf648 commit ddd5bf8

63 files changed

Lines changed: 4442 additions & 5225 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/workflows/release.yml‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,12 +126,14 @@ jobs:
126126
path: assets
127127
merge-multiple: true
128128

129-
# Assets are minimal: the binaries, nothing else. Integrity is the
130-
# attestation plus GitHub's own immutable per-asset digests; gzip's
131-
# CRC catches corruption in transit.
129+
# Assets are minimal: the binaries plus LICENSE and NOTICE, which
130+
# the third-party licenses require to travel with them. Integrity is
131+
# the attestation plus GitHub's own immutable per-asset digests;
132+
# gzip's CRC catches corruption in transit.
132133
- name: Check assets
133134
run: |
134135
set -euo pipefail
136+
cp LICENSE NOTICE assets/
135137
cd assets
136138
for target in \
137139
x86_64-unknown-linux-gnu \

‎Cargo.lock‎

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Dockerfile‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,5 +42,6 @@ ARG CELLD_VERSION=unknown
4242
LABEL org.opencontainers.image.title="celld" \
4343
org.opencontainers.image.revision="${CELLD_COMMIT}" \
4444
org.opencontainers.image.version="${CELLD_VERSION}"
45+
COPY LICENSE NOTICE /usr/share/doc/celld/
4546
COPY --from=test /out/celld /usr/local/bin/celld
4647
ENTRYPOINT ["/usr/local/bin/celld"]

‎LICENSE.tokio‎

Lines changed: 0 additions & 21 deletions
This file was deleted.

‎NOTICE‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
celld
2+
Copyright 2026 Deno Land Inc.
3+
4+
celld is licensed under the Apache License 2.0; see LICENSE. Code adapted
5+
from Tokio is under the MIT License; see the header of
6+
crates/celld/tokio_select.rs.
7+
8+
Third-party software
9+
--------------------
10+
11+
celld uses lol_html, Cloudflare's HTML rewriting library (BSD-3-Clause,
12+
https://github.com/cloudflare/lol-html), to implement the HTMLRewriter
13+
API. lol_html depends on the following crates from the Servo project,
14+
which are licensed under the Mozilla Public License 2.0
15+
(https://mozilla.org/MPL/2.0/). celld binaries include them unmodified;
16+
cssparser-macros runs only at build time. Their source code is available
17+
at:
18+
19+
cssparser https://crates.io/crates/cssparser
20+
cssparser-macros https://crates.io/crates/cssparser-macros
21+
dtoa-short https://crates.io/crates/dtoa-short
22+
selectors https://crates.io/crates/selectors
23+
24+
The exact versions are recorded in Cargo.lock.
25+
26+
All other dependencies are under permissive licenses (Apache-2.0, MIT,
27+
BSD-3-Clause, ISC, Unicode-3.0, Zlib, BSL-1.0, CC0-1.0,
28+
CDLA-Permissive-2.0); Cargo.lock lists them.

‎crates/celld/Cargo.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "celld"
3-
version = "0.6.1"
3+
version = "0.6.2"
44
edition = "2021"
55
rust-version = "1.94.1"
66
license = "Apache-2.0"

‎crates/celld/actor.rs‎

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,17 @@ impl Ownership {
390390
}
391391
}
392392

393+
/// The identity that lets a request finish on a quiescing resident, where an
394+
/// ordinary request waits for the successor route. One field holds it, so a
395+
/// request cannot claim two identities.
396+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
397+
pub enum ResidentWork {
398+
/// An event from this exact registered WebSocket.
399+
WebSocket(u64),
400+
/// The output gate for an effect that the cell's running work raised.
401+
OutputGate,
402+
}
403+
393404
pub enum Message {
394405
/// A periodic resource sample. The measuring is the shell's job; every
395406
/// decision that follows belongs to the core.
@@ -436,10 +447,9 @@ pub enum Message {
436447
/// settles this channel as soon as the ownership CAS is authoritative;
437448
/// the ordinary route reply remains pending until it is cancelled.
438449
handoff_accept: Option<HandoffAcceptWaiter>,
439-
/// An event from this exact registered WebSocket can finish on a
440-
/// quiescing resident. Ordinary requests carry no identity and wait
441-
/// for the successor route.
442-
websocket: Option<u64>,
450+
/// Work that can finish on a quiescing resident. Ordinary requests
451+
/// carry none and wait for the successor route.
452+
resident_work: Option<ResidentWork>,
443453
reply: oneshot::Sender<Result<Routed, RequestError>>,
444454
},
445455
/// A caller disappeared before routing finished. The request identity is
@@ -1281,6 +1291,13 @@ impl AppHandle {
12811291
self.request_with_mode(cell, false, None).await
12821292
}
12831293

1294+
/// Route the output gate for an effect raised inside one of `cell`'s
1295+
/// handlers. See `ResidentWork::OutputGate`.
1296+
pub async fn gate_request(&self, cell: String) -> Result<Routed, RequestError> {
1297+
self.request_with_mode(cell, false, Some(ResidentWork::OutputGate))
1298+
.await
1299+
}
1300+
12841301
/// Route one test request and retain which asynchronous seam produced the
12851302
/// result. The shipping method keeps its compact public result, while this
12861303
/// receipt prevents an inference from `NodeFenced` or an error string.
@@ -1313,16 +1330,21 @@ impl AppHandle {
13131330
cell: String,
13141331
websocket: u64,
13151332
) -> Result<Routed, RequestError> {
1316-
self.request_with_mode(cell, false, Some(websocket)).await
1333+
self.request_with_mode(cell, false, Some(ResidentWork::WebSocket(websocket)))
1334+
.await
13171335
}
13181336

13191337
async fn request_with_mode(
13201338
&self,
13211339
cell: String,
13221340
capacity_handoff: bool,
1323-
websocket: Option<u64>,
1341+
resident_work: Option<ResidentWork>,
13241342
) -> Result<Routed, RequestError> {
1325-
match self.request_path(cell, capacity_handoff, websocket).await.1 {
1343+
match self
1344+
.request_path(cell, capacity_handoff, resident_work)
1345+
.await
1346+
.1
1347+
{
13261348
RequestPathOutcome::Returned(result) => result,
13271349
RequestPathOutcome::SubmissionFailure | RequestPathOutcome::ReplyChannelClosed => {
13281350
Err(RequestError::NodeFenced)
@@ -1334,7 +1356,7 @@ impl AppHandle {
13341356
&self,
13351357
cell: String,
13361358
capacity_handoff: bool,
1337-
websocket: Option<u64>,
1359+
resident_work: Option<ResidentWork>,
13381360
) -> (u64, RequestPathOutcome) {
13391361
let request = crate::asyncrt::next_core_request();
13401362
let (reply, receive) = oneshot::channel();
@@ -1345,7 +1367,7 @@ impl AppHandle {
13451367
cell,
13461368
capacity_handoff,
13471369
handoff_accept: None,
1348-
websocket,
1370+
resident_work,
13491371
reply,
13501372
})
13511373
.is_err()
@@ -1383,7 +1405,7 @@ impl AppHandle {
13831405
released_epoch,
13841406
reply: accept_reply,
13851407
}),
1386-
websocket: None,
1408+
resident_work: None,
13871409
reply: route_reply,
13881410
})
13891411
.is_err()
@@ -2684,7 +2706,7 @@ impl Actor {
26842706
cell,
26852707
capacity_handoff,
26862708
handoff_accept,
2687-
websocket,
2709+
resident_work,
26882710
reply,
26892711
} => {
26902712
self.pending.insert(request, reply);
@@ -2695,14 +2717,20 @@ impl Actor {
26952717
self.begin_route_if_cold(&cell);
26962718
self.request_cells.insert(request, cell.clone());
26972719
self.drive(
2698-
if let Some(websocket) = websocket {
2720+
if let Some(ResidentWork::WebSocket(websocket)) = resident_work {
26992721
Event::WebSocketRequestAt {
27002722
request,
27012723
cell: cell.clone(),
27022724
websocket,
27032725
now_ms: now_ms(),
27042726
now_mono_ms: crate::asyncrt::mono_ms(),
27052727
}
2728+
} else if resident_work == Some(ResidentWork::OutputGate) {
2729+
Event::GateRequestAt {
2730+
request,
2731+
cell: cell.clone(),
2732+
now_mono_ms: crate::asyncrt::mono_ms(),
2733+
}
27062734
} else if ownership_handoff {
27072735
Event::HandoffRequestAt {
27082736
request,

‎crates/celld/cell_cli.rs‎

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ pub(crate) fn gc_options_from_arguments(
344344
if !dry_run {
345345
bail!(
346346
"celld cell gc deletes nothing itself; pass --dry-run to report what the owners \
347-
would delete, and give CELLD_LTX_RETENTION_SECS a positive value on the fleet to \
347+
would delete, and give CELLD_LTX_RETENTION_SECS a positive value on the nodes to \
348348
let them"
349349
);
350350
}
@@ -366,12 +366,13 @@ and prints the candidates: the epochs below the chain's base, except the
366366
newest epoch, the epoch before it, and each epoch whose newest object is
367367
younger than the grace. This command reads the bucket and writes nothing.
368368
369-
The owners delete fewer, later, or none: only a fleet node with a
370-
positive CELLD_LTX_RETENTION_SECS deletes, with that grace instead of
371-
--grace-secs; a paged cell waits until its local file is complete; an
372-
inactive cell waits until it is active again; a cell that is not paged
373-
waits until its activation has a write, so a cell that is only read
374-
deletes nothing; and one pass deletes at most 64 epochs of a cell.
369+
The owners delete fewer, later, or none: only a node with a positive
370+
CELLD_LTX_RETENTION_SECS deletes, in either CELLD_DURABILITY mode, with
371+
that grace instead of --grace-secs; a paged cell waits until its local
372+
file is complete; an inactive cell waits until it is active again; a cell
373+
that is not paged waits until its activation has a write, so a cell that
374+
is only read deletes nothing; and one pass deletes at most 64 epochs of a
375+
cell.
375376
376377
OPTIONS:
377378
--dry-run Required; report without deleting

0 commit comments

Comments
 (0)