-
Notifications
You must be signed in to change notification settings - Fork 193
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: do not allow opening a new connection when the limit is reached C…
…OMPASS-7727 (#5624) * chore: draft, limit number of maximum open connections * chore: remove console.log * chore: put use-all-saved-connections under test * chore: enable tests * chore: add tests to hook * chore: remove .only * chore: add clue on what to do when the limit is reached * chore: add new tests * chore: fix bootstrap * chore: fix linter * chore: fix linting issues * chore: use useActiveConnections hook instead of a new hook * chore: rename toggle
- Loading branch information
Showing
12 changed files
with
284 additions
and
24 deletions.
There are no files selected for viewing
File renamed without changes.
File renamed without changes.
146 changes: 146 additions & 0 deletions
146
packages/compass-connections/src/hooks/use-can-open-new-connections.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
import { expect } from 'chai'; | ||
import { waitFor } from '@testing-library/react'; | ||
import { renderHook } from '@testing-library/react-hooks'; | ||
import { createElement } from 'react'; | ||
import { | ||
type ConnectionInfo, | ||
type ConnectionStatus, | ||
} from '@mongodb-js/connection-info'; | ||
import { | ||
type PreferencesAccess, | ||
createSandboxFromDefaultPreferences, | ||
} from 'compass-preferences-model'; | ||
import { PreferencesProvider } from 'compass-preferences-model/provider'; | ||
import { ConnectionsManager, ConnectionsManagerProvider } from '../provider'; | ||
import { | ||
ConnectionRepositoryContextProvider, | ||
type ConnectionStorage, | ||
ConnectionStorageContext, | ||
} from '@mongodb-js/connection-storage/provider'; | ||
import { ConnectionStorageBus } from '@mongodb-js/connection-storage/renderer'; | ||
import { useCanOpenNewConnections } from './use-can-open-new-connections'; | ||
|
||
const FAVORITE_CONNECTION_INFO: ConnectionInfo = { | ||
id: 'favorite', | ||
connectionOptions: { | ||
connectionString: 'mongodb://localhost:27017', | ||
}, | ||
savedConnectionType: 'favorite', | ||
}; | ||
|
||
const NONFAVORITE_CONNECTION_INFO: ConnectionInfo = { | ||
id: 'nonfavorite', | ||
connectionOptions: { | ||
connectionString: 'mongodb://localhost:27017', | ||
}, | ||
savedConnectionType: 'recent', | ||
}; | ||
|
||
describe('useCanOpenNewConnections', function () { | ||
let renderHookWithContext: typeof renderHook; | ||
let connectionStorage: ConnectionStorage; | ||
let connectionManager: ConnectionsManager; | ||
let preferencesAccess: PreferencesAccess; | ||
|
||
function withConnectionWithStatus( | ||
connectionId: ConnectionInfo['id'], | ||
status: ConnectionStatus | ||
) { | ||
const connectionManagerInspectable = connectionManager as any; | ||
connectionManagerInspectable.connectionStatuses.set(connectionId, status); | ||
} | ||
|
||
async function withConnectionLimit(limit: number) { | ||
await preferencesAccess.savePreferences({ | ||
maximumNumberOfActiveConnections: limit, | ||
}); | ||
} | ||
beforeEach(async function () { | ||
preferencesAccess = await createSandboxFromDefaultPreferences(); | ||
connectionManager = new ConnectionsManager({} as any); | ||
connectionStorage = { | ||
loadAll() { | ||
return Promise.resolve([ | ||
FAVORITE_CONNECTION_INFO, | ||
NONFAVORITE_CONNECTION_INFO, | ||
]); | ||
}, | ||
events: new ConnectionStorageBus(), | ||
} as ConnectionStorage; | ||
|
||
renderHookWithContext = (callback, options) => { | ||
const wrapper: React.FC = ({ children }) => | ||
createElement(PreferencesProvider, { | ||
value: preferencesAccess, | ||
children: [ | ||
createElement(ConnectionStorageContext.Provider, { | ||
value: connectionStorage, | ||
children: [ | ||
createElement(ConnectionRepositoryContextProvider, { | ||
children: [ | ||
createElement(ConnectionsManagerProvider, { | ||
value: connectionManager, | ||
children, | ||
}), | ||
], | ||
}), | ||
], | ||
}), | ||
], | ||
}); | ||
return renderHook(callback, { wrapper, ...options }); | ||
}; | ||
}); | ||
|
||
describe('number of active connections', function () { | ||
it('should return the count of active connections', async function () { | ||
withConnectionWithStatus(FAVORITE_CONNECTION_INFO.id, 'connected'); | ||
|
||
const { result } = renderHookWithContext(() => | ||
useCanOpenNewConnections() | ||
); | ||
|
||
await waitFor(() => { | ||
const { numberOfConnectionsOpen } = result.current; | ||
expect(numberOfConnectionsOpen).to.equal(1); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('connection limiting', function () { | ||
it('should not limit when the maximum number of connections is not reached', async function () { | ||
await withConnectionLimit(1); | ||
|
||
const { result } = renderHookWithContext(() => | ||
useCanOpenNewConnections() | ||
); | ||
|
||
await waitFor(() => { | ||
const { numberOfConnectionsOpen, canOpenNewConnection } = | ||
result.current; | ||
expect(numberOfConnectionsOpen).to.equal(0); | ||
expect(canOpenNewConnection).to.equal(true); | ||
}); | ||
}); | ||
|
||
it('should limit when the maximum number of connections is reached', async function () { | ||
withConnectionWithStatus(FAVORITE_CONNECTION_INFO.id, 'connected'); | ||
await withConnectionLimit(1); | ||
|
||
const { result } = renderHookWithContext(() => | ||
useCanOpenNewConnections() | ||
); | ||
|
||
await waitFor(() => { | ||
const { | ||
numberOfConnectionsOpen, | ||
canOpenNewConnection, | ||
canNotOpenReason, | ||
} = result.current; | ||
expect(numberOfConnectionsOpen).to.equal(1); | ||
expect(canOpenNewConnection).to.equal(false); | ||
expect(canNotOpenReason).to.equal('maximum-number-exceeded'); | ||
}); | ||
}); | ||
}); | ||
}); |
29 changes: 29 additions & 0 deletions
29
packages/compass-connections/src/hooks/use-can-open-new-connections.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { useActiveConnections } from './use-active-connections'; | ||
import { usePreference } from 'compass-preferences-model/provider'; | ||
|
||
export type CanNotOpenConnectionReason = 'maximum-number-exceeded'; | ||
|
||
export function useCanOpenNewConnections(): { | ||
numberOfConnectionsOpen: number; | ||
maximumNumberOfConnectionsOpen: number; | ||
canOpenNewConnection: boolean; | ||
canNotOpenReason?: CanNotOpenConnectionReason; | ||
} { | ||
const activeConnections = useActiveConnections(); | ||
const maximumNumberOfConnectionsOpen = | ||
usePreference('maximumNumberOfActiveConnections') ?? 1; | ||
|
||
const numberOfConnectionsOpen = activeConnections.length; | ||
const canOpenNewConnection = | ||
numberOfConnectionsOpen < maximumNumberOfConnectionsOpen; | ||
const canNotOpenReason = !canOpenNewConnection | ||
? 'maximum-number-exceeded' | ||
: undefined; | ||
|
||
return { | ||
numberOfConnectionsOpen, | ||
maximumNumberOfConnectionsOpen, | ||
canOpenNewConnection, | ||
canNotOpenReason, | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.