v1.1.0 — Gzip canvas compression + throttled sends
All checks were successful
CI / ci (push) Successful in 6m29s

- Canvas snapshots gzip-compressed before sending: 1MB raw -> ~1-5KB
  for a mostly-white canvas, ~100-500KB for a busy one
- Semaphore throttles concurrent canvas sends (default 20) to prevent
  memory spikes during connection bursts
- Frontend decompresses gzip via browser DecompressionStream API
- New config: MAX_CONCURRENT_CANVAS_SENDS (default 20)
- Added flate2 dependency for gzip encoding
This commit is contained in:
2026-08-18 02:28:47 +02:00
parent 31f0fce7a9
commit 3fbae1bd95
9 changed files with 113 additions and 20 deletions

View File

@@ -13,6 +13,13 @@ const createSocketIoTransport = () => {
};
};
const decompressGzip = async (buffer) => {
const stream = new Blob([buffer])
.stream()
.pipeThrough(new DecompressionStream("gzip"));
return new Response(stream).arrayBuffer();
};
const createWebSocketTransport = () => {
const handlers = {};
const wsUrl = isDebug
@@ -38,9 +45,10 @@ const createWebSocketTransport = () => {
ws.addEventListener("open", () => dispatch("connect"));
ws.addEventListener("message", (event) => {
ws.addEventListener("message", async (event) => {
if (event.data instanceof ArrayBuffer) {
const pixels = new Uint32Array(event.data);
const decompressed = await decompressGzip(event.data);
const pixels = new Uint32Array(decompressed);
dispatch("canvas_state", Array.from(pixels));
return;
}