Ably REST client used to broadcast transactionStatusUpdated. null
disables realtime publishing (tests, or a process that legitimately has
no Ably credentials) — the cache bust still runs. Required (not
defaulted) so every construction site has to decide explicitly, rather
than silently shipping a process with no realtime updates.
Bust both transaction caches for a customer, then broadcast that the given
transactions changed. customerId is the external string carried in the
emitted transaction event — the same value TransactionService.search /
aggregateTotalsByMethod write as their cache tag. transactionIds are
the external ids of the rows that this mutation touched for that customer.
The cache bust runs first (so the dashboard refetches fresh data) and keeps its current throwing behaviour. The realtime publish is best-effort: it never throws, so an Ably failure can never fail the mutation that triggered it.
OptionalbankId?: stringThe owning bank, when the mutated transaction is bank-routed (deposits, withdrawals). When present, the realtime nudge is additionally published on the bank's channel so the bank dashboard refreshes without subscribing to a network-wide firehose. Omit for bankless transactions — the customer and operator channels still fire.
Cross-namespace buster + realtime broadcaster over the customer transaction projection owned by TransactionService. Transaction-writer services (deposit, manual mint, withdrawal, swap, ledger-account transfer, card, reward, redemption, fee, escrow) construct or receive one of these and call invalidateTag after a successful write + event publish, so that — cross-process via the shared Valkey cluster + Ably — both:
customerId; admin search collection-wide), andThis replaces the old customer-dashboard
/api/eventswebhook, which used to re-fetch + publish the realtime event centrally. The dashboard's Ably subscriber only reads each row'sid(to invalidate its react-query caches and refetch), so the published payload is just{ id }per transaction — we never need to dragdb/TransactionServiceinto the writer processes to re-serialize the full row, keeping this collaborator lightweight.Builds busters over the exact same namespaces
TransactionServicereads through (TRANSACTION_SEARCH_CACHE / TRANSACTION_METHOD_AGGREGATE_CACHE, busted percustomerId) plus TRANSACTION_ADMIN_SEARCH_CACHE thatTransactionAdminServicereads through (busted collection-wide via TRANSACTION_ADMIN_SEARCH_COLLECTION_TAG, since admin pages are cross-customer).Transactions are the one entity that keeps a buster collaborator rather than rooting every writer on a
SearchCachesubclass: the writers are deposit / withdrawal / swap / reward / card / … services, each already rooted in its own entity's hierarchy and in another package, so single inheritance forbids them extending aTransactionCachetoo. See CACHING.md "Cross-domain (foreign-key) writers".