Repository navigation
feat(payments): add per-plan event rate limits and retention - #922
Priyanshubhartistm wants to merge 3 commits into
Conversation
Signed-off-by: Priyanshubhartistm <bhartipriyanshustm@gmail.com>
🦋 Changeset detectedLatest commit: 13ad9b7 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Coverage Report for CI Build 40769746508Warning No base build found for commit Coverage: 76.532%Details
Uncovered ChangesNo uncovered changes found. Coverage RegressionsRequires a base build to compare against. How to fix this → Coverage Stats💛 - Coveralls |
[Critical impact] The PR appears safe to merge; no new actionable issue was found.
|
…an for 60s Signed-off-by: Priyanshubhartistm <bhartipriyanshustm@gmail.com>
Description
Builds on the subscription lifecycle (#909). Nothing changes unless
payments.enabledis true and a plan setslimits.rateLimitsorlimits.retentionMaxDays(settings and validation already exist from #849).EventMessageHandler.isRateLimiteduses the limits of the sender's plan in place oflimits.event.rateLimitswhile the subscription gives access (grace included). An empty list means no limit. Everyone else, and a subscriber whose subscription ended or whose plan was removed from the settings, keeps the global limits. Counters are keyed exactly as before (<pubkey>:events:<period>), whitelists still apply.<pubkey>:subscription-plan(plan:<id>ornone) with a TTL that never outlives access, andisUserAdmittedfills it when it reads the subscription, so there is no extra database read per event. If a read fails the global limits apply and nothing is cached.deleteExpiredAndRetained) takesplanRetention. Events of subscribers on a plan withretentionMaxDaysare purged at the plan's window, everyone else at the global one, with the kind and pubkey whitelists unchanged. A subscriber counts only while their access lasts, so once it ends their events fall back to the global window at the next pass. The query is the same as before when no plan sets a retention.CONFIGURATION.mddescribes both settings.Related Issue
Closes #921
Motivation and Context
Rate limits and retention were global, so a premium subscriber got the same limits as everyone else. This is the "higher tiers get better rate limits and longer event retention" part of the tiered access.
A plan retention only applies while
limits.event.retention.maxDaysis set (the purge does not run without it). Per-plan connection and subscription-count limits are not part of this PR.How Has This Been Tested?
isRateLimited(plan vs global, empty list, kinds, expired, lapsed and grace, removed plan, whitelist, subscriptions off, cache hit/miss/error/TTL, database error), the plan cached byisUserAdmitted, the purge query with plan retention (exact SQL, whitelists, several plans, shorter windows, expired subscribers, invalid values) andMaintenanceService. Reverting the access check, the cache read, the global exclusion, the expired filter or the subscriptions-enabled check each fails a test.pnpm lint,pnpm check:deps,pnpm run build:check,pnpm run build,pnpm run verify:cli:build,pnpm run test:unit(2547 passing),pnpm run test:cli(105 passing).