fix: isolate overlapping Human Gate loads
This commit is contained in:
parent
9d84d5c5c4
commit
ab329aa126
|
|
@ -10,6 +10,7 @@ function createHumanGates(options = {}) {
|
||||||
let reviewSnapshot = [];
|
let reviewSnapshot = [];
|
||||||
let reviewIndex = -1;
|
let reviewIndex = -1;
|
||||||
let loadedAccountKey = '';
|
let loadedAccountKey = '';
|
||||||
|
let loadEpoch = 0;
|
||||||
const decisionKeys = new Map();
|
const decisionKeys = new Map();
|
||||||
let decisionFlight = null;
|
let decisionFlight = null;
|
||||||
|
|
||||||
|
|
@ -80,6 +81,7 @@ function createHumanGates(options = {}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function load() {
|
async function load() {
|
||||||
|
const epoch = ++loadEpoch;
|
||||||
const accountKey = String(getAccountKey() || '').trim().toLowerCase();
|
const accountKey = String(getAccountKey() || '').trim().toLowerCase();
|
||||||
if (accountKey !== loadedAccountKey) {
|
if (accountKey !== loadedAccountKey) {
|
||||||
loadedAccountKey = accountKey;
|
loadedAccountKey = accountKey;
|
||||||
|
|
@ -92,12 +94,14 @@ function createHumanGates(options = {}) {
|
||||||
if (cached) { queue = cached; render(); }
|
if (cached) { queue = cached; render(); }
|
||||||
try {
|
try {
|
||||||
const live = validSnapshot(await fetchJson('api/v1/human-gates'));
|
const live = validSnapshot(await fetchJson('api/v1/human-gates'));
|
||||||
|
if (epoch !== loadEpoch || accountKey !== loadedAccountKey) return queue;
|
||||||
if (!live) throw new Error('Human Gates response is invalid.');
|
if (!live) throw new Error('Human Gates response is invalid.');
|
||||||
queue = { pending_count: live.pending_count, items: live.items.slice() };
|
queue = { pending_count: live.pending_count, items: live.items.slice() };
|
||||||
save(queue);
|
save(queue);
|
||||||
render();
|
render();
|
||||||
return queue;
|
return queue;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
if (epoch !== loadEpoch || accountKey !== loadedAccountKey) return queue;
|
||||||
if (!cached) throw error;
|
if (!cached) throw error;
|
||||||
setText(nodes.status, 'Offline cached gate list · reconnect before deciding.');
|
setText(nodes.status, 'Offline cached gate list · reconnect before deciding.');
|
||||||
return queue;
|
return queue;
|
||||||
|
|
|
||||||
|
|
@ -94,6 +94,18 @@ const gates=createHumanGates({storage,getLogin:()=> 'timmy',getAccountKey:()=>ac
|
||||||
assert "secret" not in output["html"]
|
assert "secret" not in output["html"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_stale_account_load_cannot_overwrite_new_account_queue_or_cache():
|
||||||
|
output = run_node(r"""
|
||||||
|
const values=new Map(); const storage={getItem:k=>values.get(k)||null,setItem:(k,v)=>values.set(k,v)};
|
||||||
|
let account='1:timmy', resolveA, resolveB;
|
||||||
|
const responseA=new Promise(resolve=>resolveA=resolve), responseB=new Promise(resolve=>resolveB=resolve);
|
||||||
|
const gates=createHumanGates({storage,getLogin:()=> 'timmy',getAccountKey:()=>account,isOnline:()=>true,nodes:{count:{},list:{innerHTML:''},status:{},panel:{}},location:{hash:''},fetchJson:()=>account.startsWith('1:')?responseA:responseB});
|
||||||
|
(async()=>{const loadA=gates.load();account='2:timmy';const loadB=gates.load();resolveB({pending_count:1,items:[{id:'b',title:'B gate',candidate_hash:'bhash'}]});await loadB;resolveA({pending_count:1,items:[{id:'a-secret',title:'A secret',candidate_hash:'asecret'}]});await loadA;process.stdout.write(JSON.stringify({snapshot:gates.snapshot(),cached:JSON.parse(values.get('stackchain.human-gates.v1:2:timmy'))}));})();
|
||||||
|
""")
|
||||||
|
assert [item["id"] for item in output["snapshot"]["items"]] == ["b"]
|
||||||
|
assert [item["id"] for item in output["cached"]["items"]] == ["b"]
|
||||||
|
|
||||||
|
|
||||||
def test_decision_retry_reuses_the_same_idempotency_key():
|
def test_decision_retry_reuses_the_same_idempotency_key():
|
||||||
output = run_node(r"""
|
output = run_node(r"""
|
||||||
let attempts=0; const keys=[];
|
let attempts=0; const keys=[];
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user