19 Commits
Author SHA1 Message Date
binwiederhier 43a26501b9 Advance by the topic's own touch interval in the tests that touch after an hour
Claude-Session: https://claude.ai/code/session_01DeXuhSjq5Gta5qPJgSceFe
2026-11-02 18:01:06 +00:00
binwiederhier 858af8c6ad Write a topic's subscriber activity every one to two hours instead of every 30 to 60 minutes
Claude-Session: https://claude.ai/code/session_01DeXuhSjq5Gta5qPJgSceFe
2026-11-02 17:59:00 +00:00
binwiederhier 799d13f6d8 Write a UnifiedPush topic's subscriber activity about once an hour, spread over time
v2.37.0 wrote every topic with an open stream every 5 minutes, and the topics touched together after a restart stayed in step, so ntfy.sh wrote ~45k topic rows in the same minute every 5 minutes (~145 rows/s on average, more than the message inserts), stalling the primary. Each topic now has its own interval between 30 and 60 minutes (by hash), and a subscribe or poll that only repeats the same rate visitor is a touch.

Claude-Session: https://claude.ai/code/session_01DeXuhSjq5Gta5qPJgSceFe
2026-11-02 17:51:41 +00:00
binwiederhier 4f1f62b0b5 Rename RecordRefused to Refused 2026-11-02 01:23:04 +00:00
binwiederhier 15c924fd3b Rename Note to RecordRefused, and its counter and cap to match 2026-11-02 00:52:26 +00:00
binwiederhier 01047d68b7 Keep the topic service's pending rows and the store's row slices as pointers 2026-11-02 00:47:09 +00:00
binwiederhier 3a3e4217b9 Merge Keepalive into Touch, throttled to once per 5 minutes
The manager touches the topics of open streams every minute; subscribes, polls and closing streams use the same throttle, which shifts subscriber activity by at most 5 minutes.
2026-11-01 20:07:17 +00:00
binwiederhier e6b97f524a Pass the store to limit.New and topic.New instead of a one-field Config 2026-11-01 18:29:46 +00:00
binwiederhier c56f4fb529 Answer 410 after 4 days without a subscriber, and prune topic rows after 7 days 2026-11-01 17:14:11 +00:00
binwiederhier 70a992aba5 Clarify that the cap on topics known from refused pushes is cluster-wide 2026-11-01 17:11:46 +00:00
binwiederhier 943dec84f1 Serve if the topics cannot be loaded at startup, and leave the load to the sync worker 2026-11-01 17:11:46 +00:00
binwiederhier c56a9f9f73 Do not write a stale rate visitor with a touch or keepalive, so a newer one from another node wins 2026-11-01 17:11:07 +00:00
binwiederhier 582cae9f4c Simplify the topic service: one pending-rows map, one flat State row, a synchronous startup load
A refused push's Note returns the topic's state for the publish path, prune forgets unwritten
changes along with the topic, and SetForTest is gone: tests age rows in the database.
2026-11-01 15:16:30 +00:00
binwiederhier 312e036ec9 Do not mark topics to be written without a store, so the dirty set cannot grow forever 2026-11-01 14:59:24 +00:00
binwiederhier 3fb5b53086 Look up the rate visitor's user on each push, like an authenticated publish does
Drops the background refresh, its cache and Manager.UsersByIDs: one primary key read per UnifiedPush push to a topic whose subscriber has an account (none for anonymous subscribers), and a tier change applies to the next message.
2026-11-01 14:35:10 +00:00
binwiederhier 7ad3e3d6ea Answer 410 Gone (41002) instead of 404 for an abandoned UnifiedPush topic
Every app server that drops a subscription on a 404 also drops it on a 410, and Misskey and its forks only do on a 410. 410 is also what Mozilla's and Apple's push services answer for an expired subscription.
2026-11-01 13:33:56 +00:00
binwiederhier 6dc9abb3f7 Prune topic rows two weeks after their last write instead of 30 days
Half the memory per node; an abandoned UnifiedPush topic still has its row when a push 7+ days later decides on the 404, as long as it is pushed to at least every two weeks.
2026-11-01 11:25:02 +00:00
binwiederhier abcfd88cd8 Rename topic.Topic to topic.State, so the live topic can take the name later
The package comment now says the server's live topics are meant to move into the topic package.
2026-10-31 18:29:29 +00:00
binwiederhier 6ae42e7590 Add the topic package: per-topic cluster-wide state synced through the topic table
One row per topic (first_seen_at, subscribed_at, rate visitor user and IP,
updated_at), merged by rule (earliest, latest, last written) so the nodes can
write in any order, synced by the package's own 5 s worker from a dirty set.
User schema 10 -> 11 now creates this table.
2026-10-31 13:51:38 +00:00