@sproutboat/runtime 0.17.0 → 0.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @sproutboat/runtime
2
2
 
3
+ ## 0.17.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 3dabc97: Scheduled, queue and Durable Object alarm triggers answer `204` with no body again. The prelude built that reply as `new Response("", { status: 204 })`, which the Fetch-spec `Response` of 0.17.0 rejects (an empty string is still a body), so the first cron or alarm failed, and on the alarm path the error took the server down.
8
+
3
9
  ## 0.17.0
4
10
 
5
11
  ### Minor Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sproutboat/runtime",
3
- "version": "0.17.0",
3
+ "version": "0.17.1",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "repository": {
@@ -5080,7 +5080,7 @@ async function __sb204WithDrain(res, tasks) {
5080
5080
  __sbLogUncaught("scheduled/alarm", error);
5081
5081
  }
5082
5082
  await __sbDrainWaitUntil(tasks);
5083
- return new Response("", { status: 204 });
5083
+ return new Response(null, { status: 204 });
5084
5084
  }
5085
5085
 
5086
5086
  async function __sbQueueWithDrain(result, tasks) {
@@ -5179,10 +5179,10 @@ globalThis.__sbEntry = function (handlers, request) {
5179
5179
  } catch (error) {
5180
5180
  // #179 — same rule as fetch: don't let a throw here crash the process.
5181
5181
  __sbLogUncaught("scheduled", error);
5182
- return new Response("", { status: 204 });
5182
+ return new Response(null, { status: 204 });
5183
5183
  }
5184
5184
  if (__sbTasks.length || (__sres && __sbIsFn(__sres.then))) return __sb204WithDrain(__sres, __sbTasks);
5185
- return new Response("", { status: 204 });
5185
+ return new Response(null, { status: 204 });
5186
5186
  }
5187
5187
 
5188
5188
  if (trigger === "queue") {
@@ -5214,12 +5214,12 @@ globalThis.__sbEntry = function (handlers, request) {
5214
5214
  } catch (error) {
5215
5215
  // #179 — same rule as fetch: don't let a throw here crash the process.
5216
5216
  __sbLogUncaught("alarm", error);
5217
- return new Response("", { status: 204 });
5217
+ return new Response(null, { status: 204 });
5218
5218
  }
5219
5219
  // Was fire-and-forget before: an async `alarm()` and any `state.waitUntil()`
5220
5220
  // it queued were both dropped the moment 204 went out. Await both.
5221
5221
  if (inst.__sbTasks.length || (__ares && __sbIsFn(__ares.then))) return __sb204WithDrain(__ares, inst.__sbTasks);
5222
- return new Response("", { status: 204 });
5222
+ return new Response(null, { status: 204 });
5223
5223
  }
5224
5224
 
5225
5225
  return new Response("unknown trigger", { status: 400 });
@@ -15,7 +15,11 @@ const handler = `export default {async fetch(request, env, ctx) {
15
15
  return new Response("scheduled");
16
16
  }
17
17
  if (path === "/state") return new Response(String(globalThis.__done));
18
+ if (path === "/cron") return new Response(String(globalThis.__cron));
18
19
  return new Response("ok");
20
+ },
21
+ async scheduled(event, env, ctx) {
22
+ ctx.waitUntil(new Promise((resolve) => setTimeout(() => { globalThis.__cron = event.cron; resolve(); }, 50)));
19
23
  }};`;
20
24
 
21
25
  function freePort(): number {
@@ -59,7 +63,7 @@ try {
59
63
  const port = freePort();
60
64
  server = Bun.spawn([binary], {
61
65
  cwd: workdir,
62
- env: { ...process.env, PORT: String(port) },
66
+ env: { ...process.env, PORT: String(port), SB_BROKER_TOKEN: "native-test-token" },
63
67
  stdout: "ignore",
64
68
  stderr: "inherit",
65
69
  });
@@ -82,7 +86,18 @@ try {
82
86
  assert.equal(await (await fetch(`http://127.0.0.1:${port}/state`)).text(), "pending");
83
87
  await Bun.sleep(700);
84
88
  assert.equal(await (await fetch(`http://127.0.0.1:${port}/state`)).text(), "done");
85
- console.log(`Native waitUntil runs after the response (${Math.round(elapsed)} ms) and completes`);
89
+ // A trigger answers 204 with no body. new Response("", { status: 204 }) throws under the
90
+ // Fetch-spec Response, and the prelude used it: the first cron or alarm took the server down.
91
+ const cron = await fetch(`http://127.0.0.1:${port}/`, {
92
+ method: "POST",
93
+ headers: { "x-sb-trigger": "scheduled", "x-sb-token": "native-test-token", "content-type": "application/json" },
94
+ body: JSON.stringify({ cron: "*/5 * * * *", scheduledTime: Date.now() }),
95
+ });
96
+ assert.equal(cron.status, 204);
97
+ assert.equal(await cron.text(), "");
98
+ assert.equal(await (await fetch(`http://127.0.0.1:${port}/cron`)).text(), "*/5 * * * *");
99
+ assert.equal(server.exitCode, null, "the server exited after a scheduled trigger");
100
+ console.log(`Native waitUntil runs after the response (${Math.round(elapsed)} ms) and completes; scheduled() answers 204`);
86
101
  } finally {
87
102
  if (server) {
88
103
  server.kill(9);