mirror of
https://github.com/tompro/sattle.git
synced 2026-10-26 01:49:58 +00:00
refactor(lnurlcash): generalize bounded polling beyond verify endpoints
pollVerifyUntilSettled keeps its exact behavior and messages, reimplemented on a generic pollUntil so flows that watch something other than a LUD-21 verify (a named mint output appearing) share the same backoff, budget and abort semantics.
This commit is contained in:
+33
-12
@@ -76,16 +76,17 @@ const abortableSleep = (ms: number, signal: AbortSignal): Promise<void> =>
|
|||||||
signal.addEventListener('abort', onAbort, {once: true})
|
signal.addEventListener('abort', onAbort, {once: true})
|
||||||
})
|
})
|
||||||
|
|
||||||
// polls a LUD-21/LUD-25 verify endpoint until it reports settled, with
|
// polls `check` until it yields a value, with backoff, inside a total
|
||||||
// backoff, inside a total time budget. A single failed check isn't fatal -
|
// time budget. A single failed check isn't fatal - the next round tries
|
||||||
// the next round tries again. Returns the settled VerifyResult; throws on
|
// again. Returns the first value; throws on budget exhaustion, or
|
||||||
// budget exhaustion, or PollAbortedError when the caller's signal fires
|
// PollAbortedError when the caller's signal fires (a hung fetch is
|
||||||
// (a hung fetch is interrupted too: the signal is bound into the request).
|
// interrupted too: the signal is bound into the request).
|
||||||
export const pollVerifyUntilSettled = async (
|
export const pollUntil = async <T>(
|
||||||
verifyUrl: string,
|
check: (options: LnurlcashOptions) => Promise<T | null>,
|
||||||
|
exhausted: string,
|
||||||
poll: PollOptions,
|
poll: PollOptions,
|
||||||
options: LnurlcashOptions,
|
options: LnurlcashOptions,
|
||||||
): Promise<VerifyResult> => {
|
): Promise<T> => {
|
||||||
const {intervalMs, intervalCapMs, maxWaitMs, signal} = {
|
const {intervalMs, intervalCapMs, maxWaitMs, signal} = {
|
||||||
...DEFAULT_POLL,
|
...DEFAULT_POLL,
|
||||||
...poll,
|
...poll,
|
||||||
@@ -105,8 +106,8 @@ export const pollVerifyUntilSettled = async (
|
|||||||
while (Date.now() < deadline) {
|
while (Date.now() < deadline) {
|
||||||
if (signal?.aborted) throw new PollAbortedError()
|
if (signal?.aborted) throw new PollAbortedError()
|
||||||
try {
|
try {
|
||||||
const result = await fetchInvoiceVerification(verifyUrl, fetchOptions)
|
const result = await check(fetchOptions)
|
||||||
if (result.settled) return result
|
if (result !== null) return result
|
||||||
lastError = null
|
lastError = null
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// the signal's own AbortError lands here on an interrupted fetch
|
// the signal's own AbortError lands here on an interrupted fetch
|
||||||
@@ -118,7 +119,27 @@ export const pollVerifyUntilSettled = async (
|
|||||||
delay = Math.min(delay * 2, intervalCapMs)
|
delay = Math.min(delay * 2, intervalCapMs)
|
||||||
}
|
}
|
||||||
if (lastError instanceof Error) {
|
if (lastError instanceof Error) {
|
||||||
throw new Error(`Payment not confirmed: ${lastError.message}`)
|
throw new Error(`${exhausted}: ${lastError.message}`)
|
||||||
}
|
}
|
||||||
throw new Error('Payment not confirmed within the time budget.')
|
throw new Error(`${exhausted} within the time budget.`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// polls a LUD-21/LUD-25 verify endpoint until it reports settled, with
|
||||||
|
// backoff, inside a total time budget. A single failed check isn't fatal -
|
||||||
|
// the next round tries again. Returns the settled VerifyResult; throws on
|
||||||
|
// budget exhaustion, or PollAbortedError when the caller's signal fires
|
||||||
|
// (a hung fetch is interrupted too: the signal is bound into the request).
|
||||||
|
export const pollVerifyUntilSettled = (
|
||||||
|
verifyUrl: string,
|
||||||
|
poll: PollOptions,
|
||||||
|
options: LnurlcashOptions,
|
||||||
|
): Promise<VerifyResult> =>
|
||||||
|
pollUntil(
|
||||||
|
async (fetchOptions) => {
|
||||||
|
const result = await fetchInvoiceVerification(verifyUrl, fetchOptions)
|
||||||
|
return result.settled ? result : null
|
||||||
|
},
|
||||||
|
'Payment not confirmed',
|
||||||
|
poll,
|
||||||
|
options,
|
||||||
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user