import * as NodeHttpClient from "@effect/platform-node/NodeHttpClient";import * as NodeServices from "@effect/platform-node/NodeServices";import { assert, describe, it } from "@effect/vitest";import * as Effect from "effect/Effect";import * as FileSystem from "effect/FileSystem";import * as Layer from "effect/Layer";import * as Schema from "effect/Schema"; import * as DesktopConfig from "./DesktopConfig.ts";import * as DesktopEnvironment from "./DesktopEnvironment.ts";import * as DesktopObservability from "./DesktopObservability.ts"; const DesktopBackendChildLogRecord = Schema.Struct({ message: Schema.String, level: Schema.Literals(["INFO", "ERROR"]), timestamp: Schema.String, annotations: Schema.Record(Schema.String, Schema.Unknown), spans: Schema.Record(Schema.String, Schema.Unknown), fiberId: Schema.String,}); const decodeDesktopBackendChildLogRecord = Schema.decodeEffect( Schema.fromJsonString(DesktopBackendChildLogRecord),); const TraceRecordLine = Schema.Struct({ name: Schema.String, attributes: Schema.Record(Schema.String, Schema.Unknown), events: Schema.Array( Schema.Struct({ name: Schema.String, attributes: Schema.Record(Schema.String, Schema.Unknown), }), ),}); const decodeTraceRecordLine = Schema.decodeUnknownSync(Schema.fromJsonString(TraceRecordLine)); const environmentInput = (baseDir: string) => ({ dirname: "/repo/apps/desktop/dist-electron", homeDirectory: baseDir, platform: "darwin", processArch: "arm64", appVersion: "1.2.3", appPath: "/repo", isPackaged: false, resourcesPath: "/repo/resources", runningUnderArm64Translation: false, }) satisfies DesktopEnvironment.MakeDesktopEnvironmentInput; const makeEnvironmentLayer = (baseDir: string, isDevelopment = true) => DesktopEnvironment.layer(environmentInput(baseDir)).pipe( Layer.provide( Layer.mergeAll( NodeServices.layer, DesktopConfig.layerTest({ T3CODE_HOME: baseDir, VITE_DEV_SERVER_URL: isDevelopment ? "http://127.0.0.1:5733" : undefined, }), ), ), ); describe("DesktopObservability", () => { it("advances a retained output offset instead of repeatedly copying a full head chunk", () => { const maxBufferedBytes = 1024 * 1024; const initial = DesktopObservability.appendBoundedOutputChunk( { runId: "test-run", startDetails: "pid=123", chunks: [], byteLength: 0, }, "stderr", new Uint8Array(maxBufferedBytes), ); const initialBackingBuffer = initial.chunks[0]?.chunk.buffer; const next = DesktopObservability.appendBoundedOutputChunk(initial, "stderr", Uint8Array.of(1)); assert.equal(next.chunks[0]?.chunk.buffer, initialBackingBuffer); assert.equal(next.chunks[0]?.offset, 1); assert.equal(next.byteLength, maxBufferedBytes); }); it.effect("persists desktop Effect logs as span events in desktop.trace.ndjson", () => Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; const baseDir = yield* fileSystem.makeTempDirectoryScoped({ prefix: "t3-desktop-observability-test-", }); const environmentLayer = makeEnvironmentLayer(baseDir); const tracePath = yield* Effect.gen(function* () { const environment = yield* DesktopEnvironment.DesktopEnvironment; return environment.path.join(environment.logDir, "desktop.trace.ndjson"); }).pipe(Effect.provide(environmentLayer)); const logPath = yield* Effect.gen(function* () { const environment = yield* DesktopEnvironment.DesktopEnvironment; return environment.path.join(environment.logDir, "desktop-main.log"); }).pipe(Effect.provide(environmentLayer)); yield* Effect.scoped( Effect.gen(function* () { yield* Effect.annotateCurrentSpan({ "desktop.test": true }); yield* Effect.logInfo("desktop trace event"); }).pipe( Effect.withSpan("desktop-observability-test"), Effect.provide(DesktopObservability.layer.pipe(Layer.provideMerge(environmentLayer))), ), ); const records = (yield* fileSystem.readFileString(tracePath)) .trim() .split("\n") .filter((line) => line.length > 0) .map((line) => decodeTraceRecordLine(line)); const record = records.find((entry) => entry.name === "desktop-observability-test"); assert.notEqual(record, undefined); if (!record) { return; } assert.equal(record.attributes["desktop.test"], true); assert.equal( record.events.some((event) => event.name === "desktop trace event"), true, ); assert.isFalse(yield* fileSystem.exists(logPath)); }).pipe( Effect.scoped, Effect.provide(Layer.mergeAll(NodeServices.layer, NodeHttpClient.layerUndici)), ), ); it.effect("buffers backend child output and persists it only when a failure is reported", () => Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; const baseDir = yield* fileSystem.makeTempDirectoryScoped({ prefix: "t3-desktop-backend-output-log-test-", }); const environmentLayer = makeEnvironmentLayer(baseDir, false); const logPath = yield* Effect.gen(function* () { const environment = yield* DesktopEnvironment.DesktopEnvironment; return environment.path.join(environment.logDir, "server-child.log"); }).pipe(Effect.provide(environmentLayer)); const tracePath = yield* Effect.gen(function* () { const environment = yield* DesktopEnvironment.DesktopEnvironment; return environment.path.join(environment.logDir, "desktop.trace.ndjson"); }).pipe(Effect.provide(environmentLayer)); yield* Effect.gen(function* () { const factory = yield* DesktopObservability.DesktopBackendOutputLogFactory; const outputLog = yield* factory.forInstance("primary"); yield* outputLog.beginSession({ details: "pid=123 port=3773 cwd=/repo", }); yield* outputLog.writeOutputChunk("stdout", new TextEncoder().encode("hello server\n")); assert.isFalse(yield* fileSystem.exists(logPath)); yield* outputLog.persistFailure({ details: "code=1" }); yield* outputLog.beginSession({ details: "pid=456" }); yield* outputLog.writeOutputChunk("stderr", new TextEncoder().encode("normal shutdown\n")); yield* outputLog.discardSession; }).pipe( Effect.annotateLogs({ runId: "test-run" }), Effect.provide(DesktopObservability.layer.pipe(Layer.provideMerge(environmentLayer))), ); const log = yield* fileSystem.readFileString(logPath); const lines = log.trimEnd().split("\n"); const start = yield* decodeDesktopBackendChildLogRecord(lines[0] ?? ""); const output = yield* decodeDesktopBackendChildLogRecord(lines[1] ?? ""); const end = yield* decodeDesktopBackendChildLogRecord(lines[2] ?? ""); assert.equal(lines.length, 3); assert.equal(start.message, "backend child process failure output start"); assert.equal(start.level, "ERROR"); assert.equal(start.annotations.component, "desktop-backend-child"); assert.equal(start.annotations.runId, "test-run"); assert.equal(start.annotations.instanceId, "primary"); assert.equal(start.annotations.phase, "START"); assert.equal(start.annotations.details, "pid=123 port=3773 cwd=/repo"); assert.equal(output.message, "backend child process output"); assert.equal(output.level, "INFO"); assert.equal(output.annotations.component, "desktop-backend-child"); assert.equal(output.annotations.runId, "test-run"); assert.equal(output.annotations.instanceId, "primary"); assert.equal(output.annotations.stream, "stdout"); assert.equal(output.annotations.text, "hello server\n"); assert.equal(end.message, "backend child process failure output end"); assert.equal(end.level, "ERROR"); assert.equal(end.annotations.instanceId, "primary"); assert.equal(end.annotations.phase, "END"); assert.equal(end.annotations.details, "code=1"); const traceRecords = (yield* fileSystem.readFileString(tracePath)) .trim() .split("\n") .filter((line) => line.length > 0) .map((line) => decodeTraceRecordLine(line)); assert.isFalse( traceRecords.some( (record) => record.name === "desktop.observability.backendOutput.writeOutputChunk", ), ); }).pipe( Effect.scoped, Effect.provide(Layer.mergeAll(NodeServices.layer, NodeHttpClient.layerUndici)), ), ); it.effect("keeps buffering output after a non-terminal failure snapshot", () => Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; const baseDir = yield* fileSystem.makeTempDirectoryScoped({ prefix: "t3-desktop-backend-output-snapshot-test-", }); const environmentLayer = makeEnvironmentLayer(baseDir, false); const logPath = yield* Effect.gen(function* () { const environment = yield* DesktopEnvironment.DesktopEnvironment; return environment.path.join(environment.logDir, "server-child.log"); }).pipe(Effect.provide(environmentLayer)); yield* Effect.gen(function* () { const factory = yield* DesktopObservability.DesktopBackendOutputLogFactory; const outputLog = yield* factory.forInstance("primary"); yield* outputLog.beginSession({ details: "pid=123" }); yield* outputLog.writeOutputChunk("stdout", new TextEncoder().encode("before timeout\n")); yield* outputLog.persistFailureSnapshot({ details: "readiness timeout" }); yield* outputLog.writeOutputChunk("stderr", new TextEncoder().encode("after timeout\n")); yield* outputLog.persistFailure({ details: "code=1" }); }).pipe( Effect.annotateLogs({ runId: "test-run" }), Effect.provide(DesktopObservability.layer.pipe(Layer.provideMerge(environmentLayer))), ); const records = yield* Effect.forEach( (yield* fileSystem.readFileString(logPath)).trimEnd().split("\n"), (line) => decodeDesktopBackendChildLogRecord(line), ); assert.equal( records.some((record) => record.annotations.text === "after timeout\n"), true, ); assert.equal(records.at(-1)?.annotations.details, "code=1"); }).pipe( Effect.scoped, Effect.provide(Layer.mergeAll(NodeServices.layer, NodeHttpClient.layerUndici)), ), ); it.effect("retains only the last mebibyte of backend child output", () => Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; const baseDir = yield* fileSystem.makeTempDirectoryScoped({ prefix: "t3-desktop-backend-output-bound-test-", }); const environmentLayer = makeEnvironmentLayer(baseDir, false); const logPath = yield* Effect.gen(function* () { const environment = yield* DesktopEnvironment.DesktopEnvironment; return environment.path.join(environment.logDir, "server-child.log"); }).pipe(Effect.provide(environmentLayer)); const maxBufferedBytes = 1024 * 1024; const discardedPrefixBytes = 128; const output = new Uint8Array(maxBufferedBytes + discardedPrefixBytes); output.fill("x".charCodeAt(0)); output.fill("y".charCodeAt(0), 0, discardedPrefixBytes); yield* Effect.scoped( Effect.gen(function* () { const factory = yield* DesktopObservability.DesktopBackendOutputLogFactory; const outputLog = yield* factory.forInstance("primary"); yield* outputLog.beginSession({ details: "pid=123" }); yield* outputLog.writeOutputChunk("stderr", output); yield* outputLog.persistFailure({ details: "code=1" }); }).pipe( Effect.provide(DesktopObservability.layer.pipe(Layer.provideMerge(environmentLayer))), ), ); const lines = (yield* fileSystem.readFileString(logPath)).trimEnd().split("\n"); const record = yield* decodeDesktopBackendChildLogRecord(lines[1] ?? ""); const text = record.annotations.text; assert.equal(typeof text, "string"); if (typeof text !== "string") { return; } assert.equal(new TextEncoder().encode(text).byteLength, maxBufferedBytes); assert.isFalse(text.includes("y")); }).pipe( Effect.scoped, Effect.provide(Layer.mergeAll(NodeServices.layer, NodeHttpClient.layerUndici)), ), ); it.effect("bounds the number of retained backend child output chunks", () => Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; const baseDir = yield* fileSystem.makeTempDirectoryScoped({ prefix: "t3-desktop-backend-output-chunks-test-", }); const environmentLayer = makeEnvironmentLayer(baseDir, false); const logPath = yield* Effect.gen(function* () { const environment = yield* DesktopEnvironment.DesktopEnvironment; return environment.path.join(environment.logDir, "server-child.log"); }).pipe(Effect.provide(environmentLayer)); yield* Effect.scoped( Effect.gen(function* () { const factory = yield* DesktopObservability.DesktopBackendOutputLogFactory; const outputLog = yield* factory.forInstance("primary"); yield* outputLog.beginSession({ details: "pid=123" }); for (let index = 0; index < 300; index += 1) { yield* outputLog.writeOutputChunk("stderr", Uint8Array.of(index % 128)); } yield* outputLog.persistFailure({ details: "code=1" }); }).pipe( Effect.provide(DesktopObservability.layer.pipe(Layer.provideMerge(environmentLayer))), ), ); const lines = (yield* fileSystem.readFileString(logPath)).trimEnd().split("\n"); assert.equal(lines.length, 258); }).pipe( Effect.scoped, Effect.provide(Layer.mergeAll(NodeServices.layer, NodeHttpClient.layerUndici)), ), );});
import * as NodeHttpClient from "@effect/platform-node/NodeHttpClient";
import * as NodeServices from "@effect/platform-node/NodeServices";
import { assert, describe, it } from "@effect/vitest";
import * as Effect from "effect/Effect";
import * as FileSystem from "effect/FileSystem";
import * as Layer from "effect/Layer";
import * as Schema from "effect/Schema";
import * as DesktopConfig from "./DesktopConfig.ts";
import * as DesktopEnvironment from "./DesktopEnvironment.ts";
import * as DesktopObservability from "./DesktopObservability.ts";
const DesktopBackendChildLogRecord = Schema.Struct({
message: Schema.String,
level: Schema.Literals(["INFO", "ERROR"]),
timestamp: Schema.String,
annotations: Schema.Record(Schema.String, Schema.Unknown),
spans: Schema.Record(Schema.String, Schema.Unknown),
fiberId: Schema.String,
});
const decodeDesktopBackendChildLogRecord = Schema.decodeEffect(
Schema.fromJsonString(DesktopBackendChildLogRecord),
);
const TraceRecordLine = Schema.Struct({
name: Schema.String,
attributes: Schema.Record(Schema.String, Schema.Unknown),
events: Schema.Array(
Schema.Struct({
name: Schema.String,
attributes: Schema.Record(Schema.String, Schema.Unknown),
}),
),
});
const decodeTraceRecordLine = Schema.decodeUnknownSync(Schema.fromJsonString(TraceRecordLine));
const environmentInput = (baseDir: string) =>
({
dirname: "/repo/apps/desktop/dist-electron",
homeDirectory: baseDir,
platform: "darwin",
processArch: "arm64",
appVersion: "1.2.3",
appPath: "/repo",
isPackaged: false,
resourcesPath: "/repo/resources",
runningUnderArm64Translation: false,
}) satisfies DesktopEnvironment.MakeDesktopEnvironmentInput;
const makeEnvironmentLayer = (baseDir: string, isDevelopment = true) =>
DesktopEnvironment.layer(environmentInput(baseDir)).pipe(
Layer.provide(
Layer.mergeAll(
NodeServices.layer,
DesktopConfig.layerTest({
T3CODE_HOME: baseDir,
VITE_DEV_SERVER_URL: isDevelopment ? "http://127.0.0.1:5733" : undefined,
}),
),
),
);
describe("DesktopObservability", () => {
it("advances a retained output offset instead of repeatedly copying a full head chunk", () => {
const maxBufferedBytes = 1024 * 1024;
const initial = DesktopObservability.appendBoundedOutputChunk(
{
runId: "test-run",
startDetails: "pid=123",
chunks: [],
byteLength: 0,
},
"stderr",
new Uint8Array(maxBufferedBytes),
);
const initialBackingBuffer = initial.chunks[0]?.chunk.buffer;
const next = DesktopObservability.appendBoundedOutputChunk(initial, "stderr", Uint8Array.of(1));
assert.equal(next.chunks[0]?.chunk.buffer, initialBackingBuffer);
assert.equal(next.chunks[0]?.offset, 1);
assert.equal(next.byteLength, maxBufferedBytes);
});
it.effect("persists desktop Effect logs as span events in desktop.trace.ndjson", () =>
Effect.gen(function* () {
const fileSystem = yield* FileSystem.FileSystem;
const baseDir = yield* fileSystem.makeTempDirectoryScoped({
prefix: "t3-desktop-observability-test-",
});
const environmentLayer = makeEnvironmentLayer(baseDir);
const tracePath = yield* Effect.gen(function* () {
const environment = yield* DesktopEnvironment.DesktopEnvironment;
return environment.path.join(environment.logDir, "desktop.trace.ndjson");
}).pipe(Effect.provide(environmentLayer));
const logPath = yield* Effect.gen(function* () {
const environment = yield* DesktopEnvironment.DesktopEnvironment;
return environment.path.join(environment.logDir, "desktop-main.log");
}).pipe(Effect.provide(environmentLayer));
yield* Effect.scoped(
Effect.gen(function* () {
yield* Effect.annotateCurrentSpan({ "desktop.test": true });
yield* Effect.logInfo("desktop trace event");
}).pipe(
Effect.withSpan("desktop-observability-test"),
Effect.provide(DesktopObservability.layer.pipe(Layer.provideMerge(environmentLayer))),
),
);
const records = (yield* fileSystem.readFileString(tracePath))
.trim()
.split("\n")
.filter((line) => line.length > 0)
.map((line) => decodeTraceRecordLine(line));
const record = records.find((entry) => entry.name === "desktop-observability-test");
assert.notEqual(record, undefined);
if (!record) {
return;
}
assert.equal(record.attributes["desktop.test"], true);
assert.equal(
record.events.some((event) => event.name === "desktop trace event"),
true,
);
assert.isFalse(yield* fileSystem.exists(logPath));
}).pipe(
Effect.scoped,
Effect.provide(Layer.mergeAll(NodeServices.layer, NodeHttpClient.layerUndici)),
),
);
it.effect("buffers backend child output and persists it only when a failure is reported", () =>
Effect.gen(function* () {
const fileSystem = yield* FileSystem.FileSystem;
const baseDir = yield* fileSystem.makeTempDirectoryScoped({
prefix: "t3-desktop-backend-output-log-test-",
});
const environmentLayer = makeEnvironmentLayer(baseDir, false);
const logPath = yield* Effect.gen(function* () {
const environment = yield* DesktopEnvironment.DesktopEnvironment;
return environment.path.join(environment.logDir, "server-child.log");
}).pipe(Effect.provide(environmentLayer));
const tracePath = yield* Effect.gen(function* () {
const environment = yield* DesktopEnvironment.DesktopEnvironment;
return environment.path.join(environment.logDir, "desktop.trace.ndjson");
}).pipe(Effect.provide(environmentLayer));
yield* Effect.gen(function* () {
const factory = yield* DesktopObservability.DesktopBackendOutputLogFactory;
const outputLog = yield* factory.forInstance("primary");
yield* outputLog.beginSession({
details: "pid=123 port=3773 cwd=/repo",
});
yield* outputLog.writeOutputChunk("stdout", new TextEncoder().encode("hello server\n"));
assert.isFalse(yield* fileSystem.exists(logPath));
yield* outputLog.persistFailure({ details: "code=1" });
yield* outputLog.beginSession({ details: "pid=456" });
yield* outputLog.writeOutputChunk("stderr", new TextEncoder().encode("normal shutdown\n"));
yield* outputLog.discardSession;
}).pipe(
Effect.annotateLogs({ runId: "test-run" }),
Effect.provide(DesktopObservability.layer.pipe(Layer.provideMerge(environmentLayer))),
);
const log = yield* fileSystem.readFileString(logPath);
const lines = log.trimEnd().split("\n");
const start = yield* decodeDesktopBackendChildLogRecord(lines[0] ?? "");
const output = yield* decodeDesktopBackendChildLogRecord(lines[1] ?? "");
const end = yield* decodeDesktopBackendChildLogRecord(lines[2] ?? "");
assert.equal(lines.length, 3);
assert.equal(start.message, "backend child process failure output start");
assert.equal(start.level, "ERROR");
assert.equal(start.annotations.component, "desktop-backend-child");
assert.equal(start.annotations.runId, "test-run");
assert.equal(start.annotations.instanceId, "primary");
assert.equal(start.annotations.phase, "START");
assert.equal(start.annotations.details, "pid=123 port=3773 cwd=/repo");
assert.equal(output.message, "backend child process output");
assert.equal(output.level, "INFO");
assert.equal(output.annotations.component, "desktop-backend-child");
assert.equal(output.annotations.runId, "test-run");
assert.equal(output.annotations.instanceId, "primary");
assert.equal(output.annotations.stream, "stdout");
assert.equal(output.annotations.text, "hello server\n");
assert.equal(end.message, "backend child process failure output end");
assert.equal(end.level, "ERROR");
assert.equal(end.annotations.instanceId, "primary");
assert.equal(end.annotations.phase, "END");
assert.equal(end.annotations.details, "code=1");
const traceRecords = (yield* fileSystem.readFileString(tracePath))
.trim()
.split("\n")
.filter((line) => line.length > 0)
.map((line) => decodeTraceRecordLine(line));
assert.isFalse(
traceRecords.some(
(record) => record.name === "desktop.observability.backendOutput.writeOutputChunk",
),
);
}).pipe(
Effect.scoped,
Effect.provide(Layer.mergeAll(NodeServices.layer, NodeHttpClient.layerUndici)),
),
);
it.effect("keeps buffering output after a non-terminal failure snapshot", () =>
Effect.gen(function* () {
const fileSystem = yield* FileSystem.FileSystem;
const baseDir = yield* fileSystem.makeTempDirectoryScoped({
prefix: "t3-desktop-backend-output-snapshot-test-",
});
const environmentLayer = makeEnvironmentLayer(baseDir, false);
const logPath = yield* Effect.gen(function* () {
const environment = yield* DesktopEnvironment.DesktopEnvironment;
return environment.path.join(environment.logDir, "server-child.log");
}).pipe(Effect.provide(environmentLayer));
yield* Effect.gen(function* () {
const factory = yield* DesktopObservability.DesktopBackendOutputLogFactory;
const outputLog = yield* factory.forInstance("primary");
yield* outputLog.beginSession({ details: "pid=123" });
yield* outputLog.writeOutputChunk("stdout", new TextEncoder().encode("before timeout\n"));
yield* outputLog.persistFailureSnapshot({ details: "readiness timeout" });
yield* outputLog.writeOutputChunk("stderr", new TextEncoder().encode("after timeout\n"));
yield* outputLog.persistFailure({ details: "code=1" });
}).pipe(
Effect.annotateLogs({ runId: "test-run" }),
Effect.provide(DesktopObservability.layer.pipe(Layer.provideMerge(environmentLayer))),
);
const records = yield* Effect.forEach(
(yield* fileSystem.readFileString(logPath)).trimEnd().split("\n"),
(line) => decodeDesktopBackendChildLogRecord(line),
);
assert.equal(
records.some((record) => record.annotations.text === "after timeout\n"),
true,
);
assert.equal(records.at(-1)?.annotations.details, "code=1");
}).pipe(
Effect.scoped,
Effect.provide(Layer.mergeAll(NodeServices.layer, NodeHttpClient.layerUndici)),
),
);
it.effect("retains only the last mebibyte of backend child output", () =>
Effect.gen(function* () {
const fileSystem = yield* FileSystem.FileSystem;
const baseDir = yield* fileSystem.makeTempDirectoryScoped({
prefix: "t3-desktop-backend-output-bound-test-",
});
const environmentLayer = makeEnvironmentLayer(baseDir, false);
const logPath = yield* Effect.gen(function* () {
const environment = yield* DesktopEnvironment.DesktopEnvironment;
return environment.path.join(environment.logDir, "server-child.log");
}).pipe(Effect.provide(environmentLayer));
const maxBufferedBytes = 1024 * 1024;
const discardedPrefixBytes = 128;
const output = new Uint8Array(maxBufferedBytes + discardedPrefixBytes);
output.fill("x".charCodeAt(0));
output.fill("y".charCodeAt(0), 0, discardedPrefixBytes);
yield* Effect.scoped(
Effect.gen(function* () {
const factory = yield* DesktopObservability.DesktopBackendOutputLogFactory;
const outputLog = yield* factory.forInstance("primary");
yield* outputLog.beginSession({ details: "pid=123" });
yield* outputLog.writeOutputChunk("stderr", output);
yield* outputLog.persistFailure({ details: "code=1" });
}).pipe(
Effect.provide(DesktopObservability.layer.pipe(Layer.provideMerge(environmentLayer))),
),
);
const lines = (yield* fileSystem.readFileString(logPath)).trimEnd().split("\n");
const record = yield* decodeDesktopBackendChildLogRecord(lines[1] ?? "");
const text = record.annotations.text;
assert.equal(typeof text, "string");
if (typeof text !== "string") {
return;
}
assert.equal(new TextEncoder().encode(text).byteLength, maxBufferedBytes);
assert.isFalse(text.includes("y"));
}).pipe(
Effect.scoped,
Effect.provide(Layer.mergeAll(NodeServices.layer, NodeHttpClient.layerUndici)),
),
);
it.effect("bounds the number of retained backend child output chunks", () =>
Effect.gen(function* () {
const fileSystem = yield* FileSystem.FileSystem;
const baseDir = yield* fileSystem.makeTempDirectoryScoped({
prefix: "t3-desktop-backend-output-chunks-test-",
});
const environmentLayer = makeEnvironmentLayer(baseDir, false);
const logPath = yield* Effect.gen(function* () {
const environment = yield* DesktopEnvironment.DesktopEnvironment;
return environment.path.join(environment.logDir, "server-child.log");
}).pipe(Effect.provide(environmentLayer));
yield* Effect.scoped(
Effect.gen(function* () {
const factory = yield* DesktopObservability.DesktopBackendOutputLogFactory;
const outputLog = yield* factory.forInstance("primary");
yield* outputLog.beginSession({ details: "pid=123" });
for (let index = 0; index < 300; index += 1) {
yield* outputLog.writeOutputChunk("stderr", Uint8Array.of(index % 128));
}
yield* outputLog.persistFailure({ details: "code=1" });
}).pipe(
Effect.provide(DesktopObservability.layer.pipe(Layer.provideMerge(environmentLayer))),
),
);
const lines = (yield* fileSystem.readFileString(logPath)).trimEnd().split("\n");
assert.equal(lines.length, 258);
}).pipe(
Effect.scoped,
Effect.provide(Layer.mergeAll(NodeServices.layer, NodeHttpClient.layerUndici)),
),
);
});