Fix indexer race: instant verify (join-now auto-submission) pre-cached new members, making the log tail skip their registration (referrer directCount never bumped - #41 stuck at 1/2 despite #134). preIndexed flag + merge on event + one-time re-snapshot migration.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -57,6 +57,9 @@ function loadState() {
|
|||||||
if (state.payouts.some(p => p.kind === 'income' && !p.desc)) state.snapshotAt = 0;
|
if (state.payouts.some(p => p.kind === 'income' && !p.desc)) state.snapshotAt = 0;
|
||||||
// one-time true-up: earlier tail code didn't maintain directCount/matrix slots live
|
// one-time true-up: earlier tail code didn't maintain directCount/matrix slots live
|
||||||
if (!state.migratedLiveCounts) { state.snapshotAt = 0; state.migratedLiveCounts = true; }
|
if (!state.migratedLiveCounts) { state.snapshotAt = 0; state.migratedLiveCounts = true; }
|
||||||
|
// one-time re-snapshot: repair members pre-cached by verifyMember whose
|
||||||
|
// registration the tail skipped (#134 missing placement, #41 stuck at 1/2)
|
||||||
|
if (!state.migratedPreIndexFix) { state.snapshotAt = 0; state.migratedPreIndexFix = true; }
|
||||||
}
|
}
|
||||||
function saveState() {
|
function saveState() {
|
||||||
try {
|
try {
|
||||||
@@ -275,8 +278,10 @@ async function processRange(fromBlock, toBlock) {
|
|||||||
const key = tx.slice(2, 12) + ':' + hexInt(l.logIndex);
|
const key = tx.slice(2, 12) + ':' + hexInt(l.logIndex);
|
||||||
if (l.topics[0] === T_REGISTERED) {
|
if (l.topics[0] === T_REGISTERED) {
|
||||||
const id = topicInt(l.topics[1]);
|
const id = topicInt(l.topics[1]);
|
||||||
if (!state.members[id]) {
|
const existing = state.members[id];
|
||||||
state.members[id] = { account: topicAddr(l.topics[2]), referrerId: topicInt(l.topics[3]), tier: wInt(l.data, 0), joinedAt: ts, level: 1, directCount: 0, earnedPol: 0 };
|
if (!existing || existing.preIndexed) {
|
||||||
|
state.members[id] = { ...(existing || {}), account: topicAddr(l.topics[2]), referrerId: topicInt(l.topics[3]), tier: wInt(l.data, 0), joinedAt: ts, level: (existing && existing.level) || 1, directCount: (existing && existing.directCount) || 0, earnedPol: (existing && existing.earnedPol) || 0 };
|
||||||
|
delete state.members[id].preIndexed;
|
||||||
// keep the referrer's qualification progress live between snapshots
|
// keep the referrer's qualification progress live between snapshots
|
||||||
const ref = state.members[topicInt(l.topics[3])];
|
const ref = state.members[topicInt(l.topics[3])];
|
||||||
if (ref) ref.directCount = (ref.directCount || 0) + 1;
|
if (ref) ref.directCount = (ref.directCount || 0) + 1;
|
||||||
@@ -411,7 +416,11 @@ function getPayoutsPublic(offset = 0, limit = 40) {
|
|||||||
async function verifyMember(id) {
|
async function verifyMember(id) {
|
||||||
const m = await fetchMember(id);
|
const m = await fetchMember(id);
|
||||||
if (!m) return { registered: false };
|
if (!m) return { registered: false };
|
||||||
if (state && !state.members[id]) state.members[id] = { account: m.account, referrerId: m.referrerId, uplineId: m.uplineId, tier: m.tier, level: m.level, joinedAt: m.joinedAt };
|
// preIndexed: provisional cache — the log tail must still process this
|
||||||
|
// member's registration event (referrer directCount++ etc.). Without the
|
||||||
|
// flag, an instant verify (join-now auto-submission) races the tail and the
|
||||||
|
// registration gets skipped as a duplicate (bit us with #134/#41, 2026-08-19).
|
||||||
|
if (state && !state.members[id]) state.members[id] = { account: m.account, referrerId: m.referrerId, uplineId: m.uplineId, tier: m.tier, level: m.level, joinedAt: m.joinedAt, preIndexed: true };
|
||||||
return { registered: true, ...m, tierName: tierName(m.tier), levelName: levelName(m.level) };
|
return { registered: true, ...m, tierName: tierName(m.tier), levelName: levelName(m.level) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user