Skip to content

Commit 21d83aa

Browse files
authored
feat: Iceberg Roulette initial implementation
* Add design spec and gitignore Initial project spec for iceberg-roulette: Svelte+Vite single-page site with roulette wheel engine picker and typed compatibility data model. * Update spec: remove cloud provider, add DuckLake catalog * docs: add implementation plan * feat: scaffold Vite + Svelte + TypeScript project * fix: use vitest/config defineConfig for correct test types, commit lockfile * feat: add data types and skeleton compatibility data * test: add compatibility data quality and known-fact assertions * feat: add full Iceberg catalog compatibility data * fix: correct catalog support levels based on Notion empirical matrix * feat: add Wheel SVG component with spin animation and manual selection * fix: reorder spin callback state updates; add aria-live, aria-pressed, aria-label * feat: add CatalogResults component with expandable limitations * fix: reset expanded state on engine change; fix Space key handler; fix aria roles * feat: wire App.svelte with two-column layout and full data flow * fix: remove redundant on:select handlers; drop gap:0 no-op; add noreferrer * ci: add GitHub Actions deploy to GitHub Pages * chore: add .vite cache to gitignore * fix: add test/check steps to CI; remove unused dispatch; idiomatic reactive syntax; add OGP meta * chore: switch to pnpm * feat: bigger wheels, spin audio ticks, improved text contrast * fix: shared AudioContext across wheels, await resume before scheduling ticks * fix: setTimeout-based audio timing; add no-match red banner; confirm postgres all-none * fix: combine write+read engine rules per catalog; read engine now affects results * feat: add read-side catalog overrides for asymmetric engine capabilities Some engines can read from catalogs they cannot write to (e.g. Databricks can read from REST/Glue, Redshift can read from Glue via Spectrum). Introduces engineReadRules for these cases so bigquery→databricks correctly shows REST as partial rather than none. * fix: warm AudioContext before animation start to fix first-spin sound timing Pre-scheduling sounds relative to spinStart failed when the AudioContext needed to resume — the async gap made early tick delays go negative and collapse to a single click. Now we await the context first, then start the animation, so all setTimeout delays are simple targetMs values with no elapsed-time correction needed. * fix: use Web Audio scheduler instead of setTimeout for tick timing setTimeout has ~1ms minimum resolution and coalesces callbacks at similar delays into the same event loop batch, causing early ticks to play simultaneously. Use ctx.currentTime + absolute offsets with src.start(when) instead — the Web Audio scheduler is sub-millisecond accurate and runs independently of the JS event loop. * fix: pre-warm AudioContext in capture phase + replace Nessie with S3 Tables Audio: document capture-phase listener creates AudioContext synchronously on first click, before any element handler fires. This guarantees the context is in 'running' state when spin() runs — no async gap, no collapsed early ticks. Data: replace Nessie catalog with AWS S3 Tables. Athena and Trino have full support; Snowflake partial via CLD+REST; Databricks and Redshift can read via REST/Spectrum respectively (engineReadRules). * fix: redshift has partial write support for Glue and S3 Tables * data: clarify Unity Catalog write creates Managed Iceberg tables only Per Databricks docs, external engines writing via the Unity Catalog Iceberg REST API create Managed Iceberg tables. Existing Delta tables are read-only via this interface. * data: correct 5 entries based on online doc verification - snowflake→s3tables: partial→full (REST write GA Oct 2025) - redshift→glue: partial→full (full DML write support Nov 2025) - redshift→s3tables: partial→full (full DML write support Nov 2025) - trino→unity: full→partial (write not GA in OSS Trino; requires security mode adjustments) - duckdb→s3tables: none→partial (supported via Iceberg REST endpoint) * fix(audio): silent primer + 0.1s lookahead + debug logging On a fresh AudioContext, currentTime=0 and the pipeline hasn't opened yet. Scheduling sounds at t=0 queues them all until the pipeline opens, which happens to be ~4s later (coinciding with animation end). Fix: - Play a silent 1-sample buffer immediately on initAudio to force the pipeline open before any real sounds are scheduled - Add 0.1s lookahead offset so sounds are always in the future even on a cold-start context - Console logs on every audio event so the browser devtools show exactly what state the context is in at each step * fix(audio): use wall-clock setTimeout chain instead of AudioContext absolute times ctx.currentTime was 0 on first spin — sounds scheduled at absolute audio times played when the audio clock started advancing (~4s later), not when intended. Fix: use performance.now() to decide WHEN each tick fires, and ctx.currentTime+5ms only for the actual src.start() call ('play right now'). The AudioContext clock value no longer matters. * fix(audio): simplest possible approach — OscillatorNode + pre-scheduled setTimeouts Drop the noise buffer + chain approach entirely. Use: - OscillatorNode (proven to produce sound, no buffer setup needed) - All setTimeouts scheduled upfront at spin time (no chaining complexity) - Louder gain (0.5/0.8 vs 0.15/0.28) * fix(audio): white noise click buffer, 100ms startup delay, halved volume - Replace sine-wave OscillatorNode with pre-computed white noise buffer (18ms exponential decay — sounds like a real mechanical click) - Add 100ms minimum delay before first tick so the AudioContext pipeline is fully initialized; prevents silent startup burst where early ticks all fired at ctxTime=0 simultaneously - Gain: 0.35 for ticks, 0.5 for final ding * chore: add GitHub Pages deploy workflow and fill out README - deploy.yml: pnpm-based GitHub Actions pipeline, triggers on push to main - README: what the app does, engines/catalogs covered, dev setup, contributing guide
1 parent 0dceddc commit 21d83aa

18 files changed

Lines changed: 4203 additions & 1 deletion

.github/workflows/deploy.yml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
name: Deploy to GitHub Pages
2+
3+
on:
4+
push:
5+
branches: [main]
6+
workflow_dispatch:
7+
8+
permissions:
9+
contents: read
10+
pages: write
11+
id-token: write
12+
13+
concurrency:
14+
group: pages
15+
cancel-in-progress: true
16+
17+
jobs:
18+
build:
19+
runs-on: ubuntu-latest
20+
steps:
21+
- uses: actions/checkout@v4
22+
- uses: pnpm/action-setup@v4
23+
with:
24+
version: 10
25+
- uses: actions/setup-node@v4
26+
with:
27+
node-version: 20
28+
cache: pnpm
29+
- run: pnpm install --frozen-lockfile
30+
- run: pnpm build
31+
- uses: actions/upload-pages-artifact@v3
32+
with:
33+
path: dist
34+
35+
deploy:
36+
needs: build
37+
runs-on: ubuntu-latest
38+
environment:
39+
name: github-pages
40+
url: ${{ steps.deployment.outputs.page_url }}
41+
steps:
42+
- id: deployment
43+
uses: actions/deploy-pages@v4

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
node_modules/
2+
dist/
3+
.superpowers/
4+
.vite/

README.md

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,45 @@
1-
# iceberg-roulette
1+
# 🎰 Iceberg Roulette
2+
3+
**Which Iceberg catalogs work between your write engine and read engine?** Spin to find out — or just click the engine chips.
4+
5+
🔗 **Live site:** https://b-per.github.io/iceberg-roulette/
6+
7+
---
8+
9+
## What it does
10+
11+
Pick a write engine and a read engine (or spin the roulette wheels). The app shows you which Apache Iceberg catalog types work for that combination, with support levels:
12+
13+
-**full** — both engines support this catalog with no known blockers
14+
-**partial** — works, but with caveats (click to expand limitations)
15+
-**none** — not supported
16+
17+
## Engines covered
18+
19+
`snowflake` · `bigquery` · `databricks` · `duckdb` · `redshift` · `trino` · `athena` · `postgres`
20+
21+
## Catalogs covered
22+
23+
| Catalog | Notes |
24+
|---------|-------|
25+
| AWS Glue | |
26+
| REST / Polaris / Open Catalog | Includes any Iceberg REST-compatible endpoint |
27+
| Hive Metastore | |
28+
| AWS S3 Tables | Managed Iceberg REST catalog, GA since Nov 2024 |
29+
| Unity Catalog | Databricks Unity Catalog Iceberg REST |
30+
| DuckLake | DuckDB-native catalog backed by a DuckDB file |
31+
32+
> Data reflects best-effort knowledge as of mid-2025. Verify against official docs before going to prod.
33+
34+
## Local development
35+
36+
```bash
37+
pnpm install
38+
pnpm dev # http://localhost:5173/iceberg-roulette/
39+
pnpm test # vitest
40+
pnpm build # output → dist/
41+
```
42+
43+
## Contributing
44+
45+
Corrections and additions welcome — the compatibility data lives in [`src/data/compatibility.ts`](src/data/compatibility.ts). Tests are in [`src/data/compatibility.test.ts`](src/data/compatibility.test.ts).

0 commit comments

Comments
 (0)