race condition

This commit is contained in:
2026-05-30 14:14:07 -05:00
parent b020ded682
commit b19a167306

View File

@@ -15,6 +15,7 @@ const path = require('path');
let oauthClient = null;
let _lastSavedAccessToken = null;
let refreshInFlight = null; // single-flight lock for concurrent token refresh
const tokenFile = path.join(__dirname, 'qbo_token.json');
const getOAuthClient = () => {
@@ -110,25 +111,34 @@ async function makeQboApiCall(requestOptions) {
}
const doRefresh = async () => {
if (refreshInFlight) {
console.log(`[${ts()}] ⏳ Awaiting in-flight token refresh...`);
return refreshInFlight;
}
console.log(`[${ts()}] 🔄 QBO Token Refresh...`);
const refreshTokenStr = currentToken.refresh_token;
try {
const authResponse = await client.refreshUsingToken(refreshTokenStr);
console.log(`[${ts()}] ✅ Token refreshed via refreshUsingToken()`);
saveTokens(); // saveTokens prüft selbst ob sich was geändert hat
return authResponse;
} catch (e) {
const errMsg = e.originalMessage || e.message || String(e);
console.error(`[${ts()}] ❌ Refresh failed: ${errMsg}`);
if (e.intuit_tid) console.error(` intuit_tid: ${e.intuit_tid}`);
if (errMsg.includes('invalid_grant')) {
throw new Error(
"Der Refresh Token ist bei Intuit ungültig (invalid_grant). " +
"Bitte im Playground einen neuen Token holen und set_qbo_token.js ausführen."
);
refreshInFlight = (async () => {
try {
const authResponse = await client.refreshUsingToken(refreshTokenStr);
console.log(`[${ts()}] ✅ Token refreshed via refreshUsingToken()`);
saveTokens();
return authResponse;
} catch (e) {
const errMsg = e.originalMessage || e.message || String(e);
console.error(`[${ts()}] ❌ Refresh failed: ${errMsg}`);
if (e.intuit_tid) console.error(` intuit_tid: ${e.intuit_tid}`);
if (errMsg.includes('invalid_grant')) {
throw new Error(
"Der Refresh Token ist bei Intuit ungültig (invalid_grant). " +
"Bitte im Playground einen neuen Token holen und set_qbo_token.js ausführen."
);
}
throw e;
} finally {
refreshInFlight = null;
}
throw e;
}
})();
return refreshInFlight;
};
try {