9 Commits
Author SHA1 Message Date
tiennm99 9f50237a3c docs: purge remaining Upstash references and sync to DO storage
Drop /admin/migrate-from-upstash from public API docs, replace deprecated
UPSTASH_* env vars with ALLOWED_ORIGINS/ENVIRONMENT, update Worker
conventions to reflect DO bindings (env.CANVAS_ROOM) instead of Redis
client patterns, and rewrite system-architecture security/data-flow
sections to cover cookie+IP identity, transactionSync atomicity, WS
Origin allowlist, per-identity WS cap, and broadcast sequence numbers.
2026-05-11 15:59:50 +07:00
tiennm99 b890dfb3b7 fix(canvas): code-review fixes + sync user-facing docs to DO storage
Fixes from code review of canvas-on-do migration (commit c3f7c02):

- worker.js /api/ws: rewrite request URL to '/ws' so the DO pathname
  switch dispatches correctly. The original c.req.raw kept '/api/ws'
  which the DO never matched → 404 on every WS upgrade.
- migrate-from-upstash.js pickSampleOffsets: use TOTAL_PIXELS - 1 for the
  last byte instead of CANVAS_WIDTH * CANVAS_WIDTH (only correct when
  the canvas is square; constants explicitly invite non-square).
- chunk-storage.js writePixels: clarify atomicity comment — the loop is
  atomic *because it has no awaits*, not because of any implicit DO
  transaction. Added guidance for future maintainers.
- cooldown-store.js tryAcquire: GC sweep wrapped in try/catch so a
  transient failure can't drop the user's allowed: true response.

Docs:
- README.md: drop Upstash from tech stack, redraw architecture,
  document new project layout (durable-objects/lib, admin/), add
  CHUNK_BYTES to configuration table.
- docs/system-architecture.md: full rewrite for DO-storage data flow,
  document SQLite schema, race-safe rate-limit pattern, free-tier table.
- docs/deployment-guide.md: drop Upstash setup, add optional one-shot
  migration runbook, update free-tier table to actual May 2026 limits.

Tests: 112 pass, 6 skipped (pending Phase 4 rewrite via
@cloudflare/vitest-pool-workers). Bundle dry-run clean.

Local wrangler dev smoke test was attempted but the sandboxed env
hangs HTTP requests at the workerd layer (TCP connects, no response).
Routing fix verified by code inspection; user must verify in their
own dev or production.
2026-05-10 00:37:27 +07:00
tiennm99 cdf2295ef6 docs(canvas): correct CF DO limits in resize doc and plan
Earlier docs assumed a 1 GB per-DO storage cap. Actual May 2026 free-tier
limits per the CF DO docs:
- 10 GB per Durable Object
- 5 GB per account (the real Free-tier ceiling)
- 2 MB per BLOB row
- 1,000 req/sec soft cap per DO

Practical effect: canvas can grow to ~70,000 × 70,000 on Free (was previously
documented as ~32K × 32K). Existing 64 KB CHUNK_BYTES is well-suited:
clustered writes (single pixels + image patches) minimize read-modify-write
amplification; bigger chunks would only help uniform-random writes which
isn't rplace's workload.

No code change. Just doc accuracy.
2026-05-10 00:07:39 +07:00
tiennm99 c3f7c02f6d feat(canvas): migrate canvas + cooldown storage to DO SQLite
Move pixel state and rate-limit cooldowns out of Upstash Redis and into
the existing CanvasRoom Durable Object's SQLite-backed storage. Worker
becomes a thin validation/proxy; the DO does atomic cooldown check +
pixel write + WS broadcast in one in-memory step.

Why: eliminate external dependency, keep $0/month free-tier forever,
exploit single-threaded actor for strong consistency without round-trips.

Architecture:
- canvas_chunks: 256 BLOB rows × 64 KB; CHUNK_COUNT derived from
  CANVAS_WIDTH × CANVAS_HEIGHT / CHUNK_BYTES so resize is config-only.
