Improved the background request loading order
This commit is contained in:
20
dist/chromium/content.js
vendored
20
dist/chromium/content.js
vendored
@@ -3684,6 +3684,7 @@ function createFusionOpportunities({
|
|||||||
getOpportunityTypeValues,
|
getOpportunityTypeValues,
|
||||||
readResponseBodyForDebug,
|
readResponseBodyForDebug,
|
||||||
resetDebugRequests = () => {},
|
resetDebugRequests = () => {},
|
||||||
|
loadServiceRequests = async () => {},
|
||||||
environment
|
environment
|
||||||
}) {
|
}) {
|
||||||
const { fetch } = environment;
|
const { fetch } = environment;
|
||||||
@@ -3712,7 +3713,13 @@ function createFusionOpportunities({
|
|||||||
const payload = createOpportunitiesQueryPayload(dateRange, offset, savedSearchNumber);
|
const payload = createOpportunitiesQueryPayload(dateRange, offset, savedSearchNumber);
|
||||||
const requestBody = JSON.stringify(payload);
|
const requestBody = JSON.stringify(payload);
|
||||||
// One history per query, preserving all pages of the same result set.
|
// One history per query, preserving all pages of the same result set.
|
||||||
if (page === 1) resetDebugRequests();
|
if (page === 1) {
|
||||||
|
resetDebugRequests();
|
||||||
|
// SR queries do not depend on opportunity or product IDs. Keep their
|
||||||
|
// diagnostics in this query's history and reuse the loaded SR state later.
|
||||||
|
try { await loadServiceRequests(token, requestVersion); } catch { /* SR failure must not block opportunities. */ }
|
||||||
|
if (!isCurrentPeriodRequest(requestVersion)) return null;
|
||||||
|
}
|
||||||
const requestEntry = logRequestStart({
|
const requestEntry = logRequestStart({
|
||||||
name: "requestOpportunities",
|
name: "requestOpportunities",
|
||||||
method: "POST",
|
method: "POST",
|
||||||
@@ -3953,7 +3960,7 @@ function createFusionCrmServiceRequests({ isCurrentPeriodRequest,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Source: src/features/opportunities/crm-service-requests.js
|
// Source: src/features/opportunities/crm-service-requests.js
|
||||||
function createOpportunityCrmServiceRequests({ requestCrmServiceRequest, isCurrentPeriodRequest, bindPopover, closePopover, createSrButton, closeSrForm, allowsCrmActivities, reportProgress, activityCache, setBadgeContent, formatDate, environment }) {
|
function createOpportunityCrmServiceRequests({ requestCrmServiceRequest, isCurrentPeriodRequest, bindPopover, closePopover, createSrButton, closeSrForm, allowsCrmActivities, reportProgress, activityCache, setBadgeContent, formatDate, environment, onStateChange = () => {} }) {
|
||||||
let status = "idle";
|
let status = "idle";
|
||||||
let byOpportunity = new Map();
|
let byOpportunity = new Map();
|
||||||
let pending = null;
|
let pending = null;
|
||||||
@@ -3975,6 +3982,7 @@ function createOpportunityCrmServiceRequests({ requestCrmServiceRequest, isCurre
|
|||||||
async function run(token, version, currentGeneration, cacheOptions) {
|
async function run(token, version, currentGeneration, cacheOptions) {
|
||||||
const isActive = () => currentGeneration === generation;
|
const isActive = () => currentGeneration === generation;
|
||||||
status = "loading";
|
status = "loading";
|
||||||
|
onStateChange();
|
||||||
try {
|
try {
|
||||||
const cached = cacheOptions ? await activityCache.read("sr", "all", cacheOptions.cachedAt) : null;
|
const cached = cacheOptions ? await activityCache.read("sr", "all", cacheOptions.cachedAt) : null;
|
||||||
if (!isActive()) return false;
|
if (!isActive()) return false;
|
||||||
@@ -4000,9 +4008,11 @@ function createOpportunityCrmServiceRequests({ requestCrmServiceRequest, isCurre
|
|||||||
loadedItems = items;
|
loadedItems = items;
|
||||||
status = "ready";
|
status = "ready";
|
||||||
if (!cached) reportProgress("complete", items.length, items.length);
|
if (!cached) reportProgress("complete", items.length, items.length);
|
||||||
|
// Refresh SR badges, filters and totals independently of product/action jobs.
|
||||||
|
onStateChange();
|
||||||
return true;
|
return true;
|
||||||
} catch {
|
} catch {
|
||||||
if (isActive()) { status = "error"; reportProgress("error"); }
|
if (isActive()) { status = "error"; reportProgress("error"); onStateChange(); }
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -11714,6 +11724,7 @@ function createContentApplication(overrides = {}) {
|
|||||||
setOpportunitiesTableState: (...args) => opportunitiesTable.setOpportunitiesTableState(...args)
|
setOpportunitiesTableState: (...args) => opportunitiesTable.setOpportunitiesTableState(...args)
|
||||||
});
|
});
|
||||||
const fusionOpportunities = createFusionOpportunities({
|
const fusionOpportunities = createFusionOpportunities({
|
||||||
|
loadServiceRequests: (token, version) => opportunityCrmServiceRequests.load(token, version),
|
||||||
resetDebugRequests: () => debugState.reset(),
|
resetDebugRequests: () => debugState.reset(),
|
||||||
OPPORTUNITIES_PAGE_LIMIT: contracts.OPPORTUNITIES_PAGE_LIMIT,
|
OPPORTUNITIES_PAGE_LIMIT: contracts.OPPORTUNITIES_PAGE_LIMIT,
|
||||||
OPPORTUNITIES_QUERY_URL: contracts.OPPORTUNITIES_QUERY_URL,
|
OPPORTUNITIES_QUERY_URL: contracts.OPPORTUNITIES_QUERY_URL,
|
||||||
@@ -11793,6 +11804,9 @@ function createContentApplication(overrides = {}) {
|
|||||||
requestPillars: () => requestSrFormLookup(messageTypes.requestSrLookupPrimaryPillar)
|
requestPillars: () => requestSrFormLookup(messageTypes.requestSrLookupPrimaryPillar)
|
||||||
});
|
});
|
||||||
const opportunityCrmServiceRequests = createOpportunityCrmServiceRequests({
|
const opportunityCrmServiceRequests = createOpportunityCrmServiceRequests({
|
||||||
|
onStateChange: () => {
|
||||||
|
if (environment.document?.getElementById?.(contracts.OPPORTUNITIES_TABLE_ID)) opportunitiesTable.renderOpportunitiesTable();
|
||||||
|
},
|
||||||
formatDate: value => opportunitiesFormatters.formatOracleResponseDate(value),
|
formatDate: value => opportunitiesFormatters.formatOracleResponseDate(value),
|
||||||
createSrButton: number => crmSrForm.createButton(number),
|
createSrButton: number => crmSrForm.createButton(number),
|
||||||
closeSrForm: () => { internalSrForm.close(false); crmSrForm.close(false); },
|
closeSrForm: () => { internalSrForm.close(false); crmSrForm.close(false); },
|
||||||
|
|||||||
20
dist/firefox/content.js
vendored
20
dist/firefox/content.js
vendored
@@ -3684,6 +3684,7 @@ function createFusionOpportunities({
|
|||||||
getOpportunityTypeValues,
|
getOpportunityTypeValues,
|
||||||
readResponseBodyForDebug,
|
readResponseBodyForDebug,
|
||||||
resetDebugRequests = () => {},
|
resetDebugRequests = () => {},
|
||||||
|
loadServiceRequests = async () => {},
|
||||||
environment
|
environment
|
||||||
}) {
|
}) {
|
||||||
const { fetch } = environment;
|
const { fetch } = environment;
|
||||||
@@ -3712,7 +3713,13 @@ function createFusionOpportunities({
|
|||||||
const payload = createOpportunitiesQueryPayload(dateRange, offset, savedSearchNumber);
|
const payload = createOpportunitiesQueryPayload(dateRange, offset, savedSearchNumber);
|
||||||
const requestBody = JSON.stringify(payload);
|
const requestBody = JSON.stringify(payload);
|
||||||
// One history per query, preserving all pages of the same result set.
|
// One history per query, preserving all pages of the same result set.
|
||||||
if (page === 1) resetDebugRequests();
|
if (page === 1) {
|
||||||
|
resetDebugRequests();
|
||||||
|
// SR queries do not depend on opportunity or product IDs. Keep their
|
||||||
|
// diagnostics in this query's history and reuse the loaded SR state later.
|
||||||
|
try { await loadServiceRequests(token, requestVersion); } catch { /* SR failure must not block opportunities. */ }
|
||||||
|
if (!isCurrentPeriodRequest(requestVersion)) return null;
|
||||||
|
}
|
||||||
const requestEntry = logRequestStart({
|
const requestEntry = logRequestStart({
|
||||||
name: "requestOpportunities",
|
name: "requestOpportunities",
|
||||||
method: "POST",
|
method: "POST",
|
||||||
@@ -3953,7 +3960,7 @@ function createFusionCrmServiceRequests({ isCurrentPeriodRequest,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Source: src/features/opportunities/crm-service-requests.js
|
// Source: src/features/opportunities/crm-service-requests.js
|
||||||
function createOpportunityCrmServiceRequests({ requestCrmServiceRequest, isCurrentPeriodRequest, bindPopover, closePopover, createSrButton, closeSrForm, allowsCrmActivities, reportProgress, activityCache, setBadgeContent, formatDate, environment }) {
|
function createOpportunityCrmServiceRequests({ requestCrmServiceRequest, isCurrentPeriodRequest, bindPopover, closePopover, createSrButton, closeSrForm, allowsCrmActivities, reportProgress, activityCache, setBadgeContent, formatDate, environment, onStateChange = () => {} }) {
|
||||||
let status = "idle";
|
let status = "idle";
|
||||||
let byOpportunity = new Map();
|
let byOpportunity = new Map();
|
||||||
let pending = null;
|
let pending = null;
|
||||||
@@ -3975,6 +3982,7 @@ function createOpportunityCrmServiceRequests({ requestCrmServiceRequest, isCurre
|
|||||||
async function run(token, version, currentGeneration, cacheOptions) {
|
async function run(token, version, currentGeneration, cacheOptions) {
|
||||||
const isActive = () => currentGeneration === generation;
|
const isActive = () => currentGeneration === generation;
|
||||||
status = "loading";
|
status = "loading";
|
||||||
|
onStateChange();
|
||||||
try {
|
try {
|
||||||
const cached = cacheOptions ? await activityCache.read("sr", "all", cacheOptions.cachedAt) : null;
|
const cached = cacheOptions ? await activityCache.read("sr", "all", cacheOptions.cachedAt) : null;
|
||||||
if (!isActive()) return false;
|
if (!isActive()) return false;
|
||||||
@@ -4000,9 +4008,11 @@ function createOpportunityCrmServiceRequests({ requestCrmServiceRequest, isCurre
|
|||||||
loadedItems = items;
|
loadedItems = items;
|
||||||
status = "ready";
|
status = "ready";
|
||||||
if (!cached) reportProgress("complete", items.length, items.length);
|
if (!cached) reportProgress("complete", items.length, items.length);
|
||||||
|
// Refresh SR badges, filters and totals independently of product/action jobs.
|
||||||
|
onStateChange();
|
||||||
return true;
|
return true;
|
||||||
} catch {
|
} catch {
|
||||||
if (isActive()) { status = "error"; reportProgress("error"); }
|
if (isActive()) { status = "error"; reportProgress("error"); onStateChange(); }
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -11714,6 +11724,7 @@ function createContentApplication(overrides = {}) {
|
|||||||
setOpportunitiesTableState: (...args) => opportunitiesTable.setOpportunitiesTableState(...args)
|
setOpportunitiesTableState: (...args) => opportunitiesTable.setOpportunitiesTableState(...args)
|
||||||
});
|
});
|
||||||
const fusionOpportunities = createFusionOpportunities({
|
const fusionOpportunities = createFusionOpportunities({
|
||||||
|
loadServiceRequests: (token, version) => opportunityCrmServiceRequests.load(token, version),
|
||||||
resetDebugRequests: () => debugState.reset(),
|
resetDebugRequests: () => debugState.reset(),
|
||||||
OPPORTUNITIES_PAGE_LIMIT: contracts.OPPORTUNITIES_PAGE_LIMIT,
|
OPPORTUNITIES_PAGE_LIMIT: contracts.OPPORTUNITIES_PAGE_LIMIT,
|
||||||
OPPORTUNITIES_QUERY_URL: contracts.OPPORTUNITIES_QUERY_URL,
|
OPPORTUNITIES_QUERY_URL: contracts.OPPORTUNITIES_QUERY_URL,
|
||||||
@@ -11793,6 +11804,9 @@ function createContentApplication(overrides = {}) {
|
|||||||
requestPillars: () => requestSrFormLookup(messageTypes.requestSrLookupPrimaryPillar)
|
requestPillars: () => requestSrFormLookup(messageTypes.requestSrLookupPrimaryPillar)
|
||||||
});
|
});
|
||||||
const opportunityCrmServiceRequests = createOpportunityCrmServiceRequests({
|
const opportunityCrmServiceRequests = createOpportunityCrmServiceRequests({
|
||||||
|
onStateChange: () => {
|
||||||
|
if (environment.document?.getElementById?.(contracts.OPPORTUNITIES_TABLE_ID)) opportunitiesTable.renderOpportunitiesTable();
|
||||||
|
},
|
||||||
formatDate: value => opportunitiesFormatters.formatOracleResponseDate(value),
|
formatDate: value => opportunitiesFormatters.formatOracleResponseDate(value),
|
||||||
createSrButton: number => crmSrForm.createButton(number),
|
createSrButton: number => crmSrForm.createButton(number),
|
||||||
closeSrForm: () => { internalSrForm.close(false); crmSrForm.close(false); },
|
closeSrForm: () => { internalSrForm.close(false); crmSrForm.close(false); },
|
||||||
|
|||||||
@@ -273,6 +273,7 @@ function createContentApplication(overrides = {}) {
|
|||||||
setOpportunitiesTableState: (...args) => opportunitiesTable.setOpportunitiesTableState(...args)
|
setOpportunitiesTableState: (...args) => opportunitiesTable.setOpportunitiesTableState(...args)
|
||||||
});
|
});
|
||||||
const fusionOpportunities = createFusionOpportunities({
|
const fusionOpportunities = createFusionOpportunities({
|
||||||
|
loadServiceRequests: (token, version) => opportunityCrmServiceRequests.load(token, version),
|
||||||
resetDebugRequests: () => debugState.reset(),
|
resetDebugRequests: () => debugState.reset(),
|
||||||
OPPORTUNITIES_PAGE_LIMIT: contracts.OPPORTUNITIES_PAGE_LIMIT,
|
OPPORTUNITIES_PAGE_LIMIT: contracts.OPPORTUNITIES_PAGE_LIMIT,
|
||||||
OPPORTUNITIES_QUERY_URL: contracts.OPPORTUNITIES_QUERY_URL,
|
OPPORTUNITIES_QUERY_URL: contracts.OPPORTUNITIES_QUERY_URL,
|
||||||
@@ -352,6 +353,9 @@ function createContentApplication(overrides = {}) {
|
|||||||
requestPillars: () => requestSrFormLookup(messageTypes.requestSrLookupPrimaryPillar)
|
requestPillars: () => requestSrFormLookup(messageTypes.requestSrLookupPrimaryPillar)
|
||||||
});
|
});
|
||||||
const opportunityCrmServiceRequests = createOpportunityCrmServiceRequests({
|
const opportunityCrmServiceRequests = createOpportunityCrmServiceRequests({
|
||||||
|
onStateChange: () => {
|
||||||
|
if (environment.document?.getElementById?.(contracts.OPPORTUNITIES_TABLE_ID)) opportunitiesTable.renderOpportunitiesTable();
|
||||||
|
},
|
||||||
formatDate: value => opportunitiesFormatters.formatOracleResponseDate(value),
|
formatDate: value => opportunitiesFormatters.formatOracleResponseDate(value),
|
||||||
createSrButton: number => crmSrForm.createButton(number),
|
createSrButton: number => crmSrForm.createButton(number),
|
||||||
closeSrForm: () => { internalSrForm.close(false); crmSrForm.close(false); },
|
closeSrForm: () => { internalSrForm.close(false); crmSrForm.close(false); },
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
function createOpportunityCrmServiceRequests({ requestCrmServiceRequest, isCurrentPeriodRequest, bindPopover, closePopover, createSrButton, closeSrForm, allowsCrmActivities, reportProgress, activityCache, setBadgeContent, formatDate, environment }) {
|
function createOpportunityCrmServiceRequests({ requestCrmServiceRequest, isCurrentPeriodRequest, bindPopover, closePopover, createSrButton, closeSrForm, allowsCrmActivities, reportProgress, activityCache, setBadgeContent, formatDate, environment, onStateChange = () => {} }) {
|
||||||
let status = "idle";
|
let status = "idle";
|
||||||
let byOpportunity = new Map();
|
let byOpportunity = new Map();
|
||||||
let pending = null;
|
let pending = null;
|
||||||
@@ -20,6 +20,7 @@ function createOpportunityCrmServiceRequests({ requestCrmServiceRequest, isCurre
|
|||||||
async function run(token, version, currentGeneration, cacheOptions) {
|
async function run(token, version, currentGeneration, cacheOptions) {
|
||||||
const isActive = () => currentGeneration === generation;
|
const isActive = () => currentGeneration === generation;
|
||||||
status = "loading";
|
status = "loading";
|
||||||
|
onStateChange();
|
||||||
try {
|
try {
|
||||||
const cached = cacheOptions ? await activityCache.read("sr", "all", cacheOptions.cachedAt) : null;
|
const cached = cacheOptions ? await activityCache.read("sr", "all", cacheOptions.cachedAt) : null;
|
||||||
if (!isActive()) return false;
|
if (!isActive()) return false;
|
||||||
@@ -45,9 +46,11 @@ function createOpportunityCrmServiceRequests({ requestCrmServiceRequest, isCurre
|
|||||||
loadedItems = items;
|
loadedItems = items;
|
||||||
status = "ready";
|
status = "ready";
|
||||||
if (!cached) reportProgress("complete", items.length, items.length);
|
if (!cached) reportProgress("complete", items.length, items.length);
|
||||||
|
// Refresh SR badges, filters and totals independently of product/action jobs.
|
||||||
|
onStateChange();
|
||||||
return true;
|
return true;
|
||||||
} catch {
|
} catch {
|
||||||
if (isActive()) { status = "error"; reportProgress("error"); }
|
if (isActive()) { status = "error"; reportProgress("error"); onStateChange(); }
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ function createFusionOpportunities({
|
|||||||
getOpportunityTypeValues,
|
getOpportunityTypeValues,
|
||||||
readResponseBodyForDebug,
|
readResponseBodyForDebug,
|
||||||
resetDebugRequests = () => {},
|
resetDebugRequests = () => {},
|
||||||
|
loadServiceRequests = async () => {},
|
||||||
environment
|
environment
|
||||||
}) {
|
}) {
|
||||||
const { fetch } = environment;
|
const { fetch } = environment;
|
||||||
@@ -37,7 +38,13 @@ function createFusionOpportunities({
|
|||||||
const payload = createOpportunitiesQueryPayload(dateRange, offset, savedSearchNumber);
|
const payload = createOpportunitiesQueryPayload(dateRange, offset, savedSearchNumber);
|
||||||
const requestBody = JSON.stringify(payload);
|
const requestBody = JSON.stringify(payload);
|
||||||
// One history per query, preserving all pages of the same result set.
|
// One history per query, preserving all pages of the same result set.
|
||||||
if (page === 1) resetDebugRequests();
|
if (page === 1) {
|
||||||
|
resetDebugRequests();
|
||||||
|
// SR queries do not depend on opportunity or product IDs. Keep their
|
||||||
|
// diagnostics in this query's history and reuse the loaded SR state later.
|
||||||
|
try { await loadServiceRequests(token, requestVersion); } catch { /* SR failure must not block opportunities. */ }
|
||||||
|
if (!isCurrentPeriodRequest(requestVersion)) return null;
|
||||||
|
}
|
||||||
const requestEntry = logRequestStart({
|
const requestEntry = logRequestStart({
|
||||||
name: "requestOpportunities",
|
name: "requestOpportunities",
|
||||||
method: "POST",
|
method: "POST",
|
||||||
|
|||||||
8
tests/srRequestPriority.test.cjs
Normal file
8
tests/srRequestPriority.test.cjs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
const {test}=require('node:test');const assert=require('node:assert/strict');const fs=require('node:fs');const vm=require('node:vm');
|
||||||
|
const factory=vm.runInNewContext(fs.readFileSync('src/services/fusion/opportunities.js','utf8')+'\ncreateFusionOpportunities');
|
||||||
|
for(const mode of ['success','failure','stale'])test(`SR precedes opportunities: ${mode}`,async()=>{
|
||||||
|
const order=[];let active=true;let page=0;
|
||||||
|
const api=factory({OPPORTUNITIES_PAGE_LIMIT:1,OPPORTUNITIES_QUERY_URL:'https://example.invalid',isCurrentPeriodRequest:()=>active,getOpportunityTypeValues:()=>new Set(['ALL']),logRequestStart:()=>({}),logRequestSuccess(){},logRequestFailure(){},readResponseBodyForDebug:async()=>'',resetDebugRequests:()=>order.push('reset'),loadServiceRequests:async()=>{order.push('sr');if(mode==='stale')active=false;if(mode==='failure')throw Error('SR failed');},environment:{fetch:async()=>{order.push('opportunities');page++;return {ok:true,json:async()=>({items:[{OptyNumber:String(page)}],hasMore:page===1,count:1,offset:page-1})};}}});
|
||||||
|
await api.requestOpportunitiesPage('token','CQ',{startCloseDate:'2026-09-01',endCloseDate:'2026-12-01'},0,[],1,1,'saved-search');
|
||||||
|
assert.deepEqual(order,mode==='stale'?['reset','sr']:['reset','sr','opportunities','opportunities']);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user