v2.3.3
Live session state moved out of Postgres
- The four per-session live fields (
hashRate,currentDifficulty,channelCount,bestDifficulty) were rewritten ~3×/minute per active session — roughly 2 000 row writes a minute at current pool size. They now live in per-sessionclient:live:*Redis hashes with a TTL on the dead-session-sweep clock, andclient_entitykeeps only the birth row. - The two bulk writers behind that load are gone, so
CLIENT_ENTITY_BULK_WRITE_LOCKno longer serialises two long statements over the same ~700 rows. It still guards row births and stays for the next multi-row writer. - Scope, measured rather than assumed: of 42 slow-statement burst minutes on the previous release, 23 contain only statistics inserts and no
client_entitywrite at all. This removes one of two independent causes, not both.
The public high-score list survives a miner's own reset
/api/info→highScoresread the same column/bestdiff_resetzeroes, so a miner clearing their own best also erased their leaderboard entry — permanently, because the flush'sGREATESTonly ever re-offers the current window's maximum.- The value is now split.
bestDifficultystays the miner's own, resettable number;allTimeBestDifficultyis the pool's record and is never lowered by any reset or delete path. Both are folded by the same upsert, so there is no second writer to drift. - A reset now also clears the per-session bests in Redis. It never did, so a miner who reset kept seeing the old value on every worker row until the next share.
delete-allempties the address-settings row instead of deleting it, so the record survives. What stays behind carries no address — only a difficulty, a firmware string and a timestamp.
Fixes
- The
/bestdiff_resetbot command and the reset endpoint left different state behind: the endpoint deleted the notification baseline row, the bot command did not. Both now go through one function.
Upgrade notes
- Migrations 0013 and 0014 run at boot. 0013 drops four
client_entitycolumns, and the previous image namescurrentDifficultyin its row-birth INSERT — an oldcorecontainer can no longer create a session once the migration has run. Deploy everything at once (docker compose --profile mainnet up -dwithout service names), not service by service. - Rolling back is not "put the old image back": the dropped columns have to be added again first, or the old code writes into columns that no longer exist.
- One large
crons.kill_dead_clients: reconciled sessions swept=Nabout six to seven minutes after the deploy is expected — rows that existed before the deploy never received aclient:live:*key. - Migration 0014 seeds
allTimeBestDifficultyfrom whateverbestDifficultyholds at that moment. An address whose best was reset shortly before the deploy carries the reset value into the leaderboard, not its historic record.