Skip to content

Commit 0b2cfe9

Browse files
eabdelmoneimclaude
andauthored
fix: check backfill table before Redis so it can override stuck queue… (#937)
* fix: check backfill table before Redis so it can override stuck queued transactions Previously the backfill lookup only ran when a transaction was missing from Redis. Orphaned "queued" transactions that still exist in Redis were unreachable by backfill. Moving the check first lets backfill entries act as intentional overrides for stuck queue IDs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: check backfill before Redis in get-logs endpoint too Same change as status endpoint — backfill entries should take priority over stale Redis data for consistency across all endpoints. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: treat backfill entry as authoritative in get-logs endpoint When a backfill entry exists (even if errored), skip the Redis lookup entirely. Previously an errored backfill entry would fall through to Redis, potentially returning stale data for an orphaned transaction. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent ec98297 commit 0b2cfe9

2 files changed

Lines changed: 45 additions & 41 deletions

File tree

src/server/routes/transaction/blockchain/get-logs.ts

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -155,21 +155,28 @@ export async function getTransactionLogs(fastify: FastifyInstance) {
155155
// Get the transaction hash from the provided input.
156156
let hash: Hex | undefined;
157157
if (queueId) {
158-
// Primary lookup
159-
const transaction = await TransactionDB.get(queueId);
160-
if (transaction?.status === "mined") {
161-
hash = transaction.transactionHash;
162-
}
163-
164158
// SPECIAL LOGIC FOR AMEX
165-
// AMEX uses this endpoint to get logs for transactions they didn't receive webhooks for
166-
// the queue ID's were cleaned out of REDIS so we backfilled tx hashes to this backfill table
167-
// see https://github.com/thirdweb-dev/solutions-customer-scripts/blob/main/amex/scripts/load-backfill-via-api.ts
168-
// Fallback to backfill table if enabled and not found
169-
if (!hash && env.ENABLE_TX_BACKFILL_FALLBACK) {
159+
// Backfill table takes priority — entries are intentional overrides for
160+
// queue IDs that are stuck in Redis (e.g. orphaned "queued" transactions).
161+
if (env.ENABLE_TX_BACKFILL_FALLBACK) {
170162
const backfill = await TransactionDB.getBackfill(queueId);
171-
if (backfill?.status === "mined" && backfill.transactionHash && isHex(backfill.transactionHash)) {
172-
hash = backfill.transactionHash as Hex;
163+
if (backfill) {
164+
// Backfill entry exists and is authoritative — only set hash if mined.
165+
// If backfill is errored, hash stays undefined and we skip Redis lookup.
166+
if (backfill.status === "mined" && backfill.transactionHash && isHex(backfill.transactionHash)) {
167+
hash = backfill.transactionHash as Hex;
168+
}
169+
} else {
170+
// No backfill entry — fall back to Redis.
171+
const transaction = await TransactionDB.get(queueId);
172+
if (transaction?.status === "mined") {
173+
hash = transaction.transactionHash;
174+
}
175+
}
176+
} else {
177+
const transaction = await TransactionDB.get(queueId);
178+
if (transaction?.status === "mined") {
179+
hash = transaction.transactionHash;
173180
}
174181
}
175182
} else if (transactionHash) {

src/server/routes/transaction/status.ts

Lines changed: 25 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -145,22 +145,21 @@ export async function getTransactionStatusRoute(fastify: FastifyInstance) {
145145
handler: async (request, reply) => {
146146
const { queueId } = request.params;
147147

148-
const transaction = await TransactionDB.get(queueId);
149-
if (!transaction) {
150-
// SPECIAL LOGIC FOR AMEX
151-
// AMEX uses this endpoint to check transaction status for queue IDs they didn't receive webhooks for.
152-
// The queue ID's were cleaned out of Redis so we backfilled tx data to this backfill table.
153-
// See https://github.com/thirdweb-dev/solutions-customer-scripts/blob/main/amex/scripts/load-backfill-via-api.ts
154-
// Fallback to backfill table if enabled and not found
155-
if (env.ENABLE_TX_BACKFILL_FALLBACK) {
156-
const backfill = await TransactionDB.getBackfill(queueId);
157-
if (backfill) {
158-
return reply.status(StatusCodes.OK).send({
159-
result: createBackfillResponse(queueId, backfill),
160-
});
161-
}
148+
// SPECIAL LOGIC FOR AMEX
149+
// Backfill table takes priority — entries are intentional overrides for
150+
// queue IDs that are stuck in Redis (e.g. orphaned "queued" transactions).
151+
// See https://github.com/thirdweb-dev/solutions-customer-scripts/blob/main/amex/scripts/load-backfill-via-api.ts
152+
if (env.ENABLE_TX_BACKFILL_FALLBACK) {
153+
const backfill = await TransactionDB.getBackfill(queueId);
154+
if (backfill) {
155+
return reply.status(StatusCodes.OK).send({
156+
result: createBackfillResponse(queueId, backfill),
157+
});
162158
}
159+
}
163160

161+
const transaction = await TransactionDB.get(queueId);
162+
if (!transaction) {
164163
throw createCustomError(
165164
"Transaction not found.",
166165
StatusCodes.BAD_REQUEST,
@@ -206,22 +205,20 @@ export async function getTransactionStatusQueryParamRoute(
206205
);
207206
}
208207

209-
const transaction = await TransactionDB.get(queueId);
210-
if (!transaction) {
211-
// SPECIAL LOGIC FOR AMEX
212-
// AMEX uses this endpoint to check transaction status for queue IDs they didn't receive webhooks for.
213-
// The queue ID's were cleaned out of Redis so we backfilled tx data to this backfill table.
214-
// See https://github.com/thirdweb-dev/solutions-customer-scripts/blob/main/amex/scripts/load-backfill-via-api.ts
215-
// Fallback to backfill table if enabled and not found
216-
if (env.ENABLE_TX_BACKFILL_FALLBACK) {
217-
const backfill = await TransactionDB.getBackfill(queueId);
218-
if (backfill) {
219-
return reply.status(StatusCodes.OK).send({
220-
result: createBackfillResponse(queueId, backfill),
221-
});
222-
}
208+
// SPECIAL LOGIC FOR AMEX
209+
// Backfill table takes priority — entries are intentional overrides for
210+
// queue IDs that are stuck in Redis (e.g. orphaned "queued" transactions).
211+
if (env.ENABLE_TX_BACKFILL_FALLBACK) {
212+
const backfill = await TransactionDB.getBackfill(queueId);
213+
if (backfill) {
214+
return reply.status(StatusCodes.OK).send({
215+
result: createBackfillResponse(queueId, backfill),
216+
});
223217
}
218+
}
224219

220+
const transaction = await TransactionDB.get(queueId);
221+
if (!transaction) {
225222
throw createCustomError(
226223
"Transaction not found.",
227224
StatusCodes.BAD_REQUEST,

0 commit comments

Comments
 (0)