Perf/copilot cleanup and optimizations (#2447)

* perf: remove deprecated copilot feature, add ARM timeouts, fix race conditions

- Remove entire QueryCopilot feature (~50 files deleted, ~30 files cleaned)
- Remove CopilotConfigured and SampleDataLoaded metric phases
- Fix DatabaseTreeRendered 76% stuck rate (remove one-shot guard in useMetricPhases)
- Add 8s default timeout to ARM requests (AbortController-based)
- Fix MSAL token forceRefresh (true -> false, use cache)
- Add concurrency limit of 5 to collection loading in Explorer
- Remove orphaned SampleDataClient.ts and queryCopilotSampleData.json
- Clean up dead sampleDataConnectionInfo field from UserContext

* Clean up copilot and optimize initialization

* Clean up copilot and optimize initialization
This commit is contained in:
sunghyunkang1111
2026-04-08 11:25:33 -05:00
committed by GitHub
parent ab4f1289e1
commit fb250259ed
126 changed files with 162 additions and 22486 deletions

View File

@@ -5,16 +5,10 @@ export const scenarioConfigs: Record<MetricScenario, ScenarioConfig> = {
[MetricScenario.ApplicationLoad]: {
requiredPhases: [
ApplicationMetricPhase.PlatformConfigured,
ApplicationMetricPhase.CopilotConfigured,
ApplicationMetricPhase.SampleDataLoaded,
ApplicationMetricPhase.ExplorerInitialized,
CommonMetricPhase.Interactive,
],
deferredPhases: [
ApplicationMetricPhase.CopilotConfigured,
ApplicationMetricPhase.SampleDataLoaded,
ApplicationMetricPhase.ExplorerInitialized,
],
deferredPhases: [ApplicationMetricPhase.ExplorerInitialized],
timeoutMs: 10000,
},
[MetricScenario.DatabaseLoad]: {

View File

@@ -10,8 +10,6 @@ export enum CommonMetricPhase {
export enum ApplicationMetricPhase {
ExplorerInitialized = "ExplorerInitialized",
PlatformConfigured = "PlatformConfigured",
CopilotConfigured = "CopilotConfigured",
SampleDataLoaded = "SampleDataLoaded",
DatabasesFetched = "DatabasesFetched",
CollectionsLoaded = "CollectionsLoaded",
DatabaseTreeRendered = "DatabaseTreeRendered",

View File

@@ -112,10 +112,6 @@ describe("ScenarioMonitor", () => {
// Complete all phases to emit (PlatformConfigured auto-started, deferred phases need start+complete)
scenarioMonitor.completePhase(MetricScenario.ApplicationLoad, ApplicationMetricPhase.PlatformConfigured);
scenarioMonitor.startPhase(MetricScenario.ApplicationLoad, ApplicationMetricPhase.CopilotConfigured);
scenarioMonitor.completePhase(MetricScenario.ApplicationLoad, ApplicationMetricPhase.CopilotConfigured);
scenarioMonitor.startPhase(MetricScenario.ApplicationLoad, ApplicationMetricPhase.SampleDataLoaded);
scenarioMonitor.completePhase(MetricScenario.ApplicationLoad, ApplicationMetricPhase.SampleDataLoaded);
scenarioMonitor.startPhase(MetricScenario.ApplicationLoad, ApplicationMetricPhase.ExplorerInitialized);
scenarioMonitor.completePhase(MetricScenario.ApplicationLoad, ApplicationMetricPhase.ExplorerInitialized);
scenarioMonitor.completePhase(MetricScenario.ApplicationLoad, CommonMetricPhase.Interactive);
@@ -224,10 +220,6 @@ describe("ScenarioMonitor", () => {
// Complete all required phases (PlatformConfigured + Interactive auto-started, deferred need start)
scenarioMonitor.completePhase(MetricScenario.ApplicationLoad, ApplicationMetricPhase.PlatformConfigured);
scenarioMonitor.startPhase(MetricScenario.ApplicationLoad, ApplicationMetricPhase.CopilotConfigured);
scenarioMonitor.completePhase(MetricScenario.ApplicationLoad, ApplicationMetricPhase.CopilotConfigured);
scenarioMonitor.startPhase(MetricScenario.ApplicationLoad, ApplicationMetricPhase.SampleDataLoaded);
scenarioMonitor.completePhase(MetricScenario.ApplicationLoad, ApplicationMetricPhase.SampleDataLoaded);
scenarioMonitor.startPhase(MetricScenario.ApplicationLoad, ApplicationMetricPhase.ExplorerInitialized);
scenarioMonitor.completePhase(MetricScenario.ApplicationLoad, ApplicationMetricPhase.ExplorerInitialized);
scenarioMonitor.completePhase(MetricScenario.ApplicationLoad, CommonMetricPhase.Interactive);
@@ -237,13 +229,7 @@ describe("ScenarioMonitor", () => {
scenario: MetricScenario.ApplicationLoad,
healthy: true,
timedOut: false,
completedPhases: expect.arrayContaining([
"PlatformConfigured",
"CopilotConfigured",
"SampleDataLoaded",
"ExplorerInitialized",
"Interactive",
]),
completedPhases: expect.arrayContaining(["PlatformConfigured", "ExplorerInitialized", "Interactive"]),
}),
);
});
@@ -266,10 +252,6 @@ describe("ScenarioMonitor", () => {
// Complete ApplicationLoad (all phases including deferred)
scenarioMonitor.completePhase(MetricScenario.ApplicationLoad, ApplicationMetricPhase.PlatformConfigured);
scenarioMonitor.startPhase(MetricScenario.ApplicationLoad, ApplicationMetricPhase.CopilotConfigured);
scenarioMonitor.completePhase(MetricScenario.ApplicationLoad, ApplicationMetricPhase.CopilotConfigured);
scenarioMonitor.startPhase(MetricScenario.ApplicationLoad, ApplicationMetricPhase.SampleDataLoaded);
scenarioMonitor.completePhase(MetricScenario.ApplicationLoad, ApplicationMetricPhase.SampleDataLoaded);
scenarioMonitor.startPhase(MetricScenario.ApplicationLoad, ApplicationMetricPhase.ExplorerInitialized);
scenarioMonitor.completePhase(MetricScenario.ApplicationLoad, ApplicationMetricPhase.ExplorerInitialized);
scenarioMonitor.completePhase(MetricScenario.ApplicationLoad, CommonMetricPhase.Interactive);

View File

@@ -42,19 +42,18 @@ export function useInteractive(scenario: MetricScenario, enabled = true) {
/**
* Hook to manage DatabaseLoad scenario phase completions.
* Tracks tree rendering and completes Interactive phase.
* Only completes DatabaseTreeRendered if the database fetch was successful.
* Only attempts to complete DatabaseTreeRendered if the database fetch was successful.
* Note: Scenario must be started before databases are fetched (in refreshExplorer).
*
* Calls scenarioMonitor directly (not via React context) for the same stability reason
* as useInteractive — avoids effect re-runs from unstable context function references.
* No one-shot guard is needed — completePhase is idempotent (ScenarioMonitor returns
* early if the phase hasn't been started yet, is already completed, or is already
* emitted). This lets the effect safely re-fire on every databaseTreeNodes change
* until the phase has actually been started via startPhase() in Explorer.tsx.
*/
export function useDatabaseLoadScenario(databaseTreeNodes: unknown[], fetchSucceeded: boolean) {
const hasCompletedTreeRenderRef = React.useRef(false);
// Track DatabaseTreeRendered phase (only if fetch succeeded)
React.useEffect(() => {
if (!hasCompletedTreeRenderRef.current && fetchSucceeded) {
hasCompletedTreeRenderRef.current = true;
if (fetchSucceeded) {
scenarioMonitor.completePhase(MetricScenario.DatabaseLoad, ApplicationMetricPhase.DatabaseTreeRendered);
}
}, [databaseTreeNodes, fetchSucceeded]);