Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(search-indexes): set up search indexes detection COMPASS-7196 #4815

Merged
merged 8 commits into from
Sep 8, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/collection-model/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ interface Collection {
isTimeSeries: boolean;
isClustered: boolean;
isFLE: boolean;
isSearchIndexesSupported: boolean;
sourceName?: string;
sourceReadonly?: boolean;
sourceViewon?: string;
Expand Down
15 changes: 15 additions & 0 deletions packages/collection-model/lib/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ const CollectionModel = AmpersandModel.extend(debounceActions(['fetch']), {
/**
* Fetches collection info and returns a special format of collection metadata
* that events like open-in-new-tab, select-namespace, edit-view require
* @param {{ dataService: import('mongodb-data-service').DataService }} dataService
*/
async fetchMetadata({ dataService }) {
try {
Expand All @@ -268,12 +269,26 @@ const CollectionModel = AmpersandModel.extend(debounceActions(['fetch']), {
// We don't care if it fails to get stats from server for any reason
}

/**
* The support for search indexes is a feature of a server not a collection.
* As this check can only be performed currently by running $listSearchIndexes
* aggregation stage against a collection, so we run it from the collection model.
* With this setup, when a user opens the first collection, we set this property
* on the instance model and then from there its value is read avoiding call to server.
*/
const isSearchIndexesSupported = await getParentByType(this, 'Instance')
.getIsSearchSupported({
dataService,
ns: this.ns,
});

const collectionMetadata = {
namespace: this.ns,
isReadonly: this.readonly,
isTimeSeries: this.isTimeSeries,
isClustered: this.clustered,
isFLE: this.fle2,
isSearchIndexesSupported,
};
if (this.sourceId) {
try {
Expand Down
21 changes: 21 additions & 0 deletions packages/compass-collection/src/modules/tabs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ export interface WorkspaceTabObject {
sourceReadonly?: boolean;
sourceViewOn?: string;
localAppRegistry: AppRegistry;
isSearchIndexesSupported: boolean;
}

/**
Expand Down Expand Up @@ -148,6 +149,7 @@ const doSelectNamespace = (state: State, action: AnyAction) => {
sourceReadonly: action.sourceReadonly,
sourceViewOn: action.sourceViewOn,
localAppRegistry: action.context.localAppRegistry,
isSearchIndexesSupported: action.isSearchIndexesSupported,
});
} else {
newState.push({ ...tab });
Expand Down Expand Up @@ -197,6 +199,7 @@ const doCreateTab = (state: State, action: AnyAction) => {
sourceReadonly: action.sourceReadonly,
sourceViewOn: action.sourceViewOn,
localAppRegistry: action.context.localAppRegistry,
isSearchIndexesSupported: action.isSearchIndexesSupported,
});
return newState;
};
Expand Down Expand Up @@ -413,6 +416,7 @@ export const createTab = ({
sourceViewOn,
query,
aggregation,
isSearchIndexesSupported,
}: Pick<
WorkspaceTabObject,
| 'id'
Expand All @@ -425,6 +429,7 @@ export const createTab = ({
| 'editViewName'
| 'sourceReadonly'
| 'sourceViewOn'
| 'isSearchIndexesSupported'
> & {
context: ContextProps;
query?: any; // TODO(COMPASS-6162): type query.
Expand All @@ -444,6 +449,7 @@ export const createTab = ({
sourceViewOn,
query,
aggregation,
isSearchIndexesSupported,
});

/**
Expand Down Expand Up @@ -475,6 +481,7 @@ export const selectNamespace = ({
context,
sourceReadonly,
sourceViewOn,
isSearchIndexesSupported,
}: Pick<
WorkspaceTabObject,
| 'id'
Expand All @@ -487,6 +494,7 @@ export const selectNamespace = ({
| 'editViewName'
| 'sourceReadonly'
| 'sourceViewOn'
| 'isSearchIndexesSupported'
> & {
context: ContextProps;
}): AnyAction => ({
Expand All @@ -502,6 +510,7 @@ export const selectNamespace = ({
context,
sourceReadonly,
sourceViewOn,
isSearchIndexesSupported,
});

/**
Expand Down Expand Up @@ -662,6 +671,7 @@ export const selectOrCreateTab = ({
sourceReadonly,
sourceViewOn,
sourcePipeline,
isSearchIndexesSupported,
}: Pick<
WorkspaceTabObject,
| 'namespace'
Expand All @@ -673,6 +683,7 @@ export const selectOrCreateTab = ({
| 'editViewName'
| 'sourceReadonly'
| 'sourceViewOn'
| 'isSearchIndexesSupported'
> & {
sourcePipeline: Document[];
}): ThunkAction<void, RootState, void, AnyAction> => {
Expand All @@ -694,6 +705,7 @@ export const selectOrCreateTab = ({
sourceReadonly,
sourceViewOn,
sourcePipeline,
isSearchIndexesSupported,
})
);
} else {
Expand All @@ -716,6 +728,7 @@ export const selectOrCreateTab = ({
sourceReadonly,
sourceViewOn,
sourcePipeline,
isSearchIndexesSupported,
})
);
// Clear the stats of the closed tab's namespace if it's the last one in use.
Expand Down Expand Up @@ -751,6 +764,7 @@ export const createNewTab = ({
sourcePipeline,
query,
aggregation,
isSearchIndexesSupported,
}: Pick<
WorkspaceTabObject,
| 'namespace'
Expand All @@ -762,6 +776,7 @@ export const createNewTab = ({
| 'editViewName'
| 'sourceReadonly'
| 'sourceViewOn'
| 'isSearchIndexesSupported'
> & {
sourcePipeline?: Document[];
query?: any; // TODO(COMPASS-6162): type query.
Expand All @@ -782,6 +797,7 @@ export const createNewTab = ({
sourcePipeline,
query,
aggregation,
isSearchIndexesSupported,
});
dispatch(
createTab({
Expand All @@ -798,6 +814,7 @@ export const createNewTab = ({
sourceViewOn,
query,
aggregation,
isSearchIndexesSupported,
})
);
showCollectionSubmenu({ isReadOnly: isReadonly });
Expand All @@ -821,6 +838,7 @@ export const replaceTabContent = ({
sourceReadonly,
sourceViewOn,
sourcePipeline,
isSearchIndexesSupported,
}: Pick<
WorkspaceTabObject,
| 'namespace'
Expand All @@ -832,6 +850,7 @@ export const replaceTabContent = ({
| 'editViewName'
| 'sourceReadonly'
| 'sourceViewOn'
| 'isSearchIndexesSupported'
> & {
sourcePipeline?: Document[];
}): ThunkAction<void, RootState, void, AnyAction> => {
Expand All @@ -848,6 +867,7 @@ export const replaceTabContent = ({
sourceName,
editViewName,
sourcePipeline,
isSearchIndexesSupported,
});
dispatch(
selectNamespace({
Expand All @@ -862,6 +882,7 @@ export const replaceTabContent = ({
context,
sourceReadonly: !!sourceReadonly,
sourceViewOn,
isSearchIndexesSupported,
})
);
showCollectionSubmenu({ isReadOnly: isReadonly });
Expand Down
5 changes: 5 additions & 0 deletions packages/compass-collection/src/stores/context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export type ContextProps = {
isDataLake?: boolean;
scopedModals?: any[];
connectionString?: string;
isSearchIndexesSupported?: boolean;
};

type ContextWithAppRegistry = ContextProps & {
Expand Down Expand Up @@ -123,6 +124,7 @@ const setupStore = ({
query,
aggregation,
connectionString,
isSearchIndexesSupported,
}: ContextWithAppRegistry & { role: Role }) => {
if (!role.storeName || !role.configureStore) {
return;
Expand All @@ -149,6 +151,7 @@ const setupStore = ({
query,
aggregation,
connectionString,
isSearchIndexesSupported,
});
localAppRegistry.registerStore(role.storeName, store);

Expand Down Expand Up @@ -359,6 +362,7 @@ const createContext = ({
sourcePipeline,
query,
aggregation,
isSearchIndexesSupported,
}: ContextProps): ContextProps => {
const serverVersion = state.serverVersion;
const localAppRegistry = new AppRegistry();
Expand Down Expand Up @@ -405,6 +409,7 @@ const createContext = ({
sourcePipeline,
query,
aggregation,
isSearchIndexesSupported,
});

// Add the tab.
Expand Down
2 changes: 2 additions & 0 deletions packages/compass-collection/src/stores/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ store.onActivated = (appRegistry: AppRegistry) => {
sourcePipeline: metadata.sourcePipeline,
query: metadata.query,
aggregation: metadata.aggregation,
isSearchIndexesSupported: metadata.isSearchIndexesSupported,
})
);
});
Expand Down Expand Up @@ -268,6 +269,7 @@ store.onActivated = (appRegistry: AppRegistry) => {
sourceReadonly: metadata.sourceReadonly,
sourceViewOn: metadata.sourceViewOn,
sourcePipeline: metadata.sourcePipeline,
isSearchIndexesSupported: metadata.isSearchIndexesSupported,
})
);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const renderIndexes = (
dropFailedIndex={() => {}}
onHideIndex={() => {}}
onUnhideIndex={() => {}}
isAtlasSearchSupported={false}
{...props}
/>
);
Expand Down
7 changes: 6 additions & 1 deletion packages/compass-indexes/src/components/indexes/indexes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import type {
import { IndexesToolbar } from '../indexes-toolbar/indexes-toolbar';
import { IndexesTable } from '../indexes-table/indexes-table';
import type { RootState } from '../../modules';
import { SearchIndexesStatuses } from '../../modules/search-indexes';

const containerStyles = css({
margin: spacing[3],
Expand All @@ -44,6 +45,7 @@ type IndexesProps = {
onHideIndex: (name: string) => void;
onUnhideIndex: (name: string) => void;
readOnly?: boolean;
isAtlasSearchSupported: boolean;
};

// This constant is used as a trigger to show an insight whenever number of
Expand All @@ -65,6 +67,7 @@ export const Indexes: React.FunctionComponent<IndexesProps> = ({
onHideIndex,
onUnhideIndex,
readOnly, // preferences readOnly.
isAtlasSearchSupported,
}) => {
const deleteIndex = (index: IndexDefinition) => {
if (index.extra.status === 'failed') {
Expand All @@ -85,7 +88,7 @@ export const Indexes: React.FunctionComponent<IndexesProps> = ({
isRefreshing={isRefreshing}
writeStateDescription={description}
hasTooManyIndexes={indexes.length > IDEAL_NUMBER_OF_MAX_INDEXES}
isAtlasSearchSupported={true}
isAtlasSearchSupported={isAtlasSearchSupported}
onRefreshIndexes={refreshIndexes}
/>
{!isReadonlyView && !error && (
Expand All @@ -110,6 +113,7 @@ const mapState = ({
serverVersion,
appRegistry,
regularIndexes: { indexes, isRefreshing, error },
searchIndexes: { status },
}: RootState) => ({
indexes,
isWritable,
Expand All @@ -119,6 +123,7 @@ const mapState = ({
localAppRegistry: (appRegistry as any).localAppRegistry,
isRefreshing,
serverVersion,
isAtlasSearchSupported: status !== SearchIndexesStatuses.NOT_AVAILABLE,
});

const mapDispatch = {
Expand Down
5 changes: 5 additions & 0 deletions packages/compass-indexes/src/modules/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ import description, {
import regularIndexes, {
INITIAL_STATE as REGULAR_INDEXES_INITIAL_STATE,
} from './regular-indexes';
import searchIndexes, {
INITIAL_STATE as SEARCH_INDEXES_INITIAL_STATE,
} from './search-indexes';
import serverVersion, {
INITIAL_STATE as SV_INITIAL_STATE,
} from './server-version';
Expand All @@ -31,6 +34,7 @@ const reducer = combineReducers({
serverVersion,
namespace,
regularIndexes,
searchIndexes,
});

export type RootState = ReturnType<typeof reducer>;
Expand All @@ -45,6 +49,7 @@ const rootReducer = (state: RootState, action: AnyAction): RootState => {
serverVersion: SV_INITIAL_STATE,
namespace: NAMESPACE_INITIAL_STATE,
regularIndexes: REGULAR_INDEXES_INITIAL_STATE,
searchIndexes: SEARCH_INDEXES_INITIAL_STATE,
};
}
return reducer(state, action);
Expand Down
26 changes: 26 additions & 0 deletions packages/compass-indexes/src/modules/search-indexes.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { expect } from 'chai';
import type { Store } from 'redux';
import { SearchIndexesStatuses, setStatus } from './search-indexes';
import configureStore from '../stores/store';
import type { RootState } from '.';

describe('search-indexes module', function () {
let store: Store<RootState>;

beforeEach(function () {
store = configureStore({ namespace: 'citibike.trips' });
});

it('has not available search indexes state by default', function () {
expect(store.getState().searchIndexes.status).to.equal(
SearchIndexesStatuses.NOT_AVAILABLE
);
});

it('sets the status of the search indexes', function () {
store.dispatch(setStatus(SearchIndexesStatuses.PENDING));
expect(store.getState().searchIndexes.status).to.equal(
SearchIndexesStatuses.PENDING
);
});
});
Loading