jetstream v2 in zig stream.waow.tech
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"><title>stream</title><link rel="icon" type="image/svg+xml" href="/favicon.svg"><meta name="theme-color" content="#040708">{{$s := httpInclude "/status"}}{{$seq := regexFind "[0-9,]+" (regexFind "upstream seq[^\n]+" $s)}}{{$segs := regexFind "[0-9,]+" (regexFind "sealed segs[^\n]+" $s)}}{{$desc := "jetstream v2 firehose + full-network atproto archive"}}{{if $seq}}{{$desc = printf "%s · network seq %s · %s sealed segments" $desc $seq $segs}}{{end}}<meta name="description" content="{{$desc}}"><meta property="og:title" content="stream"><meta property="og:description" content="{{$desc}}"><meta property="og:type" content="website"><meta property="og:url" content="https://stream.waow.tech/"><meta name="twitter:card" content="summary"><meta name="twitter:title" content="stream"><meta name="twitter:description" content="{{$desc}}"><style>
#river{max-width:100%;overflow:clip;color:var(--water);font-size:15px;line-height:1.5;white-space:pre;text-align:center;letter-spacing:.05em;user-select:none}.seq{display:flex;flex-direction:column;align-items:center;gap:.25rem}#seq{font-size:1.5rem;font-weight:300;color:var(--hot);letter-spacing:.06em;font-variant-numeric:tabular-nums}.seqlbl{font-size:.72rem;color:var(--dim);letter-spacing:.3em;text-transform:uppercase}.rate{color:var(--water);letter-spacing:normal;text-transform:none;margin-left:1ch}.rate:hover{color:var(--hot)}.tag{color:var(--dim);font-size:.8rem;text-align:center;white-space:nowrap;margin-top:.3rem;max-width:100%}.eps{--endpoint-font-size:14px;display:flex;flex-direction:column;gap:.8rem;width:100%;max-width:66ch}.ep{display:grid;grid-template-columns:4.5ch minmax(0,1fr);gap:.4rem 1.2ch;align-items:baseline}.ep .m{color:var(--dim);font-size:var(--endpoint-font-size);text-align:right}.ep .p{font-size:var(--endpoint-font-size);color:var(--ink);min-width:0;white-space:nowrap}.ep .p b{color:var(--hot);font-weight:400}.ep:hover .p b{color:var(--water)}.ep .d{grid-column:2;color:var(--dim);font:var(--endpoint-font-size)/1.6 system-ui,sans-serif;min-width:0;white-space:nowrap}@media (max-width:640px){#river{font-size:11px}.wrap{padding:0 1.5ch} footer{gap:.45rem 2ch}#stats{flex-basis:100%;text-align:center}}footer .icon{width:11px;height:11px;vertical-align:-1px;margin-right:.6ch}.wrap{position:relative}</style><link rel="stylesheet" href="/brand.css?v=2"></head><body data-page="home"><div id="atmosphere" aria-hidden="true"><canvas id="depth" data-current></canvas></div><div class="wrap"><header> <a class="brand" href="/">~ s t r e a m ~</a> <span class="livedot" id="live">· connecting</span> <p class="tag">every event on the atproto network, as it happens, archived forever.</p></header><main> <div id="river" aria-hidden="true"></div> <div class="seq"><span id="seq">—</span><span class="seqlbl">network sequence<a id="rate" class="rate" href="/stats#expected" title="how the expected rate is estimated"></a></span></div> <div class="eps"> {{$eps := mustFromJson (httpInclude "/api/endpoints.json")}}{{range $eps.endpoints}}{{if ne .group "ops"}}<div class="ep"><span class="m">{{.method}}</span><span class="p">{{.prefix}}<b>{{.name}}</b></span><span class="d">{{.desc}}</span></div> {{end}}{{end}} </div></main><footer> <a href="/" aria-current="page">home</a> <a href="/stats">stats</a> <a href="/status">status</a> <a href="/strata/">strata</a> <span id="stats"></span> <a href="https://grafana.stream.waow.tech" title="grafana dashboards"><svg class="icon" viewBox="0 0 16 16" aria-hidden="true"><path d="M1.5 12.5 5 7.5l3 2.5 5.5-7" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/><path d="M1 14.5h14" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg>grafana</a> <a id="commit" href="https://tangled.org/zat.dev/stream">build</a> <a href="https://tangled.org/zat.dev/stream">source</a></footer></div><script src="/river.js?v=2"></script><script src="/ambient.js?v=river-1"></script><script>const $ = (id) => document.getElementById(id);const endpoints = document.querySelector('.eps');const endpointLines = endpoints.querySelectorAll('.p, .d, .m');function fitLines(){ endpoints.style.removeProperty('--endpoint-font-size'); let size = parseFloat(getComputedStyle(endpointLines[0]).fontSize); for (let attempt = 0; attempt < 3; attempt++) { const ratio = Math.min(1, ...Array.from(endpointLines, line => line.clientWidth / line.scrollWidth)); if (ratio >= 1) break; size *= ratio * .99; endpoints.style.setProperty('--endpoint-font-size', `${size}px`); } const tagline = document.querySelector('.tag'); tagline.style.fontSize = ''; for (let attempt = 0; attempt < 3 && tagline.scrollWidth > tagline.clientWidth; attempt++) { const size = parseFloat(getComputedStyle(tagline).fontSize); tagline.style.fontSize = `${size * tagline.clientWidth / tagline.scrollWidth * .99}px`; }}new ResizeObserver(fitLines).observe(endpoints);fitLines();let _prevSeq = null;let _prevSeqAt = 0, _rateEma = null;// cross-page continuity: polls persist {seq, t, ema}; the next page load// compares its first read against a fresh stored point instead of waiting// for a second poll. sessionStorage is per-tab, same-origin.try { const c = JSON.parse(sessionStorage.getItem("seqCont") || "null"); if (c && Date.now() - c.t < 60_000 && BigInt(c.seq) > 0n) { _prevSeq = BigInt(c.seq); _prevSeqAt = performance.now() - (Date.now() - c.t); _rateEma = c.ema; }} catch {}function saveCont(upN){ try { sessionStorage.setItem("seqCont", JSON.stringify({ seq: upN.toString(), t: Date.now(), ema: _rateEma })); } catch {}}// median firehose rate by utc hour (relay-eval, 5 months); see /statsconst EXPECTED = [360,351,335,314,278,250,240,228,220,224,249,296,346,384,413,424,428,422,419,418,423,418,400,378];// live baseline: relay-eval recomputes hour-of-day quantiles from its own// accumulating history; the embedded table is only the pre-fetch fallback.let PROFILE = null;fetch("https://relay-eval.waow.tech/api/rate-profile").then(r => r.json()) .then(d => { PROFILE = d.hours; for (let h = 0; h < 24; h++) EXPECTED[h] = d.hours[h].med; }) .catch(() => {});window.__ingestRate = () => _rateEma;function noteRate(upN){ const now = performance.now(); if (_prevSeq !== null && upN > _prevSeq && _prevSeqAt > 0) { const inst = Number(upN - _prevSeq) * 1000 / (now - _prevSeqAt); _rateEma = _rateEma === null ? inst : 0.6 * _rateEma + 0.4 * inst; } else if (upN === _prevSeq) { _rateEma = _rateEma === null ? 0 : 0.6 * _rateEma; } _prevSeqAt = now;
}async function fetchStatus(){ const t = await (await fetch("/status",{headers:{Accept:"text/plain"},cache:"no-store"})).text(); const g = (re)=>{const m=t.match(re);return m?m[1]:null}; const build = g(/build ([0-9a-f]{7,})/); if(build && $("commit")){ $("commit").textContent = build; $("commit").href = "https://tangled.org/zat.dev/stream/commits/" + build; } // honest live-tail signal: the upstream seq must exist AND advance between // reads. "state live" from the binary only means the process is serving. const up = g(/upstream seq\s+([\d,]+)/); const upN = up ? BigInt(up.replace(/,/g,"")) : 0n; const flowing = upN > 0n && _prevSeq !== null && upN > _prevSeq; const stalled = upN > 0n && _prevSeq !== null && upN === _prevSeq; // a booting instance reports upstream seq 0: feeding that into the rate // math (or persisting it) makes the next real read look like a delta of // the entire relay sequence space — the '503M/s' artifact if (upN > 0n) { dispatchEvent(new CustomEvent('stream-sequence', { detail: upN.toString() })); noteRate(upN); saveCont(upN); _prevSeq = upN; } const x = _rateEma === null ? 0 : _rateEma / EXPECTED[new Date().getUTCHours()]; const rateTxt = _rateEma !== null && _rateEma >= 1 ? " · <a href=\"/stats#expected\" style=\"color:var(--water);text-decoration:none\">≈" + Math.round(_rateEma).toLocaleString() + " events/s" + (x > 1.5 ? " (" + x.toFixed(1) + "× typical)" : "") + "</a>" : ""; if($("live")) $("live").innerHTML = flowing ? "<b>●</b> live tail flowing" + rateTxt : stalled ? "· live tail stalled · archive serving" : upN > 0n ? "· checking tail…" : "· live tail paused · archive serving"; return { t, g };}
(() => { async function tick(){ try{ const { g } = await fetchStatus(); const up = g(/upstream seq\s+([\d,]+)/), cur = g(/durable cursor\s+([\d,]+)/); const shown = (up && up !== "0") ? up : cur; if(shown){ $("seq").textContent = shown; } const ev = g(/events this run\s+([\d,]+)/), ls = g(/listeners\s+([\d,]+)/); const bits = []; if(ev && ev !== "0") bits.push(ev + " events this run"); if(ls && ls !== "0") bits.push(ls + " listening"); $("stats").textContent = bits.join(" · "); }catch(e){ $("live").textContent = "· unreachable"; } } tick(); setInterval(tick, 5000);})();
</script></body></html>