tapimo 0.10.2 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/App.d.ts +4896 -2166
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +2 -2
- package/dist/App.js.map +1 -1
- package/dist/Assets.d.ts +15 -0
- package/dist/Assets.d.ts.map +1 -1
- package/dist/Assets.js +7 -0
- package/dist/Assets.js.map +1 -1
- package/dist/Webhooks.d.ts +0 -75
- package/dist/Webhooks.d.ts.map +1 -1
- package/dist/Webhooks.js +1 -143
- package/dist/Webhooks.js.map +1 -1
- package/dist/admin/App.d.ts +127 -78
- package/dist/admin/App.d.ts.map +1 -1
- package/dist/admin/apps/earn-vaults.d.ts +115 -1
- package/dist/admin/apps/earn-vaults.d.ts.map +1 -1
- package/dist/admin/apps/earn-vaults.js +59 -6
- package/dist/admin/apps/earn-vaults.js.map +1 -1
- package/dist/admin/apps/organizations.d.ts +3 -3
- package/dist/admin/apps/organizations.d.ts.map +1 -1
- package/dist/admin/apps/organizations.js +4 -2
- package/dist/admin/apps/organizations.js.map +1 -1
- package/dist/admin/apps/verified-tokens.d.ts +83 -83
- package/dist/admin/ui.generated.d.ts +1 -1
- package/dist/admin/ui.generated.d.ts.map +1 -1
- package/dist/admin/ui.generated.js +151 -151
- package/dist/admin/ui.generated.js.map +1 -1
- package/dist/apps/data/App.d.ts +5924 -4310
- package/dist/apps/data/App.d.ts.map +1 -1
- package/dist/apps/data/App.js +61 -9
- package/dist/apps/data/App.js.map +1 -1
- package/dist/apps/data/ZoneSelection.d.ts +62 -0
- package/dist/apps/data/ZoneSelection.d.ts.map +1 -0
- package/dist/apps/data/ZoneSelection.js +44 -0
- package/dist/apps/data/ZoneSelection.js.map +1 -0
- package/dist/apps/data/routes/activities.d.ts +2368 -5
- package/dist/apps/data/routes/activities.d.ts.map +1 -1
- package/dist/apps/data/routes/activities.js +423 -114
- package/dist/apps/data/routes/activities.js.map +1 -1
- package/dist/apps/data/routes/addresses.d.ts +131 -0
- package/dist/apps/data/routes/addresses.d.ts.map +1 -1
- package/dist/apps/data/routes/balances.d.ts +25 -25
- package/dist/apps/data/routes/balances.js +1 -1
- package/dist/apps/data/routes/balances.js.map +1 -1
- package/dist/apps/data/routes/blocks.d.ts +1 -1
- package/dist/apps/data/routes/blocks.js +1 -1
- package/dist/apps/data/routes/blocks.js.map +1 -1
- package/dist/apps/data/routes/earn.d.ts +135 -10
- package/dist/apps/data/routes/earn.d.ts.map +1 -1
- package/dist/apps/data/routes/earn.js +157 -25
- package/dist/apps/data/routes/earn.js.map +1 -1
- package/dist/apps/data/routes/exchanges.d.ts +829 -123
- package/dist/apps/data/routes/exchanges.d.ts.map +1 -1
- package/dist/apps/data/routes/exchanges.js +16 -13
- package/dist/apps/data/routes/exchanges.js.map +1 -1
- package/dist/apps/data/routes/fee-amm.d.ts +26 -26
- package/dist/apps/data/routes/fee-amm.d.ts.map +1 -1
- package/dist/apps/data/routes/fee-amm.js +9 -11
- package/dist/apps/data/routes/fee-amm.js.map +1 -1
- package/dist/apps/data/routes/receipts.d.ts +54 -54
- package/dist/apps/data/routes/receipts.js +1 -1
- package/dist/apps/data/routes/receipts.js.map +1 -1
- package/dist/apps/data/routes/rpc.js +24 -10
- package/dist/apps/data/routes/rpc.js.map +1 -1
- package/dist/apps/data/routes/tokenlist.d.ts +12 -12
- package/dist/apps/data/routes/tokenlist.d.ts.map +1 -1
- package/dist/apps/data/routes/tokenlist.js +16 -15
- package/dist/apps/data/routes/tokenlist.js.map +1 -1
- package/dist/apps/data/routes/tokens.d.ts +17 -3
- package/dist/apps/data/routes/tokens.d.ts.map +1 -1
- package/dist/apps/data/routes/tokens.js +34 -15
- package/dist/apps/data/routes/tokens.js.map +1 -1
- package/dist/apps/data/routes/transactions.d.ts +1 -1
- package/dist/apps/data/routes/transactions.js +1 -1
- package/dist/apps/data/routes/transactions.js.map +1 -1
- package/dist/apps/data/routes/transfers.d.ts +13 -13
- package/dist/apps/data/routes/transfers.d.ts.map +1 -1
- package/dist/apps/data/routes/transfers.js +7 -9
- package/dist/apps/data/routes/transfers.js.map +1 -1
- package/dist/apps/data/routes/valuation.d.ts +21 -21
- package/dist/apps/data/routes/verified-tokens.d.ts +5 -5
- package/dist/apps/data/routes/webhooks.d.ts +1011 -151
- package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/data/routes/webhooks.js +126 -739
- package/dist/apps/data/routes/webhooks.js.map +1 -1
- package/dist/apps/data/routes/zones.d.ts +15 -15
- package/dist/apps/funding/App.d.ts +27 -27
- package/dist/apps/funding/routes/chains.d.ts.map +1 -1
- package/dist/apps/funding/routes/chains.js +5 -4
- package/dist/apps/funding/routes/chains.js.map +1 -1
- package/dist/apps/funding/routes/deposit-addresses.d.ts +18 -18
- package/dist/apps/funding/routes/deposit-addresses.d.ts.map +1 -1
- package/dist/apps/funding/routes/deposit-addresses.js +8 -8
- package/dist/apps/funding/routes/deposit-addresses.js.map +1 -1
- package/dist/apps/funding/routes/providers.d.ts.map +1 -1
- package/dist/apps/funding/routes/providers.js +3 -2
- package/dist/apps/funding/routes/providers.js.map +1 -1
- package/dist/apps/funding/routes/quotes.d.ts.map +1 -1
- package/dist/apps/funding/routes/quotes.js +2 -2
- package/dist/apps/funding/routes/quotes.js.map +1 -1
- package/dist/apps/funding/routes/transfers.d.ts +33 -33
- package/dist/apps/management/App.d.ts +1433 -322
- package/dist/apps/management/App.d.ts.map +1 -1
- package/dist/apps/management/Billing.d.ts.map +1 -1
- package/dist/apps/management/Billing.js +19 -6
- package/dist/apps/management/Billing.js.map +1 -1
- package/dist/apps/management/routes/api-keys.d.ts +154 -94
- package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
- package/dist/apps/management/routes/api-keys.js +76 -30
- package/dist/apps/management/routes/api-keys.js.map +1 -1
- package/dist/apps/management/routes/billing.d.ts +103 -30
- package/dist/apps/management/routes/billing.d.ts.map +1 -1
- package/dist/apps/management/routes/billing.js +91 -32
- package/dist/apps/management/routes/billing.js.map +1 -1
- package/dist/apps/management/routes/faucet.d.ts +12 -12
- package/dist/apps/management/routes/faucet.d.ts.map +1 -1
- package/dist/apps/management/routes/faucet.js +23 -12
- package/dist/apps/management/routes/faucet.js.map +1 -1
- package/dist/apps/management/routes/invitations.d.ts +46 -13
- package/dist/apps/management/routes/invitations.d.ts.map +1 -1
- package/dist/apps/management/routes/invitations.js +79 -29
- package/dist/apps/management/routes/invitations.js.map +1 -1
- package/dist/apps/management/routes/invite-links.d.ts +128 -83
- package/dist/apps/management/routes/invite-links.d.ts.map +1 -1
- package/dist/apps/management/routes/invite-links.js +100 -41
- package/dist/apps/management/routes/invite-links.js.map +1 -1
- package/dist/apps/management/routes/me.d.ts +5 -5
- package/dist/apps/management/routes/me.d.ts.map +1 -1
- package/dist/apps/management/routes/me.js +14 -10
- package/dist/apps/management/routes/me.js.map +1 -1
- package/dist/apps/management/routes/members.d.ts +68 -47
- package/dist/apps/management/routes/members.d.ts.map +1 -1
- package/dist/apps/management/routes/members.js +37 -18
- package/dist/apps/management/routes/members.js.map +1 -1
- package/dist/apps/management/routes/orgs.d.ts +48 -8
- package/dist/apps/management/routes/orgs.d.ts.map +1 -1
- package/dist/apps/management/routes/orgs.js +48 -19
- package/dist/apps/management/routes/orgs.js.map +1 -1
- package/dist/apps/management/routes/projects.d.ts +130 -68
- package/dist/apps/management/routes/projects.d.ts.map +1 -1
- package/dist/apps/management/routes/projects.js +72 -21
- package/dist/apps/management/routes/projects.js.map +1 -1
- package/dist/apps/management/routes/scopes.d.ts.map +1 -1
- package/dist/apps/management/routes/scopes.js +8 -5
- package/dist/apps/management/routes/scopes.js.map +1 -1
- package/dist/apps/management/routes/usage.d.ts +38 -38
- package/dist/apps/management/routes/usage.d.ts.map +1 -1
- package/dist/apps/management/routes/usage.js +41 -31
- package/dist/apps/management/routes/usage.js.map +1 -1
- package/dist/apps/management/routes/verified-token-requests.d.ts +34 -6
- package/dist/apps/management/routes/verified-token-requests.d.ts.map +1 -1
- package/dist/apps/management/routes/verified-token-requests.js +36 -17
- package/dist/apps/management/routes/verified-token-requests.js.map +1 -1
- package/dist/apps/management/routes/webhooks.d.ts +1186 -197
- package/dist/apps/management/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/management/routes/webhooks.js +106 -38
- package/dist/apps/management/routes/webhooks.js.map +1 -1
- package/dist/apps/mpp/internal/Adapter.d.ts +1 -1
- package/dist/apps/mpp/internal/Adapter.d.ts.map +1 -1
- package/dist/apps/mpp/internal/Adapter.js +12 -0
- package/dist/apps/mpp/internal/Adapter.js.map +1 -1
- package/dist/db/Db.d.ts +2 -0
- package/dist/db/Db.d.ts.map +1 -1
- package/dist/db/Db.js +61 -0
- package/dist/db/Db.js.map +1 -1
- package/dist/db/Schema.d.ts +30 -2
- package/dist/db/Schema.d.ts.map +1 -1
- package/dist/db/Schema.js +28 -3
- package/dist/db/Schema.js.map +1 -1
- package/dist/db/tables/earnVaults.d.ts +5 -1
- package/dist/db/tables/earnVaults.d.ts.map +1 -1
- package/dist/db/tables/earnVaults.js +5 -0
- package/dist/db/tables/earnVaults.js.map +1 -1
- package/dist/db/tables/webhookDeliveries.d.ts.map +1 -1
- package/dist/db/tables/webhookDeliveries.js +10 -0
- package/dist/db/tables/webhookDeliveries.js.map +1 -1
- package/dist/db/tables/webhookQueueCompletions.d.ts +15 -0
- package/dist/db/tables/webhookQueueCompletions.d.ts.map +1 -0
- package/dist/db/tables/webhookQueueCompletions.js +32 -0
- package/dist/db/tables/webhookQueueCompletions.js.map +1 -0
- package/dist/db/tables/webhookQueueEvents.d.ts +16 -20
- package/dist/db/tables/webhookQueueEvents.d.ts.map +1 -1
- package/dist/db/tables/webhookQueueEvents.js +68 -43
- package/dist/db/tables/webhookQueueEvents.js.map +1 -1
- package/dist/db/tables/webhookSubscriptions.d.ts +47 -72
- package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -1
- package/dist/db/tables/webhookSubscriptions.js +92 -105
- package/dist/db/tables/webhookSubscriptions.js.map +1 -1
- package/dist/internal/Auth.d.ts +8 -1
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +13 -3
- package/dist/internal/Auth.js.map +1 -1
- package/dist/internal/Cache.d.ts.map +1 -1
- package/dist/internal/Cache.js +11 -7
- package/dist/internal/Cache.js.map +1 -1
- package/dist/internal/EarnVaults.d.ts +41 -2
- package/dist/internal/EarnVaults.d.ts.map +1 -1
- package/dist/internal/EarnVaults.js +167 -0
- package/dist/internal/EarnVaults.js.map +1 -1
- package/dist/internal/MetricSink.d.ts +35 -125
- package/dist/internal/MetricSink.d.ts.map +1 -1
- package/dist/internal/MetricSink.js +50 -121
- package/dist/internal/MetricSink.js.map +1 -1
- package/dist/internal/OpenApi.d.ts +26 -22
- package/dist/internal/OpenApi.d.ts.map +1 -1
- package/dist/internal/OpenApi.js +128 -39
- package/dist/internal/OpenApi.js.map +1 -1
- package/dist/internal/Response.d.ts +13 -8
- package/dist/internal/Response.d.ts.map +1 -1
- package/dist/internal/Response.js +16 -5
- package/dist/internal/Response.js.map +1 -1
- package/dist/internal/Schema.d.ts +8 -8
- package/dist/internal/Schema.d.ts.map +1 -1
- package/dist/internal/Schema.js +10 -9
- package/dist/internal/Schema.js.map +1 -1
- package/dist/internal/Store.d.ts +15 -6
- package/dist/internal/Store.d.ts.map +1 -1
- package/dist/internal/Store.js +45 -15
- package/dist/internal/Store.js.map +1 -1
- package/dist/internal/Tidx.d.ts +2 -0
- package/dist/internal/Tidx.d.ts.map +1 -1
- package/dist/internal/Tidx.js +16 -4
- package/dist/internal/Tidx.js.map +1 -1
- package/dist/internal/WebhookTransfer.d.ts +1 -55
- package/dist/internal/WebhookTransfer.d.ts.map +1 -1
- package/dist/internal/WebhookTransfer.js +1 -239
- package/dist/internal/WebhookTransfer.js.map +1 -1
- package/dist/internal/Webhooks.d.ts +112 -56
- package/dist/internal/Webhooks.d.ts.map +1 -1
- package/dist/internal/Webhooks.js +124 -93
- package/dist/internal/Webhooks.js.map +1 -1
- package/dist/internal/funding/Deposit.d.ts +2 -2
- package/dist/internal/funding/Deposit.d.ts.map +1 -1
- package/dist/internal/funding/Deposit.js +9 -8
- package/dist/internal/funding/Deposit.js.map +1 -1
- package/dist/internal/funding/DepositAddress.d.ts +4 -4
- package/dist/internal/funding/DepositAddress.d.ts.map +1 -1
- package/dist/internal/funding/DepositAddress.js +9 -8
- package/dist/internal/funding/DepositAddress.js.map +1 -1
- package/dist/internal/funding/DepositWebhook.d.ts +25 -0
- package/dist/internal/funding/DepositWebhook.d.ts.map +1 -0
- package/dist/internal/funding/DepositWebhook.js +74 -0
- package/dist/internal/funding/DepositWebhook.js.map +1 -0
- package/dist/internal/funding/Provider.d.ts.map +1 -1
- package/dist/internal/funding/Provider.js +13 -12
- package/dist/internal/funding/Provider.js.map +1 -1
- package/dist/internal/funding/Reconciliation.d.ts +6 -0
- package/dist/internal/funding/Reconciliation.d.ts.map +1 -1
- package/dist/internal/funding/Reconciliation.js +42 -10
- package/dist/internal/funding/Reconciliation.js.map +1 -1
- package/dist/internal/funding/index.d.ts +1 -0
- package/dist/internal/funding/index.d.ts.map +1 -1
- package/dist/internal/funding/index.js +1 -0
- package/dist/internal/funding/index.js.map +1 -1
- package/dist/internal/funding/providers/stargate.d.ts +19 -0
- package/dist/internal/funding/providers/stargate.d.ts.map +1 -0
- package/dist/internal/funding/providers/stargate.js +143 -0
- package/dist/internal/funding/providers/stargate.js.map +1 -0
- package/dist/internal/webhookDestinations/slack.d.ts.map +1 -1
- package/dist/internal/webhookDestinations/slack.js +16 -0
- package/dist/internal/webhookDestinations/slack.js.map +1 -1
- package/dist/providers/index.d.ts +7 -0
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +3 -0
- package/dist/providers/index.js.map +1 -1
- package/package.json +2 -2
- package/src/App.test.ts +48 -0
- package/src/App.ts +7 -2
- package/src/Assets.test.ts +18 -0
- package/src/Assets.ts +22 -0
- package/src/Client.test-d.ts +287 -17
- package/src/Webhooks.ts +1 -220
- package/src/admin/apps/earn-vaults.test.ts +143 -0
- package/src/admin/apps/earn-vaults.ts +83 -6
- package/src/admin/apps/organizations.ts +6 -2
- package/src/admin/ui/src/routes/api-keys.tsx +36 -0
- package/src/admin/ui.generated.ts +151 -189
- package/src/apps/data/App.test.ts +31 -0
- package/src/apps/data/App.ts +64 -10
- package/src/apps/data/ZoneSelection.test.ts +196 -0
- package/src/apps/data/ZoneSelection.ts +108 -0
- package/src/apps/data/routes/activities.test.ts +435 -12
- package/src/apps/data/routes/activities.ts +562 -125
- package/src/apps/data/routes/balances.ts +1 -1
- package/src/apps/data/routes/blocks.ts +1 -1
- package/src/apps/data/routes/earn.test.ts +183 -23
- package/src/apps/data/routes/earn.ts +225 -29
- package/src/apps/data/routes/earn.zone-access.test.ts +46 -0
- package/src/apps/data/routes/exchanges.test.ts +31 -1
- package/src/apps/data/routes/exchanges.ts +19 -15
- package/src/apps/data/routes/fee-amm.ts +18 -11
- package/src/apps/data/routes/receipts.ts +1 -1
- package/src/apps/data/routes/rpc.test.ts +75 -0
- package/src/apps/data/routes/rpc.ts +23 -9
- package/src/apps/data/routes/tokenlist.ts +21 -18
- package/src/apps/data/routes/tokens.test.ts +29 -0
- package/src/apps/data/routes/tokens.ts +38 -15
- package/src/apps/data/routes/transactions.ts +1 -1
- package/src/apps/data/routes/transfers.test.ts +3 -3
- package/src/apps/data/routes/transfers.ts +12 -9
- package/src/apps/data/routes/webhooks.test.ts +179 -1497
- package/src/apps/data/routes/webhooks.ts +156 -976
- package/src/apps/data/routes/zones.test.ts +19 -13
- package/src/apps/funding/routes/chains.test.ts +211 -7
- package/src/apps/funding/routes/chains.ts +19 -12
- package/src/apps/funding/routes/deposit-addresses.test.ts +394 -0
- package/src/apps/funding/routes/deposit-addresses.ts +84 -72
- package/src/apps/funding/routes/providers.ts +9 -5
- package/src/apps/funding/routes/quotes.test.ts +46 -0
- package/src/apps/funding/routes/quotes.ts +8 -5
- package/src/apps/funding/routes/transfers.test.ts +35 -32
- package/src/apps/management/Billing.test.ts +26 -0
- package/src/apps/management/Billing.ts +24 -7
- package/src/apps/management/routes/api-keys.test.ts +178 -0
- package/src/apps/management/routes/api-keys.ts +203 -144
- package/src/apps/management/routes/billing.test.ts +209 -0
- package/src/apps/management/routes/billing.ts +254 -177
- package/src/apps/management/routes/faucet.test.ts +39 -0
- package/src/apps/management/routes/faucet.ts +75 -41
- package/src/apps/management/routes/invitations.test.ts +216 -0
- package/src/apps/management/routes/invitations.ts +186 -109
- package/src/apps/management/routes/invite-links.test.ts +263 -1
- package/src/apps/management/routes/invite-links.ts +295 -214
- package/src/apps/management/routes/me.test.ts +49 -0
- package/src/apps/management/routes/me.ts +42 -32
- package/src/apps/management/routes/members.test.ts +124 -1
- package/src/apps/management/routes/members.ts +81 -51
- package/src/apps/management/routes/orgs.test.ts +176 -0
- package/src/apps/management/routes/orgs.ts +101 -59
- package/src/apps/management/routes/projects.test.ts +183 -0
- package/src/apps/management/routes/projects.ts +124 -60
- package/src/apps/management/routes/scopes.test.ts +44 -0
- package/src/apps/management/routes/scopes.ts +37 -28
- package/src/apps/management/routes/usage.test.ts +92 -0
- package/src/apps/management/routes/usage.ts +186 -151
- package/src/apps/management/routes/verified-token-requests.test.ts +114 -0
- package/src/apps/management/routes/verified-token-requests.ts +166 -133
- package/src/apps/management/routes/webhooks.test.ts +313 -1
- package/src/apps/management/routes/webhooks.ts +220 -71
- package/src/apps/mpp/internal/Adapter.ts +13 -1
- package/src/db/Db.test.ts +42 -5
- package/src/db/Db.ts +85 -0
- package/src/db/Schema.ts +41 -3
- package/src/db/tables/earnVaults.test.ts +22 -0
- package/src/db/tables/earnVaults.ts +11 -1
- package/src/db/tables/organizations.test.ts +5 -2
- package/src/db/tables/webhookDeliveries.ts +13 -0
- package/src/db/tables/webhookQueueCompletions.ts +55 -0
- package/src/db/tables/webhookQueueEvents.ts +97 -57
- package/src/db/tables/webhookSubscriptions.ts +134 -144
- package/src/internal/Auth.ts +23 -5
- package/src/internal/Cache.ts +14 -7
- package/src/internal/EarnVaults.capabilities.test.ts +33 -0
- package/src/internal/EarnVaults.test.ts +79 -0
- package/src/internal/EarnVaults.ts +277 -0
- package/src/internal/MetricSink.test.ts +41 -373
- package/src/internal/MetricSink.ts +92 -273
- package/src/internal/OpenApi.ts +165 -49
- package/src/internal/Response.test.ts +95 -0
- package/src/internal/Response.ts +40 -2
- package/src/internal/Schema.test.ts +34 -0
- package/src/internal/Schema.ts +20 -9
- package/src/internal/Store.test.ts +186 -0
- package/src/internal/Store.ts +57 -17
- package/src/internal/Tidx.test.ts +19 -0
- package/src/internal/Tidx.ts +16 -4
- package/src/internal/WebhookTransfer.ts +1 -351
- package/src/internal/Webhooks.test.ts +222 -145
- package/src/internal/Webhooks.ts +234 -135
- package/src/internal/funding/Deposit.ts +71 -64
- package/src/internal/funding/DepositAddress.ts +50 -43
- package/src/internal/funding/DepositWebhook.test.ts +131 -0
- package/src/internal/funding/DepositWebhook.ts +101 -0
- package/src/internal/funding/Provider.ts +164 -142
- package/src/internal/funding/Reconciliation.test.ts +14 -0
- package/src/internal/funding/Reconciliation.ts +161 -86
- package/src/internal/funding/index.test.ts +1 -0
- package/src/internal/funding/index.ts +1 -0
- package/src/internal/funding/providers/index.test.ts +185 -0
- package/src/internal/funding/providers/stargate.ts +184 -0
- package/src/internal/webhookDestinations/slack.ts +15 -0
- package/src/providers/index.test.ts +1 -0
- package/src/providers/index.ts +9 -0
- package/src/Webhooks.bench.ts +0 -714
- package/src/Webhooks.memory.bench.ts +0 -250
- package/src/Webhooks.test.ts +0 -146
|
@@ -304,44 +304,6 @@ describe('updateSubscription', () => {
|
|
|
304
304
|
})
|
|
305
305
|
})
|
|
306
306
|
|
|
307
|
-
describe('listActive', () => {
|
|
308
|
-
test('returns only active subscriptions for a stream', async () => {
|
|
309
|
-
const db = TestApp.database()
|
|
310
|
-
const a = await Webhooks.createSubscription(db, createInput())
|
|
311
|
-
const b = await Webhooks.createSubscription(db, createInput({ owner: mppOwner }))
|
|
312
|
-
await Webhooks.createSubscription(db, createInput({ eventType: 'transaction:included' }))
|
|
313
|
-
|
|
314
|
-
let active = await Webhooks.listActive(db, 4217, 'token:transfer')
|
|
315
|
-
expect(active.map((s) => s.id).sort()).toEqual([a.id, b.id].sort())
|
|
316
|
-
|
|
317
|
-
await Webhooks.updateSubscription(db, apiKeyOwner, a.id, { status: 'paused' })
|
|
318
|
-
active = await Webhooks.listActive(db, 4217, 'token:transfer')
|
|
319
|
-
expect(active.map((s) => s.id)).toEqual([b.id])
|
|
320
|
-
})
|
|
321
|
-
|
|
322
|
-
test('drops a deleted subscription from the index', async () => {
|
|
323
|
-
const db = TestApp.database()
|
|
324
|
-
const a = await Webhooks.createSubscription(db, createInput())
|
|
325
|
-
|
|
326
|
-
await Webhooks.deleteSubscription(db, apiKeyOwner, a.id)
|
|
327
|
-
expect(await Webhooks.listActive(db, 4217, 'token:transfer')).toMatchInlineSnapshot(`[]`)
|
|
328
|
-
})
|
|
329
|
-
})
|
|
330
|
-
|
|
331
|
-
describe('listActiveWithCursors', () => {
|
|
332
|
-
test('pairs each subscription with its stored cursor from one read', async () => {
|
|
333
|
-
const db = TestApp.database()
|
|
334
|
-
const anchored = await Webhooks.createSubscription(db, createInput())
|
|
335
|
-
const fresh = await Webhooks.createSubscription(db, createInput({ owner: mppOwner }))
|
|
336
|
-
await Webhooks.setCursor(db, anchored.id, Cursor.encode([100, 5]))
|
|
337
|
-
|
|
338
|
-
const pairs = await Webhooks.listActiveWithCursors(db, 4217, 'token:transfer')
|
|
339
|
-
const byId = new Map(pairs.map((pair) => [pair.subscription.id, pair.cursor]))
|
|
340
|
-
expect(Cursor.decode(byId.get(anchored.id)!, ['int', 'int'])).toEqual([100, 5])
|
|
341
|
-
expect(byId.get(fresh.id)).toBeNull()
|
|
342
|
-
})
|
|
343
|
-
})
|
|
344
|
-
|
|
345
307
|
describe('listActiveForChain', () => {
|
|
346
308
|
test('returns active subscriptions across event types in one read', async () => {
|
|
347
309
|
const db = TestApp.database()
|
|
@@ -365,102 +327,6 @@ describe('listActiveForChain', () => {
|
|
|
365
327
|
})
|
|
366
328
|
})
|
|
367
329
|
|
|
368
|
-
describe('maxCursorBlock', () => {
|
|
369
|
-
test('returns the freshest cursor block across event types', async () => {
|
|
370
|
-
const db = TestApp.database()
|
|
371
|
-
const transfer = await Webhooks.createSubscription(db, createInput())
|
|
372
|
-
const tx = await Webhooks.createSubscription(
|
|
373
|
-
db,
|
|
374
|
-
createInput({ eventType: 'transaction:included' }),
|
|
375
|
-
)
|
|
376
|
-
await Webhooks.setCursor(db, transfer.id, Cursor.encode([100, 5]))
|
|
377
|
-
await Webhooks.setCursor(db, tx.id, Cursor.encode([250, 0]))
|
|
378
|
-
|
|
379
|
-
expect(await Webhooks.maxCursorBlock(db, 4217)).toBe(250)
|
|
380
|
-
})
|
|
381
|
-
|
|
382
|
-
test('counts creation checkpoints at their recorded head', async () => {
|
|
383
|
-
const db = TestApp.database()
|
|
384
|
-
await Webhooks.createSubscription(db, createInput(), { startBlockNumber: 900 })
|
|
385
|
-
|
|
386
|
-
expect(await Webhooks.maxCursorBlock(db, 4217)).toBe(900)
|
|
387
|
-
})
|
|
388
|
-
|
|
389
|
-
test('ignores other chains and returns null without cursors', async () => {
|
|
390
|
-
const db = TestApp.database()
|
|
391
|
-
expect(await Webhooks.maxCursorBlock(db, 4217)).toBeNull()
|
|
392
|
-
|
|
393
|
-
const other = await Webhooks.createSubscription(db, createInput({ chainId: 42431 }))
|
|
394
|
-
await Webhooks.setCursor(db, other.id, Cursor.encode([999, 0]))
|
|
395
|
-
// A cursorless subscription on the queried chain still reads as null.
|
|
396
|
-
await Webhooks.createSubscription(db, createInput())
|
|
397
|
-
|
|
398
|
-
expect(await Webhooks.maxCursorBlock(db, 4217)).toBeNull()
|
|
399
|
-
expect(await Webhooks.maxCursorBlock(db, 42431)).toBe(999)
|
|
400
|
-
})
|
|
401
|
-
})
|
|
402
|
-
|
|
403
|
-
describe('cursors', () => {
|
|
404
|
-
test('round-trips a per-subscription cursor', async () => {
|
|
405
|
-
const db = TestApp.database()
|
|
406
|
-
// The cursor is a column on the subscription row, so it needs a real
|
|
407
|
-
// subscription (the old key space allowed orphan cursors).
|
|
408
|
-
const created = await Webhooks.createSubscription(db, createInput())
|
|
409
|
-
expect(await Webhooks.getCursor(db, created.id)).toMatchInlineSnapshot(`null`)
|
|
410
|
-
|
|
411
|
-
await Webhooks.setCursor(db, created.id, '12345:7')
|
|
412
|
-
expect(await Webhooks.getCursor(db, created.id)).toMatchInlineSnapshot(`"12345:7"`)
|
|
413
|
-
})
|
|
414
|
-
|
|
415
|
-
test('atomically rejects a stale cursor write', async () => {
|
|
416
|
-
const db = TestApp.database()
|
|
417
|
-
const created = await Webhooks.createSubscription(db, createInput())
|
|
418
|
-
const a = Cursor.encode([100, 1])
|
|
419
|
-
const b = Cursor.encode([100, 2])
|
|
420
|
-
const results = await Promise.all([
|
|
421
|
-
Webhooks.compareAndSetCursor(db, {
|
|
422
|
-
cursor: a,
|
|
423
|
-
expectedCursor: null,
|
|
424
|
-
subscriptionId: created.id,
|
|
425
|
-
}),
|
|
426
|
-
Webhooks.compareAndSetCursor(db, {
|
|
427
|
-
cursor: b,
|
|
428
|
-
expectedCursor: null,
|
|
429
|
-
subscriptionId: created.id,
|
|
430
|
-
}),
|
|
431
|
-
])
|
|
432
|
-
|
|
433
|
-
expect(results.toSorted((a, b) => Number(a) - Number(b))).toEqual([false, true])
|
|
434
|
-
expect([a, b]).toContain(await Webhooks.getCursor(db, created.id))
|
|
435
|
-
})
|
|
436
|
-
})
|
|
437
|
-
|
|
438
|
-
describe('compareAndSetCursors', () => {
|
|
439
|
-
test('atomically advances a batch and reports stale rows', async () => {
|
|
440
|
-
const db = TestApp.database()
|
|
441
|
-
const initialized = await Webhooks.createSubscription(db, createInput())
|
|
442
|
-
const stale = await Webhooks.createSubscription(db, createInput())
|
|
443
|
-
const uninitialized = await Webhooks.createSubscription(db, createInput())
|
|
444
|
-
const initial = Cursor.encode([100, 1])
|
|
445
|
-
const next = Cursor.encode([101, 1])
|
|
446
|
-
await Webhooks.setCursor(db, initialized.id, initial)
|
|
447
|
-
await Webhooks.setCursor(db, stale.id, initial)
|
|
448
|
-
|
|
449
|
-
const committed = await Webhooks.compareAndSetCursors(db, {
|
|
450
|
-
cursors: [
|
|
451
|
-
{ cursor: next, expectedCursor: initial, subscriptionId: initialized.id },
|
|
452
|
-
{ cursor: next, expectedCursor: null, subscriptionId: stale.id },
|
|
453
|
-
{ cursor: next, expectedCursor: null, subscriptionId: uninitialized.id },
|
|
454
|
-
],
|
|
455
|
-
})
|
|
456
|
-
|
|
457
|
-
expect([...committed].toSorted()).toEqual([initialized.id, uninitialized.id].toSorted())
|
|
458
|
-
expect(await Webhooks.getCursor(db, initialized.id)).toBe(next)
|
|
459
|
-
expect(await Webhooks.getCursor(db, stale.id)).toBe(initial)
|
|
460
|
-
expect(await Webhooks.getCursor(db, uninitialized.id)).toBe(next)
|
|
461
|
-
})
|
|
462
|
-
})
|
|
463
|
-
|
|
464
330
|
describe('recordSuccess / recordFailure', () => {
|
|
465
331
|
test('recordSuccess resets failures and stamps lastDeliveryAt', async () => {
|
|
466
332
|
const db = TestApp.database()
|
|
@@ -482,6 +348,41 @@ describe('recordSuccess / recordFailure', () => {
|
|
|
482
348
|
expect(read?.lastDeliveryAt).toBe('2026-01-01T00:00:00.000Z')
|
|
483
349
|
})
|
|
484
350
|
|
|
351
|
+
test('recordSuccess refreshes the stamp at most once per precision window', async () => {
|
|
352
|
+
const db = TestApp.database()
|
|
353
|
+
const created = await Webhooks.createSubscription(db, createInput())
|
|
354
|
+
const stamped = await Webhooks.recordSuccess(db, created, { now: fixedNow })
|
|
355
|
+
expect(stamped.lastDeliveryAt).toBe(fixedNow().toISOString())
|
|
356
|
+
|
|
357
|
+
// A success moments later has nothing to move: the counter is already zero
|
|
358
|
+
// and the stamp is inside its window, so the row is never rewritten.
|
|
359
|
+
const soon = new Date(fixedNow().getTime() + 1_000)
|
|
360
|
+
await Webhooks.recordSuccess(db, stamped, { now: () => soon })
|
|
361
|
+
const unmoved = await Webhooks.getSubscription(db, apiKeyOwner, created.id)
|
|
362
|
+
expect(unmoved?.lastDeliveryAt, 'the stored stamp must not move').toBe(fixedNow().toISOString())
|
|
363
|
+
|
|
364
|
+
// Past any plausible window; the exact bound is internal.
|
|
365
|
+
const later = new Date(fixedNow().getTime() + 3_600_000)
|
|
366
|
+
await Webhooks.recordSuccess(db, stamped, { now: () => later })
|
|
367
|
+
const moved = await Webhooks.getSubscription(db, apiKeyOwner, created.id)
|
|
368
|
+
expect(moved?.lastDeliveryAt).toBe(later.toISOString())
|
|
369
|
+
})
|
|
370
|
+
|
|
371
|
+
test('recordSuccess always resets a non-zero failure counter', async () => {
|
|
372
|
+
const db = TestApp.database()
|
|
373
|
+
const created = await Webhooks.createSubscription(db, createInput())
|
|
374
|
+
// Stamp first, so only the counter is out of date: the reset must not be
|
|
375
|
+
// suppressed by a fresh stamp.
|
|
376
|
+
const stamped = await Webhooks.recordSuccess(db, created, { now: fixedNow })
|
|
377
|
+
const failed = await Webhooks.recordFailure(db, stamped, { now: fixedNow })
|
|
378
|
+
expect(failed.failureCount).toBe(1)
|
|
379
|
+
|
|
380
|
+
await Webhooks.recordSuccess(db, failed, { now: fixedNow })
|
|
381
|
+
|
|
382
|
+
const read = await Webhooks.getSubscription(db, apiKeyOwner, created.id)
|
|
383
|
+
expect(read?.failureCount, 'a pending reset must never be skipped').toBe(0)
|
|
384
|
+
})
|
|
385
|
+
|
|
485
386
|
test('recordFailure auto-disables at the threshold and drops from the active index', async () => {
|
|
486
387
|
const db = TestApp.database()
|
|
487
388
|
let subscription = await Webhooks.createSubscription(db, createInput())
|
|
@@ -490,11 +391,13 @@ describe('recordSuccess / recordFailure', () => {
|
|
|
490
391
|
subscription = await Webhooks.recordFailure(db, subscription, { maxFailures: 3 })
|
|
491
392
|
subscription = await Webhooks.recordFailure(db, subscription, { maxFailures: 3 })
|
|
492
393
|
expect(subscription.status).toMatchInlineSnapshot(`"active"`)
|
|
493
|
-
expect(
|
|
494
|
-
|
|
495
|
-
|
|
394
|
+
expect(
|
|
395
|
+
(
|
|
396
|
+
await Webhooks.listActiveForChain(db, { chainId: 4217, eventTypes: ['token:transfer'] })
|
|
397
|
+
).map((pair) => pair.subscription.id),
|
|
398
|
+
).toEqual([subscription.id])
|
|
496
399
|
|
|
497
|
-
// Hitting the threshold disables it and removes it from the
|
|
400
|
+
// Hitting the threshold disables it and removes it from the active index.
|
|
498
401
|
subscription = await Webhooks.recordFailure(db, subscription, { maxFailures: 3 })
|
|
499
402
|
expect({ failureCount: subscription.failureCount, status: subscription.status })
|
|
500
403
|
.toMatchInlineSnapshot(`
|
|
@@ -503,7 +406,40 @@ describe('recordSuccess / recordFailure', () => {
|
|
|
503
406
|
"status": "disabled",
|
|
504
407
|
}
|
|
505
408
|
`)
|
|
506
|
-
expect(
|
|
409
|
+
expect(
|
|
410
|
+
await Webhooks.listActiveForChain(db, { chainId: 4217, eventTypes: ['token:transfer'] }),
|
|
411
|
+
).toMatchInlineSnapshot(`[]`)
|
|
412
|
+
})
|
|
413
|
+
|
|
414
|
+
test('recordFailure leaves an already-disabled subscription alone at the cap', async () => {
|
|
415
|
+
const db = TestApp.database()
|
|
416
|
+
let subscription = await Webhooks.createSubscription(db, createInput())
|
|
417
|
+
subscription = await Webhooks.recordFailure(db, subscription, { maxFailures: 2, now: fixedNow })
|
|
418
|
+
subscription = await Webhooks.recordFailure(db, subscription, { maxFailures: 2, now: fixedNow })
|
|
419
|
+
expect(subscription.status).toBe('disabled')
|
|
420
|
+
|
|
421
|
+
// A straggler failing after the disable has nothing to move: the row is
|
|
422
|
+
// never rewritten.
|
|
423
|
+
const later = new Date(fixedNow().getTime() + 1_000)
|
|
424
|
+
await Webhooks.recordFailure(db, subscription, { maxFailures: 2, now: () => later })
|
|
425
|
+
|
|
426
|
+
const read = await Webhooks.getSubscription(db, apiKeyOwner, subscription.id)
|
|
427
|
+
expect(read?.failureCount, 'the stored counter must not move').toBe(2)
|
|
428
|
+
expect(read?.updatedAt, 'the stored stamp must not move').toBe(fixedNow().toISOString())
|
|
429
|
+
})
|
|
430
|
+
|
|
431
|
+
test('recordFailure re-disables a re-enabled subscription still at the cap', async () => {
|
|
432
|
+
const db = TestApp.database()
|
|
433
|
+
let subscription = await Webhooks.createSubscription(db, createInput())
|
|
434
|
+
subscription = await Webhooks.recordFailure(db, subscription, { maxFailures: 1, now: fixedNow })
|
|
435
|
+
expect(subscription.status).toBe('disabled')
|
|
436
|
+
|
|
437
|
+
await Webhooks.updateSubscription(db, apiKeyOwner, subscription.id, { status: 'active' })
|
|
438
|
+
|
|
439
|
+
// The counter still sits at the cap, so this failure must write again.
|
|
440
|
+
await Webhooks.recordFailure(db, subscription, { maxFailures: 1, now: fixedNow })
|
|
441
|
+
const read = await Webhooks.getSubscription(db, apiKeyOwner, subscription.id)
|
|
442
|
+
expect(read?.status).toBe('disabled')
|
|
507
443
|
})
|
|
508
444
|
})
|
|
509
445
|
|
|
@@ -1014,6 +950,72 @@ describe('ensureQueueEvents', () => {
|
|
|
1014
950
|
expect(histograms.has('webhook_delivery_subscription_read_ms')).toBe(true)
|
|
1015
951
|
})
|
|
1016
952
|
|
|
953
|
+
test('measures observation to attempt from the staged head stamp', async () => {
|
|
954
|
+
const db = TestApp.database()
|
|
955
|
+
const subscription = await Webhooks.createSubscription(
|
|
956
|
+
db,
|
|
957
|
+
createInput({ eventType: 'transaction:included' }),
|
|
958
|
+
)
|
|
959
|
+
const envelope = Webhooks.buildEnvelope({
|
|
960
|
+
blockNumber: 123,
|
|
961
|
+
data: {},
|
|
962
|
+
logIndex: 4,
|
|
963
|
+
subscription,
|
|
964
|
+
})
|
|
965
|
+
const observedAt = Date.now() - 5_000
|
|
966
|
+
const { references: [reference] } = await Webhooks.ensureQueueEvents(db, [{ envelope, subscription }], { observedAt }) // prettier-ignore
|
|
967
|
+
const histograms = new Map<string, number>()
|
|
968
|
+
const metrics = Metrics.from({
|
|
969
|
+
count() {},
|
|
970
|
+
flush() {},
|
|
971
|
+
gauge() {},
|
|
972
|
+
histogram(name, value) {
|
|
973
|
+
histograms.set(name, value)
|
|
974
|
+
},
|
|
975
|
+
})
|
|
976
|
+
const fetch = (async () => new Response(null, { status: 200 })) satisfies typeof globalThis.fetch // prettier-ignore
|
|
977
|
+
|
|
978
|
+
const result = await Webhooks.deliverQueueEventAndRecord(db, reference!, { fetch, metrics })
|
|
979
|
+
|
|
980
|
+
expect(result.status).toBe('delivered')
|
|
981
|
+
// Measured from the head stamp, so it covers the whole controllable span
|
|
982
|
+
// rather than only the time since this worker dequeued the message.
|
|
983
|
+
expect(histograms.get('webhook_observed_to_attempt_ms')).toBeGreaterThanOrEqual(5_000)
|
|
984
|
+
expect(histograms.has('webhook_delivery_preflight_ms')).toBe(true)
|
|
985
|
+
expect(histograms.has('webhook_delivery_settle_ms')).toBe(true)
|
|
986
|
+
})
|
|
987
|
+
|
|
988
|
+
test('omits observation timing for a replay with no staged head stamp', async () => {
|
|
989
|
+
const db = TestApp.database()
|
|
990
|
+
const subscription = await Webhooks.createSubscription(
|
|
991
|
+
db,
|
|
992
|
+
createInput({ eventType: 'transaction:included' }),
|
|
993
|
+
)
|
|
994
|
+
const envelope = Webhooks.buildEnvelope({
|
|
995
|
+
blockNumber: 124,
|
|
996
|
+
data: {},
|
|
997
|
+
logIndex: 4,
|
|
998
|
+
subscription,
|
|
999
|
+
})
|
|
1000
|
+
const { references: [reference] } = await Webhooks.ensureQueueEvents(db, [{ envelope, subscription }]) // prettier-ignore
|
|
1001
|
+
const histograms = new Map<string, number>()
|
|
1002
|
+
const metrics = Metrics.from({
|
|
1003
|
+
count() {},
|
|
1004
|
+
flush() {},
|
|
1005
|
+
gauge() {},
|
|
1006
|
+
histogram(name, value) {
|
|
1007
|
+
histograms.set(name, value)
|
|
1008
|
+
},
|
|
1009
|
+
})
|
|
1010
|
+
const fetch = (async () => new Response(null, { status: 200 })) satisfies typeof globalThis.fetch // prettier-ignore
|
|
1011
|
+
|
|
1012
|
+
await Webhooks.deliverQueueEventAndRecord(db, reference!, { fetch, metrics })
|
|
1013
|
+
|
|
1014
|
+
// Absent rather than zero: a replay is unattributable, not instant.
|
|
1015
|
+
expect(histograms.has('webhook_observed_to_attempt_ms')).toBe(false)
|
|
1016
|
+
expect(histograms.has('webhook_event_to_attempt_ms')).toBe(true)
|
|
1017
|
+
})
|
|
1018
|
+
|
|
1017
1019
|
test('skips a staged event after its subscription expires', async () => {
|
|
1018
1020
|
vi.useFakeTimers({ now: fixedNow(), toFake: ['Date'] })
|
|
1019
1021
|
try {
|
|
@@ -1079,7 +1081,7 @@ describe('ensureQueueEvents', () => {
|
|
|
1079
1081
|
expect(await Webhooks.getQueueEvent(db, reference)).toBeNull()
|
|
1080
1082
|
})
|
|
1081
1083
|
|
|
1082
|
-
test('
|
|
1084
|
+
test('stages a replay once its completion has expired', async () => {
|
|
1083
1085
|
vi.useFakeTimers({ toFake: ['Date'] })
|
|
1084
1086
|
vi.setSystemTime(fixedNow())
|
|
1085
1087
|
try {
|
|
@@ -1095,9 +1097,9 @@ describe('ensureQueueEvents', () => {
|
|
|
1095
1097
|
}),
|
|
1096
1098
|
).toBe(true)
|
|
1097
1099
|
|
|
1098
|
-
// Past the dedupe window an unpruned
|
|
1100
|
+
// Past the dedupe window an unpruned completion must not suppress a
|
|
1099
1101
|
// replay.
|
|
1100
|
-
vi.setSystemTime(new Date(fixedNow().getTime() + Webhooks.
|
|
1102
|
+
vi.setSystemTime(new Date(fixedNow().getTime() + Webhooks.dedupeRetentionMs + 1_000))
|
|
1101
1103
|
const replay = await Webhooks.ensureQueueEvents(db, [{ envelope, subscription }])
|
|
1102
1104
|
expect(replay.created).toBe(1)
|
|
1103
1105
|
await expect(Webhooks.claimQueueEvent(db, reference)).resolves.toMatchObject({
|
|
@@ -1107,6 +1109,65 @@ describe('ensureQueueEvents', () => {
|
|
|
1107
1109
|
vi.useRealTimers()
|
|
1108
1110
|
}
|
|
1109
1111
|
})
|
|
1112
|
+
|
|
1113
|
+
test('stamps a fresh observation on a post-expiry replay', async () => {
|
|
1114
|
+
vi.useFakeTimers({ toFake: ['Date'] })
|
|
1115
|
+
vi.setSystemTime(fixedNow())
|
|
1116
|
+
try {
|
|
1117
|
+
const db = TestApp.database()
|
|
1118
|
+
const { envelope, reference, subscription } = await stagedObligation(db)
|
|
1119
|
+
const claim = await Webhooks.claimQueueEvent(db, reference)
|
|
1120
|
+
if (claim.type !== 'claimed') throw new Error(`Unexpected claim: ${claim.type}`)
|
|
1121
|
+
await Webhooks.completeQueueEvent(db, reference, {
|
|
1122
|
+
claimedAt: claim.record.attemptingAt!,
|
|
1123
|
+
status: 'succeeded',
|
|
1124
|
+
})
|
|
1125
|
+
|
|
1126
|
+
vi.setSystemTime(new Date(fixedNow().getTime() + Webhooks.dedupeRetentionMs + 1_000))
|
|
1127
|
+
const observedAt = Date.now() - 250
|
|
1128
|
+
await Webhooks.ensureQueueEvents(db, [{ envelope, subscription }], { observedAt })
|
|
1129
|
+
|
|
1130
|
+
// Carrying the replaced row's stamp would measure this delivery against
|
|
1131
|
+
// an observation from the retention window before it.
|
|
1132
|
+
const replayed = await Webhooks.claimQueueEvent(db, reference)
|
|
1133
|
+
if (replayed.type !== 'claimed') throw new Error(`Unexpected claim: ${replayed.type}`)
|
|
1134
|
+
expect(replayed.record.observedAt).toBe(new Date(observedAt).toISOString())
|
|
1135
|
+
} finally {
|
|
1136
|
+
vi.useRealTimers()
|
|
1137
|
+
}
|
|
1138
|
+
})
|
|
1139
|
+
|
|
1140
|
+
test('suppresses only the completed obligation when staging a mixed batch', async () => {
|
|
1141
|
+
const db = TestApp.database()
|
|
1142
|
+
const done = await stagedObligation(db, 4)
|
|
1143
|
+
const claim = await Webhooks.claimQueueEvent(db, done.reference)
|
|
1144
|
+
if (claim.type !== 'claimed') throw new Error(`Unexpected claim: ${claim.type}`)
|
|
1145
|
+
await Webhooks.completeQueueEvent(db, done.reference, {
|
|
1146
|
+
claimedAt: claim.record.attemptingAt!,
|
|
1147
|
+
status: 'failed',
|
|
1148
|
+
})
|
|
1149
|
+
|
|
1150
|
+
const fresh = Webhooks.buildEnvelope({
|
|
1151
|
+
blockNumber: 124,
|
|
1152
|
+
createdAt: new Date(),
|
|
1153
|
+
data: { amount: '1' },
|
|
1154
|
+
logIndex: 5,
|
|
1155
|
+
subscription: done.subscription,
|
|
1156
|
+
})
|
|
1157
|
+
const batch = await Webhooks.ensureQueueEvents(db, [
|
|
1158
|
+
{ envelope: done.envelope, subscription: done.subscription },
|
|
1159
|
+
{ envelope: fresh, subscription: done.subscription },
|
|
1160
|
+
])
|
|
1161
|
+
|
|
1162
|
+
expect(batch.created).toBe(1)
|
|
1163
|
+
await expect(Webhooks.claimQueueEvent(db, done.reference)).resolves.toEqual({
|
|
1164
|
+
status: 'failed',
|
|
1165
|
+
type: 'terminal',
|
|
1166
|
+
})
|
|
1167
|
+
await expect(Webhooks.claimQueueEvent(db, batch.references[1]!)).resolves.toMatchObject({
|
|
1168
|
+
type: 'claimed',
|
|
1169
|
+
})
|
|
1170
|
+
})
|
|
1110
1171
|
})
|
|
1111
1172
|
|
|
1112
1173
|
describe('claimQueueEvent', () => {
|
|
@@ -1119,6 +1180,22 @@ describe('claimQueueEvent', () => {
|
|
|
1119
1180
|
vi.useRealTimers()
|
|
1120
1181
|
})
|
|
1121
1182
|
|
|
1183
|
+
test('reads an expired completion as missing', async () => {
|
|
1184
|
+
const db = TestApp.database()
|
|
1185
|
+
const { reference } = await stagedObligation(db)
|
|
1186
|
+
const claim = await Webhooks.claimQueueEvent(db, reference)
|
|
1187
|
+
if (claim.type !== 'claimed') throw new Error(`Unexpected claim: ${claim.type}`)
|
|
1188
|
+
await Webhooks.completeQueueEvent(db, reference, {
|
|
1189
|
+
claimedAt: claim.record.attemptingAt!,
|
|
1190
|
+
status: 'succeeded',
|
|
1191
|
+
})
|
|
1192
|
+
|
|
1193
|
+
// Matches a pruned terminal row: past the dedupe window the completion is
|
|
1194
|
+
// invisible everywhere, not only to staging.
|
|
1195
|
+
vi.setSystemTime(new Date(fixedNow().getTime() + Webhooks.dedupeRetentionMs + 1_000))
|
|
1196
|
+
await expect(Webhooks.claimQueueEvent(db, reference)).resolves.toEqual({ type: 'missing' })
|
|
1197
|
+
})
|
|
1198
|
+
|
|
1122
1199
|
test('claims a due obligation once and reclaims after staleness', async () => {
|
|
1123
1200
|
const db = TestApp.database()
|
|
1124
1201
|
const { reference } = await stagedObligation(db)
|
|
@@ -1183,17 +1260,17 @@ describe('claimQueueEvent', () => {
|
|
|
1183
1260
|
|
|
1184
1261
|
// Pending obligations never expire; only terminal transitions stamp a
|
|
1185
1262
|
// dedupe deadline.
|
|
1186
|
-
vi.setSystemTime(new Date(fixedNow().getTime() + Webhooks.
|
|
1263
|
+
vi.setSystemTime(new Date(fixedNow().getTime() + Webhooks.dedupeRetentionMs * 3))
|
|
1187
1264
|
await expect(Webhooks.claimQueueEvent(db, reference)).resolves.toMatchObject({
|
|
1188
1265
|
type: 'claimed',
|
|
1189
1266
|
})
|
|
1190
1267
|
})
|
|
1191
1268
|
|
|
1192
|
-
test('
|
|
1269
|
+
test('leaves pending obligations claimable across a prune', async () => {
|
|
1193
1270
|
const db = TestApp.database()
|
|
1194
1271
|
const { reference } = await stagedObligation(db)
|
|
1195
1272
|
|
|
1196
|
-
vi.setSystemTime(new Date(fixedNow().getTime() + Webhooks.
|
|
1273
|
+
vi.setSystemTime(new Date(fixedNow().getTime() + Webhooks.dedupeRetentionMs + 1_000))
|
|
1197
1274
|
await Webhooks.pruneExpired(db)
|
|
1198
1275
|
const claim = await Webhooks.claimQueueEvent(db, reference)
|
|
1199
1276
|
expect(claim.type).toBe('claimed')
|