- cooldowns: user_id → expires_at, 1% sample-rate lazy GC.
- Worker forwards /api/canvas, /api/place, /api/ws to DO endpoints.
- POST /admin/migrate-from-upstash: token-gated one-shot importer.

Phases 1-3 code complete; Upstash dependency stays until prod migration
runs and 7-day rollback window passes (Phase 4).

Plan: plans/260509-2309-canvas-on-do-storage/
2026-05-09 23:53:21 +07:00
tiennm99andGitHub cfbac2a586 feat(canvas): 4096^2 canvas, 256-color palette (u8 byte-aligned), custom picker (#5)
Canvas:
- CANVAS_W/H = 4096, total 16,777,216 pixels
- BITS_PER_PIXEL = 8 (byte-aligned) — raw Redis bytes are palette indices
- Canvas-decoder becomes an identity wrap/copy
- Storage BITFIELD uses u8; offset = y*W + x
- Redis key versioned to rplace:canvas:v2 so old 32-color/2048^2 data is
  orphaned (operators can DEL the old key to reclaim memory)

Palette:
- 256 entries, generated deterministically:
  - 0..15  = 16-step grayscale ramp (pure black -> pure white)
  - 16..255 = 240 HSL wheel (4 lightness rings x 60 hues @ 82% saturation)
- nearestPaletteIndex(r,g,b) helper for custom-color snapping

UI:
- ColorPicker: 16-swatch favorites strip (grays + 8 accents) + current-color
  swatch + expand toggle for the full 16x16 grid + "Custom..." button that
  opens the native <input type="color"> and snaps to nearest palette entry
- Default selected color bumped to index 0 (black)

Tests + docs:
- canvas-decoder tests rewritten for identity u8 decode
- canvas-storage tests updated for u8 offsets
- image-to-palette tests anchored to PALETTE_BLACK=0 / PALETTE_WHITE=15 and
  COLORS_RGBA[i] probes (no more hardcoded old 32-color indices)
- integration test uses u8 BITFIELD and canvas-aware bounds
- README, system-architecture, deployment-guide updated (storage math,
  migration note for orphaned old key)
2026-04-18 13:47:01 +07:00
tiennm99andGitHub f59e55a852 refactor(rate-limit): 1 req/sec cooldown, batch up to 2048 (#3)
* refactor(rate-limit): switch to 1 req/sec cooldown, batch size up to 2048

Replace per-pixel credit/token-bucket model with a simple per-user cooldown
(SET NX EX 1). Batch size is now independent of the rate limit and capped
at MAX_BATCH_SIZE = 2048.

- rate-limiter: SET NX EX replaces Lua credit script
- worker: response shape { ok: true } (no credits field)
- client: drop credit state/timer/UserInfo; uploader paces by cooldown
- tests: mock checkRateLimit; integration test exercises SET NX EX
- docs: README, system-architecture, code-standards, deployment-guide

* chore(plans): remove implemented plan directories

rplace-implementation (base build), review-fixes, and
image-importer-enhancements are all shipped. Keep plans/reports/ as
historical code-review and research references.
2026-04-18 10:19:00 +07:00
tiennm99 fc49de154a add project documentation and detailed README
- README: features, architecture diagram, setup guide, API reference,
  configuration table, project structure
- docs/system-architecture.md: data flow, storage design, rate limiting
- docs/code-standards.md: conventions, project layout, API format
- docs/deployment-guide.md: step-by-step CF Workers + Upstash deploy
2026-04-16 17:05:29 +07:00
tiennm99 62188d26d2 update references and add credits to README
Remove unfetchable URLs (redditinc, reddit.com, tejash.dev, rplace.live).
Add credits section to README attributing all referenced projects.
2026-04-16 15:24:50 +07:00
tiennm99 9bdde946a0 add r/place reference links and resources
Curated collection of official post-mortems, technical walkthroughs,
open-source implementations, and live instances for r/place research.
2026-04-16 14:43:23 +07:00