KamoCRM

Leads available and credit balances read a ledger instead of counting rows

Performancekamo-shared-library
Shipped
September 23, 2026 at 1:27 AM UTC
Author
Kamo
Commit
ae437eb

"Leads available" was COUNT(*) over the assignable pool, and one org's pool holds ~796k leads: ~7.8 s per (market, product) count and ~11 s for the grouped one (measured 2026-09-17). Manage-Credits ran the single count once per allotment row, Leads-Available once per product, and every Accept ran another just to broadcast the new figure. Credit balances were the same shape on lead_credits, which keeps every spent credit forever. Both figures now come from maintained totals: lead_pool_counts / lead_credit_balances plus an append-only journal of deltas that row triggers on leads / lead_credits write in the same transaction as the change (securityservice create_lead_ledgers.sql, applied 2026-09-22). A read sums total + journal in one statement, so it is exact, and Hibernate flushes pending writes before a native query, so a transaction sees its own mints and spends. The repository methods keep their names, so every caller in every service moves over with this library. DaemonService folds the journal every 30 s and recounts nightly, appending a correction for any drift. Also: - The Accept pick (findAssignablePool) read and sorted the whole product pool: 9.5 s per Accept. It is now findAssignablePoolUids, pinned with a pg_hint_plan hint to the new partial index ix_leads_assignable_pool, because this cluster's legacy planner prefers ix_leads_org_market and sorts. 9,470 ms -> 4 ms on the live pool; the existence probe (sampleAssignablePoolUids) likewise, and an empty product no longer costs a scan of its whole market. - Batch reads for the grids: **************** (every row's balance in one read), findSpentCreditsInRange (every member's spends since the earliest local midnight), countAcceptedSinceByProduct, and **************** the in-memory twin of findApplicableAllotments for resolving many (market, product) pairs from one list. Tests: LeadLedgerQueryShapeTest pins the ledger reads, the non-negative clamp, the bigint casts and the index hint; LeadAllotmentMostSpecificOfTest pins the resolver to the query's rules. The trigger DDL, every read, the fold and the recount were replayed against YugabyteDB (temp tables, 60 checks). Full suite: 3012 tests, 5 failing exactly as on a6374937 (StorageDomainCoverage, StorageDomainAssociationLookup, ReportVisibility, PhiServiceTypeMapping, SystemBugCountContract).

All changes

Like what you see shipping?

All of it arrives in your workspace on its own. Start on the free plan and read this page again in a month.

Start Free ForeverView Pricing