Skip to content

Commit 44f499c

Browse files
committed
fixup: distinct stop analysis and cleanup actions, improve traversal value setting
1 parent 7b69069 commit 44f499c

File tree

6 files changed

+67
-61
lines changed

6 files changed

+67
-61
lines changed

packages/compass-schema/src/components/compass-schema.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,7 @@ export default connect(
446446
}),
447447
{
448448
onStartAnalysis: startAnalysis,
449-
onStopAnalysis: () => stopAnalysis(true),
449+
onStopAnalysis: () => stopAnalysis(),
450450
onExportSchemaClicked: openExportSchema,
451451
}
452452
)(Schema);

packages/compass-schema/src/modules/schema-analysis.spec.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,6 @@ describe('schema-analysis', function () {
573573
Number: 1,
574574
Boolean: 1,
575575
String: 4,
576-
Undefined: 3,
577576
});
578577
});
579578
});
@@ -604,7 +603,6 @@ describe('schema-analysis', function () {
604603
const { field_types } = await calculateSchemaMetadata(schema);
605604
expect(field_types).to.deep.equal({
606605
Number: 3,
607-
Undefined: 1,
608606
});
609607
});
610608
});
@@ -636,7 +634,6 @@ describe('schema-analysis', function () {
636634
Array: 4,
637635
String: 2,
638636
Number: 3,
639-
Undefined: 1,
640637
});
641638
});
642639
});

packages/compass-schema/src/modules/schema-analysis.ts

