diff --git a/packages/compass-schema/src/components/schema-toolbar/schema-toolbar.spec.tsx b/packages/compass-schema/src/components/schema-toolbar/schema-toolbar.spec.tsx index 1e86ef32a5c..71c811aaff5 100644 --- a/packages/compass-schema/src/components/schema-toolbar/schema-toolbar.spec.tsx +++ b/packages/compass-schema/src/components/schema-toolbar/schema-toolbar.spec.tsx @@ -3,11 +3,7 @@ import React from 'react'; import { render, screen } from '@mongodb-js/testing-library-compass'; import { expect } from 'chai'; import sinon from 'sinon'; -import { - createSandboxFromDefaultPreferences, - type PreferencesAccess, -} from 'compass-preferences-model'; -import { PreferencesProvider } from 'compass-preferences-model/provider'; +import type { AllPreferences } from 'compass-preferences-model'; import { SchemaToolbar } from './schema-toolbar'; import QueryBarPlugin from '@mongodb-js/compass-query-bar'; import { @@ -35,33 +31,28 @@ const testErrorMessage = const exportSchemaTestId = 'open-schema-export-button'; describe('SchemaToolbar', function () { - let defaultPreferences: PreferencesAccess; - - before(async function () { - defaultPreferences = await createSandboxFromDefaultPreferences(); - }); - const renderSchemaToolbar = ( props: Partial> = {}, - preferences: PreferencesAccess = defaultPreferences + preferences: Partial = {} ) => { const queryBarProps = {}; render( - - - {}} - onResetClicked={() => {}} - sampleSize={10} - schemaResultId="123" - onExportSchemaClicked={() => {}} - {...props} - /> - - + + {}} + onResetClicked={() => {}} + sampleSize={10} + schemaResultId="123" + onExportSchemaClicked={() => {}} + {...props} + /> + , + { + preferences, + } ); }; @@ -125,17 +116,14 @@ describe('SchemaToolbar', function () { }); describe('when rendered with the enableExportSchema feature flag true', function () { - beforeEach(async function () { - const preferences = await createSandboxFromDefaultPreferences(); - await preferences.savePreferences({ - enableExportSchema: true, - }); - + beforeEach(function () { renderSchemaToolbar( { sampleSize: 100, }, - preferences + { + enableExportSchema: true, + } ); }); diff --git a/packages/compass-schema/src/modules/schema-analysis.spec.ts b/packages/compass-schema/src/modules/schema-analysis.spec.ts index b91ce702e1c..04b7b90d88e 100644 --- a/packages/compass-schema/src/modules/schema-analysis.spec.ts +++ b/packages/compass-schema/src/modules/schema-analysis.spec.ts @@ -196,7 +196,7 @@ describe('schema-analysis', function () { ); }); - it('returns null if is cancelled', async function () { + it('returns undefined if is cancelled', async function () { const dataService = { sample: () => Promise.reject(new Error('test error')), isCancelError: () => true, @@ -214,7 +214,7 @@ describe('schema-analysis', function () { dummyLogger ); - expect(result).to.equal(null); + expect(result).to.equal(undefined); }); it('throws if sample throws', async function () { diff --git a/packages/compass-schema/src/modules/schema-analysis.ts b/packages/compass-schema/src/modules/schema-analysis.ts index 0774f9a54b8..aaa5193979a 100644 --- a/packages/compass-schema/src/modules/schema-analysis.ts +++ b/packages/compass-schema/src/modules/schema-analysis.ts @@ -2,6 +2,7 @@ import type { AggregateOptions, Filter, Document } from 'mongodb'; import { analyzeDocuments } from 'mongodb-schema'; import type { Schema, + SchemaAccessor, ArraySchemaType, DocumentSchemaType, SchemaField, @@ -35,8 +36,6 @@ function promoteMongoErrorCode(err?: Error & { code?: unknown }) { return err; } -export type SchemaAccessor = Awaited>; - export const analyzeSchema = async ( dataService: DataService, abortSignal: AbortSignal, @@ -50,7 +49,7 @@ export const analyzeSchema = async ( | undefined, aggregateOptions: AggregateOptions, { log, mongoLogId, debug }: Logger -): Promise => { +): Promise => { try { log.info(mongoLogId(1001000089), 'Schema', 'Starting schema analysis', { ns, @@ -82,7 +81,7 @@ export const analyzeSchema = async ( }); if (dataService.isCancelError(err)) { debug('caught background operation terminated error', err); - return null; + return; } const error = promoteMongoErrorCode(err); diff --git a/packages/compass-schema/src/stores/schema-analysis-reducer.ts b/packages/compass-schema/src/stores/schema-analysis-reducer.ts index c6a5648d4f5..14f8ec13047 100644 --- a/packages/compass-schema/src/stores/schema-analysis-reducer.ts +++ b/packages/compass-schema/src/stores/schema-analysis-reducer.ts @@ -14,7 +14,6 @@ import { addLayer, generateGeoQuery } from '../modules/geo'; import { analyzeSchema, calculateSchemaDepth, - type SchemaAccessor, schemaContainsGeoData, } from '../modules/schema-analysis'; import { capMaxTimeMSAtPreferenceLimit } from 'compass-preferences-model/provider'; @@ -32,7 +31,6 @@ export type SchemaAnalysisState = { analysisState: AnalysisState; errorMessage: string; schema: Schema | null; - schemaAccessor: SchemaAccessor | null; resultId: string; }; @@ -48,7 +46,6 @@ export type AnalysisStartedAction = { export type AnalysisFinishedAction = { type: SchemaAnalysisActions.analysisFinished; - schemaAccessor: SchemaAccessor | null; schema: Schema | null; }; @@ -72,7 +69,6 @@ export const schemaAnalysisReducer: Reducer = ( analysisState: ANALYSIS_STATE_ANALYZING, errorMessage: '', schema: null, - schemaAccessor: null, }; } @@ -88,7 +84,6 @@ export const schemaAnalysisReducer: Reducer = ( ? ANALYSIS_STATE_COMPLETE : ANALYSIS_STATE_INITIAL, schema: action.schema, - schemaAccessor: action.schemaAccessor, resultId: resultId(), }; } @@ -129,7 +124,6 @@ const getInitialState = (): SchemaAnalysisState => ({ analysisState: ANALYSIS_STATE_INITIAL, errorMessage: '', schema: null, - schemaAccessor: null, resultId: resultId(), }); @@ -171,9 +165,9 @@ export const geoLayersDeleted = ( }; export const stopAnalysis = (): SchemaThunkAction => { - return (dispatch, getState, { abortControllerRef }) => { - if (!abortControllerRef.current) return; - abortControllerRef.current?.abort(); + return (dispatch, getState, { analysisAbortControllerRef }) => { + if (!analysisAbortControllerRef.current) return; + analysisAbortControllerRef.current?.abort(); }; }; @@ -191,7 +185,8 @@ export const startAnalysis = (): SchemaThunkAction< dataService, logger, fieldStoreService, - abortControllerRef, + analysisAbortControllerRef, + schemaAccessorRef, namespace, geoLayersRef, connectionInfoRef, @@ -221,8 +216,8 @@ export const startAnalysis = (): SchemaThunkAction< maxTimeMS: capMaxTimeMSAtPreferenceLimit(preferences, query.maxTimeMS), }; - abortControllerRef.current = new AbortController(); - const abortSignal = abortControllerRef.current.signal; + analysisAbortControllerRef.current = new AbortController(); + const abortSignal = analysisAbortControllerRef.current.signal; try { debug('analysis started'); @@ -238,6 +233,7 @@ export const startAnalysis = (): SchemaThunkAction< driverOptions, logger ); + schemaAccessorRef.current = schemaAccessor; let schema: Schema | null = null; if (schemaAccessor) { schema = await schemaAccessor.getInternalSchema(); @@ -254,7 +250,6 @@ export const startAnalysis = (): SchemaThunkAction< dispatch({ type: SchemaAnalysisActions.analysisFinished, schema, - schemaAccessor, }); // track schema analyzed @@ -282,7 +277,7 @@ export const startAnalysis = (): SchemaThunkAction< error: err as Error, }); } finally { - abortControllerRef.current = undefined; + analysisAbortControllerRef.current = undefined; } }; }; diff --git a/packages/compass-schema/src/stores/schema-export-reducer.ts b/packages/compass-schema/src/stores/schema-export-reducer.ts index ddb1e6c925f..80d0f8ec64f 100644 --- a/packages/compass-schema/src/stores/schema-export-reducer.ts +++ b/packages/compass-schema/src/stores/schema-export-reducer.ts @@ -5,6 +5,7 @@ import type { InternalSchema, MongoDBJSONSchema, ExpandedJSONSchema, + SchemaAccessor, } from 'mongodb-schema'; import type { SchemaThunkAction } from './store'; @@ -12,7 +13,6 @@ import { isAction } from '../utils'; import { calculateSchemaDepth, schemaContainsGeoData, - type SchemaAccessor, } from '../modules/schema-analysis'; import { openToast } from '@mongodb-js/compass-components'; @@ -23,7 +23,6 @@ export type SchemaFormat = | 'legacyJSON'; export type ExportStatus = 'inprogress' | 'complete' | 'error'; export type SchemaExportState = { - abortController?: AbortController; isOpen: boolean; isLegacyBannerOpen: boolean; legacyBannerChoice?: 'legacy' | 'export'; @@ -81,11 +80,8 @@ export const closeExportSchema = (): SchemaThunkAction< void, CloseExportSchemaAction > => { - return (dispatch, getState) => { - const { - schemaExport: { abortController }, - } = getState(); - abortController?.abort(); + return (dispatch, getState, { exportAbortControllerRef }) => { + exportAbortControllerRef.current?.abort(); return dispatch({ type: SchemaExportActions.closeExportSchema, @@ -99,7 +95,6 @@ export type CancelExportSchemaAction = { export type ChangeExportSchemaFormatStartedAction = { type: SchemaExportActions.changeExportSchemaFormatStarted; - abortController: AbortController; exportFormat: SchemaFormat; }; @@ -117,11 +112,8 @@ export const cancelExportSchema = (): SchemaThunkAction< void, CancelExportSchemaAction > => { - return (dispatch, getState) => { - const { - schemaExport: { abortController }, - } = getState(); - abortController?.abort(); + return (dispatch, getState, { exportAbortControllerRef }) => { + exportAbortControllerRef.current?.abort(); return dispatch({ type: SchemaExportActions.cancelExportSchema, @@ -169,19 +161,19 @@ export const changeExportSchemaFormat = ( | ChangeExportSchemaFormatErroredAction | ChangeExportSchemaFormatCompletedAction > => { - return async (dispatch, getState, { logger: { log } }) => { - const { - schemaExport: { abortController: existingAbortController }, - } = getState(); - + return async ( + dispatch, + getState, + { logger: { log }, exportAbortControllerRef, schemaAccessorRef } + ) => { // If we're already in progress we abort their current operation. - existingAbortController?.abort(); + exportAbortControllerRef.current?.abort(); - const abortController = new AbortController(); + exportAbortControllerRef.current = new AbortController(); + const abortSignal = exportAbortControllerRef.current.signal; dispatch({ type: SchemaExportActions.changeExportSchemaFormatStarted, - abortController, exportFormat, }); @@ -196,7 +188,7 @@ export const changeExportSchemaFormat = ( } ); - const schemaAccessor = getState().schemaAnalysis.schemaAccessor; + const schemaAccessor = schemaAccessorRef.current; if (!schemaAccessor) { throw new Error('No schema analysis available'); } @@ -204,10 +196,10 @@ export const changeExportSchemaFormat = ( exportedSchema = await getSchemaByFormat({ schemaAccessor, exportFormat, - signal: abortController.signal, + signal: abortSignal, }); } catch (err: any) { - if (abortController.signal.aborted) { + if (abortSignal.aborted) { return; } log.error( @@ -226,7 +218,7 @@ export const changeExportSchemaFormat = ( return; } - if (abortController.signal.aborted) { + if (abortSignal.aborted) { return; } @@ -319,7 +311,6 @@ export const schemaExportReducer: Reducer = ( ) { return { ...state, - abortController: action.abortController, exportStatus: 'inprogress', exportFormat: action.exportFormat, }; diff --git a/packages/compass-schema/src/stores/store.ts b/packages/compass-schema/src/stores/store.ts index 2a7bcf4bddc..4f6c386d9c9 100644 --- a/packages/compass-schema/src/stores/store.ts +++ b/packages/compass-schema/src/stores/store.ts @@ -17,6 +17,7 @@ import type { PreferencesAccess } from 'compass-preferences-model/provider'; import type { FieldStoreService } from '@mongodb-js/compass-field-store'; import type { QueryBarService } from '@mongodb-js/compass-query-bar'; import type { TrackFunction } from '@mongodb-js/compass-telemetry'; +import type { SchemaAccessor } from 'mongodb-schema'; import { schemaAnalysisReducer, stopAnalysis } from './schema-analysis-reducer'; import { cancelExportSchema, @@ -46,7 +47,9 @@ export const rootReducer = combineReducers({ export type RootState = ReturnType; export type SchemaExtraArgs = SchemaPluginServices & { - abortControllerRef: { current?: AbortController }; + analysisAbortControllerRef: { current?: AbortController }; + exportAbortControllerRef: { current?: AbortController }; + schemaAccessorRef: { current?: SchemaAccessor }; geoLayersRef: { current: Record }; namespace: string; }; @@ -100,7 +103,13 @@ export function configureStore( services: SchemaPluginServices, namespace: string ) { - const abortControllerRef = { + const analysisAbortControllerRef = { + current: undefined, + }; + const exportAbortControllerRef = { + current: undefined, + }; + const schemaAccessorRef = { current: undefined, }; const geoLayersRef: { current: Record } = { @@ -111,7 +120,9 @@ export function configureStore( applyMiddleware( thunk.withExtraArgument({ ...services, - abortControllerRef, + analysisAbortControllerRef, + exportAbortControllerRef, + schemaAccessorRef, geoLayersRef, namespace, })