Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/future/worker-bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import { parentPort, workerData } from "node:worker_threads";
import { Ok, Err, safeTry } from "slang-ts";
import { parseBoxSize } from "./memory-pool";
import type { Result } from "slang-ts";
import type {
ActorSelf, ActorContext, ActorCallback, ActorRef, FormatUtils,
Expand Down Expand Up @@ -154,7 +155,7 @@ function createActorContext(): ActorContext {
const { msg, type, data, share = "owner" } = params;
pendingWrite = {
resolve: (lock) => {
const boxSize = Number(config.memory.boxSize);
const boxSize = parseBoxSize(config.memory.boxSize);
const offset = lock.boxIndex * boxSize;
const view = new Uint8Array(sab, offset, Math.min(data.length, boxSize));
view.set(data.subarray(0, boxSize));
Expand All @@ -169,7 +170,7 @@ function createActorContext(): ActorContext {
/** Sync read from SAB. Returns null for Tier 1 (no handle). */
read: (msg: Message) => {
if (!msg.handle) return null;
const boxSize = Number(config.memory.boxSize);
const boxSize = parseBoxSize(config.memory.boxSize);
const offset = msg.handle.boxIndex * boxSize;
const view = new Uint8Array(sab, offset, boxSize);
/** Strip trailing null bytes for text/JSON decoding (SAB is zero-initialized) */
Expand Down
57 changes: 57 additions & 0 deletions tests/future/supervisor.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,63 @@ describe("tier 2 shared memory", () => {

expect(stripNulls(data)).toBe("hello world");
});

it("supports string boxSize in worker write/read operations", async () => {
const sup = createSupervisor({
maxActors: 5,
memory: { poolSize: 2, boxSize: "1KB" },
timeouts: { defaultLeaseMs: 2000 },
});

const actor = sup.spawn(async (self, _msg, ctx) => {
const result = await ctx.write({
msg: "string-box-size",
type: "json",
data: ctx.fmt.json.encode({ ok: true, value: 42 }),
share: "owner",
});

if (result.isOk) {
self.send("string-box-size", { handle: result.value });
} else {
self.send("write-error", { error: result.error });
}
});

const data = await new Promise<unknown>((resolve, reject) => {
const timeout = setTimeout(() => {
reject(new Error("Timeout waiting for string boxSize write"));
}, 3000);

actor.subscribe((msg) => {
const m = msg as Message;

if (m.msg === "write-error" && m.data) {
clearTimeout(timeout);
reject(new Error((m.data as { error: string }).error));
}

if (m.msg === "string-box-size" && m.data) {
clearTimeout(timeout);
const handle = (m.data as { handle: Lock }).handle;
const reader = actor.read({ ...m, handle });

if (!reader) {
reject(new Error("Expected reader for string boxSize message"));
return;
}

resolve(reader.json());
}
});

actor.receive("write");
});

expect(data).toEqual({ ok: true, value: 42 });

await sup.shutdown();
});
});

// ============================================================================
Expand Down