VoteBroker Devlog — 13. Juni 2026
VoteBroker Devlog — 13. Juni 2026
Änderungen seit: 7. Juni 2026
Änderungen seit dem letzten Devlog
Diese Woche hatte zwei Gesichter: außen sichtbare Produktverbesserungen, die jeder Nutzer sofort spürt — und eine stille Infrastrukturkrise, die niemand gesehen hat, weil das System sie gerade noch selbst gelöst hat, bevor sie zum Problem wurde. Beides gehört in diesen Devlog.
„Heute" bedeutet ab jetzt dasselbe für alle — Per-User-Zeitzone
Das ist die wichtigste Produktverbesserung dieser Woche. Sie klingt technisch, aber dahinter steckt etwas, das jeden Kurator direkt betrifft.
Das bisherige Problem: Alle Tagesaggregationen in VoteBroker — Votes heute, VP-Verbrauch heute, Curation-Earnings heute, Growth-Streak — berechneten „Mitternacht" in UTC. Für jemanden in Mitteleuropa (UTC+2 im Sommer) begann der neue Tag im Dashboard also um 2 Uhr morgens statt um Mitternacht lokal. Wer um 0:30 Uhr votete, sah diesen Vote im Dashboard auf einem anderen „Tag" als erwartet.
Noch schlimmer: Chart und Kachel konnten unterschiedliche Zahlen zeigen. Die Kachel „Votes heute" zählte nach einer Logik, das Balkendiagramm nach einer anderen. Wenn man das nicht wusste, sah es aus wie ein Bug — war es auch, nur an einer Stelle, die niemand vermutete.
Die Lösung: VoteBroker speichert jetzt eine eigene IANA-Zeitzone pro Nutzer in der Datenbank. Standard ist Europe/Berlin, aber über das Einstellungen-Menü lässt sich jede gültige Zeitzone der Welt einstellen — von America/New_York bis Asia/Tokyo.
Beim ersten Besuch erkennt der Browser die lokale Zeitzone automatisch über Intl.DateTimeFormat().resolvedOptions().timeZone und speichert sie sofort. Beim ersten Login wird sie mit dem Server abgeglichen. Wer auf dem Server bereits eine Einstellung hat, behält sie. Wer noch keine hat, übernimmt die lokale — ohne Rückfrage, ohne Reibung.
Ab diesem Moment rechnen alle Systeme nach derselben Zeitzone:
- Der Vote-Zähler für heute
- Das VP-Budget und seine Tagesgruppen
- Die Earnings-Kachel und ihre Tagesbalken
- Der Growth-Streak (der bricht nicht mehr fälschlicherweise, weil ein Vote um 23:45 Uhr lokaler Zeit als „nächster Tag" in UTC gilt)
- Die Cutoff-Daten für 30-Tage- und 90-Tage-Ansichten
Technisch: Alle SQLite-Abfragen nutzen jetzt DATE(datetime(created_at, '+N minutes')) — wobei N der aktuelle UTC-Offset der Nutzer-Zeitzone ist, berechnet über die native Node.js Intl-API. Keine externe Bibliothek, kein globaler Server-Default, kein Kompromiss für DST.
Die user_settings-Tabelle ist dabei bereits für spätere Erweiterungen vorbereitet. locale, currency und date_format warten als Spalten auf ihren Einsatz — das Fundament für Sprache, Währungsanzeige und Datumsformat in einem kommenden Premium-Tier steht.
Der Healthcheck-Krimi — oder: warum Node.js manchmal einfach schweigt
Diese Geschichte beginnt mit einem simplen Symptom: Docker markierte den API-Container beim Start regelmäßig als unhealthy. Manuell aufgerufen antwortete /health sofort mit {"status":"ok"}. Was war los?
Der Healthcheck-Befehl wartete standardmäßig 5 Sekunden. Wir erhöhten auf 10 Sekunden — immer noch unhealthy. Wir erhöhten auf 30 Sekunden. Immer noch. Die API war offensichtlich oben, hörte auf Port 3000 — und trotzdem schlug der Healthcheck fehl.
Der erste Reflex war, den Healthcheck selbst zu verdächtigen. Aber wget -qO- http://127.0.0.1:3000/health funktionierte zu jeder Zeit, von jedem Terminal aus. Das Problem musste woanders liegen.
Die Diagnose: Ein Blick auf ss -tnp während des Starts zeigte es: Recv-Q: 12. Zwölf TCP-Verbindungen standen in der Warteschlange — nicht abgewiesen, nicht beantwortet, einfach wartend. Node.js war beschäftigt.
Die Ursache: Sechs Hintergrund-Jobs starteten alle gleichzeitig mit dem Server — VP-Sampler, Price-Sampler, Growth-Snapshot-Sampler, Signal-Compute, CoPilot-Shadow und Whale-Enrichment. Und alle sechs machten sofort beim Start externe Netzwerkanfragen an die Steem-Blockchain. Node.js ist single-threaded. Wenn sechs Jobs gleichzeitig auf I/O-Callbacks warten und dabei den Event-Loop fluten, kann der Server für kurze Zeit keine neuen Verbindungen akzeptieren — auch keine triviale HTTP-Anfrage auf /health.
Die Lösung in mehreren Schichten:
Erstens: Alle sechs Jobs starten jetzt mit 30 Sekunden Verzögerung nach Server-Start. Die API ist sofort bereit, der Event-Loop ist frei, der Healthcheck schlägt durch — in unter 1 ms statt Timeout.
Zweitens: Der PayoutSync-Job, der beim Start besonders viele Chain-Calls macht, wurde auf 120 Sekunden verschoben. Zusätzlich hat jeder einzelne get_content-Aufruf jetzt ein hartes 8-Sekunden-Timeout via Promise.race — ein hängender Chain-Call blockiert nicht mehr den gesamten Sync-Lauf.
Drittens: Im docker-compose.yml wurde der Healthcheck-Block auf timeout: 10s / retries: 10 / start_period: 90s gesetzt und mit dem CMD-SHELL-Flag -T 8 gegen Buffering abgesichert. Der Web-Container hängt jetzt nicht mehr am service_healthy-Status der API, sondern verwendet service_started — er startet unabhängig und ist selbst für seine Bereitschaft verantwortlich.
Das Ergebnis: Beide Container starten sauber durch, der Healthcheck zeigt nach dem nächsten Restart sofort (healthy), und die Chain-Calls laufen — ohne irgendetwas zu blockieren — im Hintergrund an.
CoPilot Shadow Mode — der stille Beobachter (8. Juni)
Der CoPilot ist VoteBrokers automatischer Kurations-Agent. Der neue Shadow Mode lässt ihn im Trockenlauf arbeiten: Alle 30 Minuten bewertet er Kandidaten vollständig und schreibt Entscheidungen in die Datenbank — aber sendet keinen Vote ab. Das Ergebnis ist ein lückenloser Entscheidungslog, der nachvollziehbar macht, was der CoPilot wollte.
Gleichzeitig wurde der Alters-Filter durch einen Opportunity Score ersetzt — ein zusammengesetzter Wert aus Curation-Fenster, historischem Timing, Whale-Signal und Autoren-Kategorie. Der Shadow Mode sammelt jetzt die Trainingsdaten, auf denen ein echter lernender Agent aufgebaut wird.
VP-Budget: Heute im Kontext (9. Juni)
Das VP-Budget-Panel zeigt jetzt den Tagesverbrauch im Vergleich mit dem 7-Tage-Schnitt. Wer normalerweise 8 % VP pro Tag verbraucht und heute bei 3 % steht, sieht das sofort. Gleichzeitig wurden die Farb-Schwellen nachjustiert: Orange beginnt früher, Rot signalisiert echten Handlungsbedarf.
Dual-Modell-Validierung und Growth Analytics (10. Juni)
Zwei Curation-Schätzmodelle laufen jetzt parallel: weight-basiert und rshares-basiert. MAE, RMSE und MAPE werden gegen tatsächliche Auszahlungen gemessen. Das weit verbreitete Tool beem überschätzt Curation-Rewards systematisch um Faktor 2,5× — zurückführbar auf Pool-Wachstum nach dem Vote. Unser Korrekturfaktor 0,20 erklärt das. Welches der beiden Modelle besser liegt, entscheiden die Daten — sobald 200–500 realisierte Votes eine stabile Basis liefern.
Das neue Growth Analytics Panel macht das sichtbar: Es zeigt den Ø Wachstumsfaktor (final_pool / pending_pool) nach Vote-Delay, Kategorie, Pool-Größe, Community, Wochentag und Stunde. Der Durchschnitt liegt bei ≈ 2,5× und bestätigt damit die Formel direkt aus realen Daten.
Vote Growth Snapshot System (11. Juni)
Für jeden VoteBroker-Vote werden jetzt Zeitreihen-Snapshots des Curation-Pools gesammelt: T+0, +15 min, +1h, +6h, +24h, +72h und bei Auszahlung. Aus diesen Werten berechnet eine SQL-View automatisch Early Momentum, Velocity, Growth Factor und Trajectory Class. Das ist die Datenbasis, auf der der CoPilot zukünftig lernen wird.
5-Minuten-Delay-Buckets (12. Juni)
Der Bucket < 30 Minuten war zu grob. Die Auflösung wurde auf 5-Minuten-Schritte verfeinert. Das Ergebnis: Ab etwa 12 Minuten nach Posting-Zeit beginnt in den realisierten Daten eine sichtbare Aktivitätsgrenze — der typische Bereich automatisierter Bots. Diese Grenze ist jetzt messbar, ohne Hypothese.
Community-Aktivität
Heute (2026-06-13):
- 26 Vote-Versuche ausgeführt
- 25 Autoren unterstützt: @realrobinhood, @abi24, @udabeu, @faisalamin, @supportive, @ini4909, @winkles, @votebroker und 17 weitere
- 2 aktive Kuratoren
Was als Nächstes kommt
- CoPilot-Entscheidungslog im Dashboard — welche Kandidaten wurden bewertet, welcher wurde gewählt und warum?
- Bucket-Analyse als Empfehlung — nicht nur zeigen, wann gute Votes stattgefunden haben, sondern aktiv empfehlen: „Deine besten Ergebnisse kommen bei Delay 15–20 min."
- Validierungsmodell: Weight vs. Rshares — Wechsel auf das bessere Modell nach 200–500 realisierten Votes.
- Sprache und Datumsformat als User-Setting — de/en-Toggle und ISO/EU-Datumsformat im Einstellungen-Menü.
VoteBroker — Community Curation auf Steem · votebroker.org
SignalCompute – Wenn Datenmengen plötzlich relevant werden (13. Juni)
Mit inzwischen fast einer halben Million Whale-Vote-Datensätzen zeigte sich ein klassisches Skalierungsproblem.
Eine Signal-Berechnung nutzte eine korrelierte SQL-Subquery, die für jede analysierte Zeile erneut Aggregationen über die gesamte Datengrundlage ausführte. Bei kleinen Datenmengen war dieser Effekt praktisch unsichtbar. Mit wachsender Datenbasis führte er jedoch dazu, dass Analysejobs den Node.js Event-Loop blockierten und API-Endpunkte verzögerten.
Die Berechnung wurde auf Voraggregation per CTE umgestellt und zusätzliche Indizes für häufig genutzte Analysepfade ergänzt. Gleichzeitig wurde der SignalCompute-Job aus dem Startup-Prozess entfernt und ausschließlich als geplanter Hintergrundjob ausgeführt.
Das Ergebnis: deutlich schnellere Berechnungen, stabile Health-Checks und ein reaktionsfähigeres Dashboard.