Lines changed: 20 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -139,22 +139,23 @@ export async function calculateSchemaMetadata(schema: Schema): Promise<{
139139
let variableTypeCount = 0;
140140
let optionalFieldCount = 0;
141141
let unblockThreadCounter = 0;
142+
let deepestPath = 0;
142143

143144
async function traverseSchemaTree(
144145
fieldsOrTypes: SchemaField[] | SchemaType[],
145-
isRoot = false
146-
): Promise<number> {
146+
depth: number
147+
): Promise<void> {
147148
unblockThreadCounter++;
148149
if (unblockThreadCounter === UNBLOCK_INTERVAL_COUNT) {
149150
unblockThreadCounter = 0;
150151
await unblockThread();
151152
}
152153

153154
if (!fieldsOrTypes || fieldsOrTypes.length === 0) {
154-
return 0;
155+
return;
155156
}
156157

157-
let deepestPath = 1;
158+
deepestPath = Math.max(depth, deepestPath);
158159

159160
for (const fieldOrType of fieldsOrTypes) {
160161
if (
@@ -170,9 +171,11 @@ export async function calculateSchemaMetadata(schema: Schema): Promise<{
170171
}
171172

172173
if (isSchemaType(fieldOrType)) {
173-
fieldTypes[fieldOrType.bsonType] =
174-
(fieldTypes[fieldOrType.bsonType] ?? 0) + 1;
175-
} else if (isRoot) {
174+
if (fieldOrType.bsonType !== 'Undefined') {
175+
fieldTypes[fieldOrType.bsonType] =
176+
(fieldTypes[fieldOrType.bsonType] ?? 0) + 1;
177+
}
178+
} else if (depth === 1 /* is root level */) {
176179
// Count variable types (more than one unique type excluding undefined).
177180
if (
178181
fieldOrType.types &&
@@ -188,41 +191,31 @@ export async function calculateSchemaMetadata(schema: Schema): Promise<{
188191
}
189192

190193
if ((fieldOrType as DocumentSchemaType).bsonType === 'Document') {
191-
const deepestFieldPath =
192-
(await traverseSchemaTree(
193-
(fieldOrType as DocumentSchemaType).fields
194-
)) + 1; /* Increment by one when we go a level deeper. */
195-
196-
deepestPath = Math.max(deepestFieldPath, deepestPath);
194+
await traverseSchemaTree(
195+
(fieldOrType as DocumentSchemaType).fields,
196+
depth + 1 // Increment by one when we go a level deeper.
197+
);
197198
} else if (
198199
(fieldOrType as ArraySchemaType).bsonType === 'Array' ||
199200
(fieldOrType as SchemaField).types
200201
) {
201-
// Increment by one when we go a level deeper.
202202
const increment =
203203
(fieldOrType as ArraySchemaType).bsonType === 'Array' ? 1 : 0;
204-
const deepestFieldPath =
205-
(await traverseSchemaTree(
206-
(fieldOrType as ArraySchemaType | SchemaField).types
207-
)) + increment;
208-
209-
deepestPath = Math.max(deepestFieldPath, deepestPath);
204+
await traverseSchemaTree(
205+
(fieldOrType as ArraySchemaType | SchemaField).types,
206+
depth + increment // Increment by one when we go a level deeper.
207+
);
210208
}
211209
}
212-
213-
return deepestPath;
214210
}
215211

216-
const schemaDepth = await traverseSchemaTree(
217-
schema.fields,
218-
true /* isRoot */
219-
);
212+
await traverseSchemaTree(schema.fields, 1);
220213

221214
return {
222215
field_types: fieldTypes,
223216
geo_data: hasGeoData,
224217
optional_field_count: optionalFieldCount,
225-
schema_depth: schemaDepth,
218+
schema_depth: deepestPath,
226219
variable_type_count: variableTypeCount,
227220
};
228221
}

packages/compass-schema/src/stores/schema-analysis-reducer.ts

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const ERROR_CODE_MAX_TIME_MS_EXPIRED = 50;
2929

3030
export type SchemaAnalysisState = {
3131
analysisState: AnalysisState;
32+
analysisStartTime?: number;
3233
errorMessage: string;
3334
schema: Schema | null;
3435
resultId: string;
@@ -42,6 +43,7 @@ export const enum SchemaAnalysisActions {
4243

4344
export type AnalysisStartedAction = {
4445
type: SchemaAnalysisActions.analysisStarted;
46+
analysisStartTime: number;
4547
};
4648

4749
export type AnalysisFinishedAction = {
@@ -66,6 +68,7 @@ export const schemaAnalysisReducer: Reducer<SchemaAnalysisState, Action> = (
6668
) {
6769
return {
6870
...state,
71+
analysisStartTime: action.analysisStartTime,
6972
analysisState: ANALYSIS_STATE_ANALYZING,
7073
errorMessage: '',
7174
schema: null,
@@ -164,19 +167,34 @@ export const geoLayersDeleted = (
164167
};
165168
};
166169

167-
// We track when the user cancels the analysis. We use the userCancelled
168-
// flag to indicate if we should track, as we also automatically stop
169-
// analysis when deactivating the plugin.
170-
const userCancelledAnalysisAbortReason = 'Cancelled analysis';
170+
export const stopAnalysis = (): SchemaThunkAction<void> => {
171+
return (
172+
dispatch,
173+
getState,
174+
{ analysisAbortControllerRef, connectionInfoRef, queryBar, track }
175+
) => {
176+
if (!analysisAbortControllerRef.current) return;
177+
const analysisTime =
178+
Date.now() - (getState().schemaAnalysis.analysisStartTime ?? 0);
179+
180+
const query = queryBar.getLastAppliedQuery('schema');
181+
track(
182+
'Schema Analysis Cancelled',
183+
{
184+
analysis_time_ms: analysisTime,
185+
with_filter: Object.entries(query.filter ?? {}).length > 0,
186+
},
187+
connectionInfoRef.current
188+
);
189+
190+
analysisAbortControllerRef.current?.abort('Analysis cancelled');
191+
};
192+
};
171193

172-
export const stopAnalysis = (
173-
userCancelled = false
174-
): SchemaThunkAction<void> => {
194+
export const cleanupAnalysis = (): SchemaThunkAction<void> => {
175195
return (dispatch, getState, { analysisAbortControllerRef }) => {
176196
if (!analysisAbortControllerRef.current) return;
177-
analysisAbortControllerRef.current?.abort(
178-
userCancelled ? userCancelledAnalysisAbortReason : undefined
179-
);
197+
analysisAbortControllerRef.current?.abort();
180198
};
181199
};
182200

@@ -271,7 +289,10 @@ export const startAnalysis = (): SchemaThunkAction<
271289
try {
272290
debug('analysis started');
273291

274-
dispatch({ type: SchemaAnalysisActions.analysisStarted });
292+
dispatch({
293+
type: SchemaAnalysisActions.analysisStarted,
294+
analysisStartTime,
295+
});
275296

276297
const schemaAccessor = await analyzeSchema(
277298
dataService,
@@ -316,21 +337,6 @@ export const startAnalysis = (): SchemaThunkAction<
316337

317338
geoLayersRef.current = {};
318339
} catch (err: any) {
319-
if (
320-
abortSignal.aborted &&
321-
abortSignal.reason === userCancelledAnalysisAbortReason
322-
) {
323-
const analysisTime = Date.now() - analysisStartTime;
324-
track(
325-
'Schema Analysis Cancelled',
326-
{
327-
analysis_time_ms: analysisTime,
328-
with_filter: Object.entries(query.filter ?? {}).length > 0,
329-
},
330-
connectionInfoRef.current
331-
);
332-
}
333-
334340
log.error(
335341
mongoLogId(1_001_000_188),
336342
'Schema analysis',

packages/compass-schema/src/stores/store.spec.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,17 @@ describe('Schema Store', function () {
112112
sampleStub.resolves([{ name: 'Hans' }, { name: 'Greta' }]);
113113
await store.dispatch(startAnalysis());
114114
expect(sampleStub).to.have.been.called;
115-
const { analysisState, errorMessage, schema, resultId } =
116-
store.getState().schemaAnalysis;
115+
const {
116+
analysisState,
117+
errorMessage,
118+
schema,
119+
resultId,
120+
analysisStartTime,
121+
} = store.getState().schemaAnalysis;
117122
expect(analysisState).to.equal('complete');
118123
expect(!!errorMessage).to.be.false;
124+
expect(analysisStartTime).to.not.be.undefined;
125+
expect(analysisStartTime).to.be.greaterThan(1000);
119126
expect(schema).not.to.be.null;
120127
expect(resultId).not.to.equal(oldResultId);
121128
});

packages/compass-schema/src/stores/store.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@ import type { FieldStoreService } from '@mongodb-js/compass-field-store';
1818
import type { QueryBarService } from '@mongodb-js/compass-query-bar';
1919
import type { TrackFunction } from '@mongodb-js/compass-telemetry';
2020
import type { SchemaAccessor } from 'mongodb-schema';
21-
import { schemaAnalysisReducer, stopAnalysis } from './schema-analysis-reducer';
21+
import {
22+
schemaAnalysisReducer,
23+
cleanupAnalysis,
24+
} from './schema-analysis-reducer';
2225
import {
2326
cancelExportSchema,
2427
confirmedExportLegacySchemaToClipboard,
@@ -88,7 +91,7 @@ export function activateSchemaPlugin(
8891
store.dispatch(confirmedExportLegacySchemaToClipboard());
8992
});
9093

91-
addCleanup(() => store.dispatch(stopAnalysis()));
94+
addCleanup(() => store.dispatch(cleanupAnalysis()));
9295
addCleanup(() => store.dispatch(cancelExportSchema()));
9396

9497
return {

0 commit comments

Comments
 (0)