mirror of
https://github.com/pezkuwichain/pezkuwi-subquery.git
synced 2026-07-22 16:55:41 +00:00
Fix noter bot: serialize signAndSend to stop concurrent-nonce tx rejection
fullScan() processes accounts in concurrent batches of 10, and each account's
own data-gathering takes variable time, so multiple accounts' submitStakingDetails
calls landed close enough together to race on nonce assignment - the pool then
rejected most of them as duplicate-priority ("Priority is too low ... already in
the pool"). Observed live: 37 of 50 tracked accounts silently dropped in a single
scan cycle, including real accounts with genuine stake (Serok, QaziM) whose trust
scores stayed stuck at 0 as a result even after the separate NotRegisteredNoter
bond issue was fixed.
Routes every submission (both fullScan's batches and the live event listener)
through a single queue so exactly one signAndSend is ever in flight at a time,
in call order - data-gathering stays concurrent (unaffected), only the actual
chain submission is serialized.
This commit is contained in:
+21
-2
@@ -232,13 +232,32 @@ function hasDataChanged(fresh, cached) {
|
||||
// TRANSACTION SUBMISSION
|
||||
// ========================================
|
||||
|
||||
/**
|
||||
* Serializes every real submission through this queue. fullScan() fires up to BATCH_SIZE
|
||||
* processAccount() calls concurrently (by design, for the read-only data-gathering they start
|
||||
* with), and the live event listener can also submit at any time - without this, multiple
|
||||
* signAndSend() calls from the same noter keypair can land close enough together that the API's
|
||||
* nonce bookkeeping races, producing duplicate-nonce transactions the pool then rejects as
|
||||
* "Priority is too low ... already in the pool" (observed: 37 of 50 accounts silently dropped in
|
||||
* a single scan). One in-flight submission at a time, in call order, removes the race entirely
|
||||
* regardless of which caller is submitting.
|
||||
*/
|
||||
let submitQueue = Promise.resolve();
|
||||
|
||||
/**
|
||||
* Submit receive_staking_details for one or more (address, source) pairs.
|
||||
* Batches multiple calls into a single utility.batchAll transaction.
|
||||
*/
|
||||
async function submitStakingDetails(peopleApi, noterKeypair, updates) {
|
||||
if (updates.length === 0) return;
|
||||
function submitStakingDetails(peopleApi, noterKeypair, updates) {
|
||||
if (updates.length === 0) return Promise.resolve();
|
||||
|
||||
const task = submitQueue.then(() => doSubmitStakingDetails(peopleApi, noterKeypair, updates));
|
||||
// Never let one caller's failure poison the queue for the next caller's submission.
|
||||
submitQueue = task.catch(() => {});
|
||||
return task;
|
||||
}
|
||||
|
||||
function doSubmitStakingDetails(peopleApi, noterKeypair, updates) {
|
||||
const calls = updates.map(({ address, source, data }) =>
|
||||
peopleApi.tx.stakingScore.receiveStakingDetails(
|
||||
address,
|
||||
|
||||
Reference in New Issue
Block a user