core: correct badge comments and one query style

This commit is contained in:
shum
2026-08-27 10:28:26 +00:00
parent 7e07426e69
commit df7cf40fe6
3 changed files with 25 additions and 3 deletions
+7
View File
@@ -218,6 +218,13 @@ data BadgeAlert = BadgeAlert
-- 'Maybe' because every other reader wants a number, and the one distinction it would carry is
-- already carried next to it.
--
-- __@monthsLeft@ excludes the month currently issued.__ It is the balance AFTER the running
-- period was debited, and 'Simplex.Chat.Library.Commands.badgePaidThrough' adds that balance to
-- a 'balanceStartTs' a successful issue moved to the END of that period — so a freshly redeemed
-- 3-month code reads as @monthsLeft = 2@ with @paidThrough@ three months out. The pair is
-- consistent and both figures are right; it is @monthsLeft@ ALONE that reads as if a month had
-- been lost. A surface showing one number should show @paidThrough@ (G4, G5).
--
-- @paidThrough@ is deliberately not the credential's expiry (UX §2.11 forbids presenting one as
-- the other).
data UserBadge = UserBadge
+12 -2
View File
@@ -5300,6 +5300,11 @@ startBadgeWorkers = mapM_ $ \User {userId} -> void $ getBadgeWorker True userId
--
-- The timer is this loop's own wait rather than a shared scheduler, and it is 'threadDelay''
-- rather than 'timeout' because a day in microseconds does not fit an 'Int' on 32-bit builds.
--
-- Every iteration gates on 'waitChatStartedAndActivated' first, as 'cleanupManager',
-- 'runRelayGroupLinkChecks' and 'expireChatItems' do: after @APISuspendChat@ the timer keeps
-- firing, and without the gate a pass would read the store and send a signed request through a
-- suspended agent.
runBadgeWorker :: UserId -> Worker -> CM ()
runBadgeWorker userId Worker {doWork} = do
interval <- asks $ badgePassInterval . config
@@ -5336,8 +5341,13 @@ issueDueBadgePeriod user@User {userId} = do
resp <- sendBadgeRequest NRMBackground user (Just purchasePrivKey) (badgeIssueRequest purchase balance)
storeBadgeIssueResponse now user purchase (Just lastEntry) resp
| otherwise -> pure BadgeUnchanged
-- unreachable via C1's createPurchase, which always inserts an opening credit, but a shown
-- purchase stuck with no ledger row would otherwise stall forever with no signal at all
-- unreachable, but NOT because a purchase is created with an opening credit — nothing in this
-- milestone writes one (plan §9), and 'createPurchase' inserts the purchase row alone.
-- 'redeemBadgeCode' is the only writer of a purchase row and of @shown_badge_id@, it refuses a
-- statement carrying no issued period BEFORE it writes anything, and it inserts that
-- statement's entries in the same transaction as the purchase row — so a shown purchase always
-- has ledger rows. A shown purchase stuck with none would otherwise stall forever with no
-- signal at all
Just (UserBadgePurchase {badgePurchaseId}, Nothing) -> do
logWarn $ "badge worker: shown purchase " <> tshow badgePurchaseId <> " (user " <> tshow userId <> ") has no ledger entries; nothing to issue"
pure BadgeUnchanged
+6 -1
View File
@@ -384,7 +384,12 @@ createIssuance db NewBadgeIssuance {badgePurchaseId, badgeType, periodStart, per
hasIssuanceForPeriod :: DB.Connection -> Int64 -> UTCTime -> IO Bool
hasIssuanceForPeriod db badgePurchaseId periodStart =
fromOnly . head
<$> DB.query db "SELECT EXISTS (SELECT 1 FROM badge_issuances WHERE badge_purchase_id = ? AND period_start = ?)" (badgePurchaseId, periodStart)
<$> DB.query
db
[sql|
SELECT EXISTS (SELECT 1 FROM badge_issuances WHERE badge_purchase_id = ? AND period_start = ?)
|]
(badgePurchaseId, periodStart)
-- Ledger ----------------------------------------------------------------------