feat: parallelize zap retry execution

Optimize `executePendingRetry` in `js/channelProfile.js` to run zap attempts in parallel using `Promise.allSettled`, improving performance when retrying multiple shares.

Refactor `splitAndZap` in `js/payments/zapSplit.js` to accept `overrideFee` as an argument, eliminating reliance on a global variable and ensuring thread safety during parallel execution.

Update `js/ui/zapController.js` to use the new `splitAndZap` API.

Co-authored-by: PR0M3TH3AN <[email protected]>
This commit is contained in:
google-labs-jules[bot]andPR0M3TH3AN committed 2026-01-31 19:10:00 +00:00
1 parent b429b1c075
commit 19345e535e
3 files changed
+53 -65

No files matched your search

+40 -45
View File
@@ -2795,23 +2795,13 @@ async function runZapAttempt({ amount, overrideFee = null, walletSettings }) {
});
const videoEvent = getZapVideoEvent();
let previousOverride;
const hasGlobal = typeof globalThis !== "undefined";
if (
hasGlobal &&
typeof overrideFee === "number" &&
Number.isFinite(overrideFee)
) {
previousOverride = globalThis.__BITVID_PLATFORM_FEE_OVERRIDE__;
globalThis.__BITVID_PLATFORM_FEE_OVERRIDE__ = overrideFee;
}
try {
const result = await splitAndZap(
{
videoEvent,
amountSats: context.shares.total,
walletSettings: settings
walletSettings: settings,
overrideFee
},
dependencies
);
@@ -2832,21 +2822,6 @@ async function runZapAttempt({ amount, overrideFee = null, walletSettings }) {
error
);
throw error;
} finally {
if (
hasGlobal &&
typeof overrideFee === "number" &&
Number.isFinite(overrideFee)
) {
if (typeof previousOverride === "number") {
globalThis.__BITVID_PLATFORM_FEE_OVERRIDE__ = previousOverride;
} else if (
globalThis &&
"__BITVID_PLATFORM_FEE_OVERRIDE__" in globalThis
) {
delete globalThis.__BITVID_PLATFORM_FEE_OVERRIDE__;
}
}
}
}
@@ -2873,25 +2848,37 @@ async function executePendingRetry({ walletSettings }) {
const aggregatedReceipts = [];
const aggregatedTracker = [];
const nextRetryShares = [];
let lastError = null;
for (const share of shares) {
const overrideFee = share.type === "platform" ? 100 : 0;
try {
const attempt = await runZapAttempt({
const results = await Promise.allSettled(
shares.map((share) => {
const overrideFee = share.type === "platform" ? 100 : 0;
return runZapAttempt({
amount: share.amount,
overrideFee,
walletSettings
});
})
);
for (let i = 0; i < results.length; i++) {
const result = results[i];
const share = shares[i];
if (result.status === "fulfilled") {
const attempt = result.value;
if (!attempt) {
setZapStatus("", "neutral");
return;
continue;
}
if (attempt?.result?.receipts) {
aggregatedReceipts.push(...attempt.result.receipts);
} else if (Array.isArray(attempt?.shareTracker)) {
aggregatedTracker.push(...attempt.shareTracker);
}
} catch (error) {
} else {
const error = result.reason;
lastError = error;
const tracker = Array.isArray(error?.__zapShareTracker)
? error.__zapShareTracker
: [];
@@ -2912,20 +2899,28 @@ async function executePendingRetry({ walletSettings }) {
const failureShares = tracker.filter(
(entry) => entry && entry.status !== "success" && entry.amount > 0
);
markZapRetryPending(failureShares.length ? failureShares : [share]);
const message = error?.message || "Retry failed.";
setZapStatus(message, "error");
app?.showError?.(message);
renderZapReceipts(
aggregatedTracker.length ? aggregatedTracker : tracker,
{
partial: true
}
);
return;
if (failureShares.length) {
nextRetryShares.push(...failureShares);
} else {
nextRetryShares.push(share);
}
}
}
if (nextRetryShares.length > 0) {
markZapRetryPending(nextRetryShares);
const message = lastError?.message || "Retry failed.";
setZapStatus(message, "error");
app?.showError?.(message);
renderZapReceipts(
aggregatedTracker.length ? aggregatedTracker : [],
{
partial: true
}
);
return;
}
renderZapReceipts(
aggregatedReceipts.length ? aggregatedReceipts : aggregatedTracker,
{ partial: false }
+12 -2
View File
@@ -520,7 +520,13 @@ async function processShare({
}
export async function splitAndZap(
{ videoEvent, amountSats, comment = "", walletSettings } = {},
{
videoEvent,
amountSats,
comment = "",
walletSettings,
overrideFee = null,
} = {},
dependencies = {}
) {
if (!videoEvent || typeof videoEvent !== "object") {
@@ -538,7 +544,11 @@ export async function splitAndZap(
throw new Error("This creator has not configured a Lightning address yet.");
}
const platformFee = clampPercent(getOverridePlatformFee());
const platformFee = clampPercent(
typeof overrideFee !== "undefined" && overrideFee !== null
? resolvePlatformFeePercent(overrideFee)
: getOverridePlatformFee()
);
const platformShare = Math.floor((amount * platformFee) / 100);
const creatorShare = amount - platformShare;
+1 -18
View File
@@ -881,13 +881,6 @@ export default class ZapController {
});
const videoEvent = this.getActiveVideoEvent();
let previousOverride;
const hasGlobal = typeof globalThis !== "undefined";
if (hasGlobal && typeof overrideFee === "number" && Number.isFinite(overrideFee)) {
previousOverride = globalThis.__BITVID_PLATFORM_FEE_OVERRIDE__;
globalThis.__BITVID_PLATFORM_FEE_OVERRIDE__ = overrideFee;
}
try {
const result = await this.splitAndZap(
{
@@ -895,6 +888,7 @@ export default class ZapController {
amountSats: context.shares.total,
comment: typeof comment === "string" ? comment : "",
walletSettings: settings,
overrideFee,
},
dependencies
);
@@ -937,17 +931,6 @@ export default class ZapController {
error
);
throw error;
} finally {
if (hasGlobal && typeof overrideFee === "number" && Number.isFinite(overrideFee)) {
if (typeof previousOverride === "number") {
globalThis.__BITVID_PLATFORM_FEE_OVERRIDE__ = previousOverride;
} else if (
globalThis &&
Object.prototype.hasOwnProperty.call(globalThis, "__BITVID_PLATFORM_FEE_OVERRIDE__")
) {
delete globalThis.__BITVID_PLATFORM_FEE_OVERRIDE__;
}
}
}
}