Allow retries of pessimistic actions
This commit is contained in:
parent
1f2b717da9
commit
be4ce5daf9
|
@ -304,14 +304,6 @@ export async function retryPaidAction (actionType, args, incomingContext) {
|
|||
throw new Error(`retryPaidAction - must be logged in ${actionType}`)
|
||||
}
|
||||
|
||||
if (!action.paymentMethods.includes(PAID_ACTION_PAYMENT_METHODS.OPTIMISTIC)) {
|
||||
throw new Error(`retryPaidAction - action does not support optimism ${actionType}`)
|
||||
}
|
||||
|
||||
if (!action.retry) {
|
||||
throw new Error(`retryPaidAction - action does not support retrying ${actionType}`)
|
||||
}
|
||||
|
||||
if (!failedInvoice) {
|
||||
throw new Error(`retryPaidAction - missing invoice ${actionType}`)
|
||||
}
|
||||
|
@ -319,7 +311,7 @@ export async function retryPaidAction (actionType, args, incomingContext) {
|
|||
const { msatsRequested, actionId, actionArgs } = failedInvoice
|
||||
const retryContext = {
|
||||
...incomingContext,
|
||||
optimistic: true,
|
||||
optimistic: failedInvoice.actionOptimistic,
|
||||
me: await models.user.findUnique({ where: { id: me.id } }),
|
||||
cost: BigInt(msatsRequested),
|
||||
actionId
|
||||
|
@ -345,7 +337,7 @@ export async function retryPaidAction (actionType, args, incomingContext) {
|
|||
const invoice = await createDbInvoice(actionType, actionArgs, context)
|
||||
|
||||
return {
|
||||
result: await action.retry({ invoiceId: failedInvoice.id, newInvoiceId: invoice.id }, context),
|
||||
result: await action.retry?.({ invoiceId: failedInvoice.id, newInvoiceId: invoice.id }, context),
|
||||
invoice,
|
||||
paymentMethod: 'OPTIMISTIC'
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ export const useQrPayment = () => {
|
|||
await invoice.cancel(inv).catch(console.error)
|
||||
reject(new InvoiceCanceledError(inv?.hash))
|
||||
}
|
||||
resolve()
|
||||
resolve(inv)
|
||||
}
|
||||
showModal(onClose =>
|
||||
<Invoice
|
||||
|
@ -99,7 +99,7 @@ export const useQrPayment = () => {
|
|||
waitFor={waitFor}
|
||||
onExpired={inv => reject(new InvoiceExpiredError(inv?.hash))}
|
||||
onCanceled={inv => { onClose(); reject(new InvoiceCanceledError(inv?.hash, inv?.actionError)) }}
|
||||
onPayment={() => { paid = true; onClose(); resolve() }}
|
||||
onPayment={() => { paid = true; onClose(); resolve(inv) }}
|
||||
poll
|
||||
/>,
|
||||
{ keepOpen, persistOnNavigate, onClose: cancelAndReject })
|
||||
|
|
|
@ -83,7 +83,7 @@ export function usePaidMutation (mutation,
|
|||
throw new Error('usePaidMutation: exactly one mutation at a time is supported')
|
||||
}
|
||||
const response = Object.values(data)[0]
|
||||
const invoice = response?.invoice
|
||||
let invoice = response?.invoice
|
||||
|
||||
// if the mutation returns an invoice, pay it
|
||||
if (invoice) {
|
||||
|
@ -113,7 +113,8 @@ export function usePaidMutation (mutation,
|
|||
// the action is pessimistic
|
||||
try {
|
||||
// wait for the invoice to be paid
|
||||
await waitForPayment(invoice, { alwaysShowQROnFailure: true, persistOnNavigate, waitFor })
|
||||
// returns the invoice that was paid since it might have been updated via retries
|
||||
invoice = await waitForPayment(invoice, { alwaysShowQROnFailure: true, persistOnNavigate, waitFor })
|
||||
if (!response.result) {
|
||||
// if the mutation didn't return any data, ie pessimistic, we need to fetch it
|
||||
const { data: { paidAction } } = await getPaidAction({ variables: { invoiceId: parseInt(invoice.id) } })
|
||||
|
|
|
@ -47,7 +47,7 @@ export function useWalletPayment () {
|
|||
let walletInvoice = invoice
|
||||
|
||||
for (const wallet of walletsWithPayments) {
|
||||
const controller = invoiceController(walletInvoice.id, invoiceHelper.isInvoice)
|
||||
const controller = invoiceController(walletInvoice, invoiceHelper.isInvoice)
|
||||
try {
|
||||
return await new Promise((resolve, reject) => {
|
||||
// can't await wallet payments since we might pay hold invoices and thus payments might not settle immediately.
|
||||
|
@ -102,20 +102,20 @@ export function useWalletPayment () {
|
|||
return waitForPayment
|
||||
}
|
||||
|
||||
const invoiceController = (id, isInvoice) => {
|
||||
const invoiceController = (inv, isInvoice) => {
|
||||
const controller = new AbortController()
|
||||
const signal = controller.signal
|
||||
controller.wait = async (waitFor = inv => inv?.actionState === 'PAID') => {
|
||||
return await new Promise((resolve, reject) => {
|
||||
const interval = setInterval(async () => {
|
||||
try {
|
||||
const paid = await isInvoice({ id }, waitFor)
|
||||
const paid = await isInvoice(inv, waitFor)
|
||||
if (paid) {
|
||||
resolve()
|
||||
resolve(inv)
|
||||
clearInterval(interval)
|
||||
signal.removeEventListener('abort', abort)
|
||||
} else {
|
||||
console.info(`invoice #${id}: waiting for payment ...`)
|
||||
console.info(`invoice #${inv.id}: waiting for payment ...`)
|
||||
}
|
||||
} catch (err) {
|
||||
reject(err)
|
||||
|
@ -125,8 +125,8 @@ const invoiceController = (id, isInvoice) => {
|
|||
}, FAST_POLL_INTERVAL)
|
||||
|
||||
const abort = () => {
|
||||
console.info(`invoice #${id}: stopped waiting`)
|
||||
resolve()
|
||||
console.info(`invoice #${inv.id}: stopped waiting`)
|
||||
resolve(inv)
|
||||
clearInterval(interval)
|
||||
signal.removeEventListener('abort', abort)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue