Skip to content

Commit 944beb3

Browse files
committed
Initial spike of home database cache
1 parent f0e6066 commit 944beb3

File tree

12 files changed

+197
-10
lines changed

12 files changed

+197
-10
lines changed

packages/bolt-connection/src/connection-provider/connection-provider-routing.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,18 @@ export default class RoutingConnectionProvider extends PooledConnectionProvider
297297
})
298298
}
299299

300+
async ensureFreshRoutingTable ({ database, accessMode }) {
301+
const context = { database: database || DEFAULT_DB_NAME }
302+
303+
await this._freshRoutingTable({
304+
accessMode,
305+
database: context.database,
306+
onDatabaseNameResolved: (databaseName) => {
307+
context.database = context.database || databaseName
308+
}
309+
})
310+
}
311+
300312
async verifyConnectivityAndGetServerInfo ({ database, accessMode }) {
301313
const context = { database: database || DEFAULT_DB_NAME }
302314

packages/core/src/connection-provider.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,10 @@ class ConnectionProvider {
110110
throw Error('Not implemented')
111111
}
112112

113+
ensureFreshRoutingTable (param?: { database?: string, accessMode?: string }): Promise<void> {
114+
throw Error('Not implemented')
115+
}
116+
113117
/**
114118
* This method verifies the connectivity of the database by trying to acquire a connection
115119
* for each server available in the cluster.

packages/core/src/driver.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ type CreateSession = (args: {
9797
notificationFilter?: NotificationFilter
9898
auth?: AuthToken
9999
log: Logger
100+
homeDatabaseCallback?: (user: string, databaseName: string) => void
100101
}) => Session
101102

102103
type CreateQueryExecutor = (createSession: (config: { database?: string, bookmarkManager?: BookmarkManager }) => Session) => QueryExecutor
@@ -470,6 +471,8 @@ class Driver {
470471
private readonly _createSession: CreateSession
471472
private readonly _defaultExecuteQueryBookmarkManager: BookmarkManager
472473
private readonly _queryExecutor: QueryExecutor
474+
homeDatabaseCache: Map<string, string>
475+
freshRoutingTablePromise: Promise<void>
473476

474477
/**
475478
* You should not be calling this directly, instead use {@link driver}.
@@ -509,6 +512,8 @@ class Driver {
509512
*/
510513
this._connectionProvider = null
511514

515+
this.homeDatabaseCache = new Map<string, string>()
516+
512517
this._afterConstruction()
513518
}
514519

@@ -863,6 +868,10 @@ class Driver {
863868
}): Session {
864869
const sessionMode = Session._validateSessionMode(defaultAccessMode)
865870
const connectionProvider = this._getOrCreateConnectionProvider()
871+
const homeDatabase = this.homeDatabaseCache.get(impersonatedUser ?? auth?.principal ?? '')
872+
if (homeDatabase !== undefined && homeDatabase !== '') {
873+
void connectionProvider.ensureFreshRoutingTable({ database: homeDatabase })
874+
}
866875
const bookmarks = bookmarkOrBookmarks != null
867876
? new Bookmarks(bookmarkOrBookmarks)
868877
: Bookmarks.empty()
@@ -879,10 +888,15 @@ class Driver {
879888
bookmarkManager,
880889
notificationFilter,
881890
auth,
882-
log: this._log
891+
log: this._log,
892+
homeDatabaseCallback: this._homeDatabaseCallback.bind(this)
883893
})
884894
}
885895

896+
_homeDatabaseCallback (user: string, databaseName: string): void {
897+
this.homeDatabaseCache.set(user, databaseName)
898+
}
899+
886900
/**
887901
* @private
888902
*/

packages/core/src/session.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ class Session {
7474
private readonly _bookmarkManager?: BookmarkManager
7575
private readonly _notificationFilter?: NotificationFilter
7676
private readonly _log: Logger
77+
private readonly _homeDatabaseCallback: Function | undefined
78+
private readonly _auth: AuthToken | undefined
7779
/**
7880
* @constructor
7981
* @protected
@@ -101,7 +103,8 @@ class Session {
101103
bookmarkManager,
102104
notificationFilter,
103105
auth,
104-
log
106+
log,
107+
homeDatabaseCallback
105108
}: {
106109
mode: SessionMode
107110
connectionProvider: ConnectionProvider
@@ -115,12 +118,15 @@ class Session {
115118
notificationFilter?: NotificationFilter
116119
auth?: AuthToken
117120
log: Logger
121+
homeDatabaseCallback?: (user: string, databaseName: string) => void
118122
}) {
119123
this._mode = mode
120124
this._database = database
121125
this._reactive = reactive
122126
this._fetchSize = fetchSize
123127
this._onDatabaseNameResolved = this._onDatabaseNameResolved.bind(this)
128+
this._homeDatabaseCallback = homeDatabaseCallback
129+
this._auth = auth
124130
this._getConnectionAcquistionBookmarks = this._getConnectionAcquistionBookmarks.bind(this)
125131
this._readConnectionHolder = new ConnectionHolder({
126132
mode: ACCESS_MODE_READ,
@@ -511,6 +517,9 @@ class Session {
511517
if (!this._databaseNameResolved) {
512518
const normalizedDatabase = database ?? ''
513519
this._database = normalizedDatabase
520+
if (this._homeDatabaseCallback != null) {
521+
this._homeDatabaseCallback(this._impersonatedUser ?? this._auth?.principal, normalizedDatabase)
522+
}
514523
this._readConnectionHolder.setDatabase(normalizedDatabase)
515524
this._writeConnectionHolder.setDatabase(normalizedDatabase)
516525
this._databaseNameResolved = true

packages/core/test/driver.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,14 @@ describe('Driver', () => {
7070
const session = driver?.session({ impersonatedUser })
7171

7272
expect(session).not.toBeUndefined()
73-
expect(createSession).toHaveBeenCalledWith(expectedSessionParams({ impersonatedUser }))
73+
expect(createSession).toHaveBeenCalledWith(expectedSessionParams({ impersonatedUser, homeDatabaseCallback: driver?._homeDatabaseCallback }))
7474
})
7575

7676
it('should create the session without impersonated user', () => {
7777
const session = driver?.session()
7878

7979
expect(session).not.toBeUndefined()
80-
expect(createSession).toHaveBeenCalledWith(expectedSessionParams())
80+
expect(createSession).toHaveBeenCalledWith(expectedSessionParams({ homeDatabaseCallback: driver?._homeDatabaseCallback }))
8181
})
8282

8383
it('should create the session with auth', () => {
@@ -90,14 +90,14 @@ describe('Driver', () => {
9090
const session = driver?.session({ auth })
9191

9292
expect(session).not.toBeUndefined()
93-
expect(createSession).toHaveBeenCalledWith(expectedSessionParams({ auth }))
93+
expect(createSession).toHaveBeenCalledWith(expectedSessionParams({ auth, homeDatabaseCallback: driver?._homeDatabaseCallback }))
9494
})
9595

9696
it('should create the session without auth', () => {
9797
const session = driver?.session()
9898

9999
expect(session).not.toBeUndefined()
100-
expect(createSession).toHaveBeenCalledWith(expectedSessionParams())
100+
expect(createSession).toHaveBeenCalledWith(expectedSessionParams({ homeDatabaseCallback: driver?._homeDatabaseCallback }))
101101
})
102102

103103
it.each([

packages/neo4j-driver-deno/deno.lock

Lines changed: 92 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/neo4j-driver-deno/lib/bolt-connection/connection-provider/connection-provider-routing.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,18 @@ export default class RoutingConnectionProvider extends PooledConnectionProvider
297297
})
298298
}
299299

300+
async ensureFreshRoutingTable ({ database, accessMode }) {
301+
const context = { database: database || DEFAULT_DB_NAME }
302+
303+
await this._freshRoutingTable({
304+
accessMode,
305+
database: context.database,
306+
onDatabaseNameResolved: (databaseName) => {
307+
context.database = context.database || databaseName
308+
}
309+
})
310+
}
311+
300312
async verifyConnectivityAndGetServerInfo ({ database, accessMode }) {
301313
const context = { database: database || DEFAULT_DB_NAME }
302314

packages/neo4j-driver-deno/lib/core/connection-provider.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,10 @@ class ConnectionProvider {
110110
throw Error('Not implemented')
111111
}
112112

113+
ensureFreshRoutingTable(param?: { database?: string, accessMode?: string }): Promise<void> {
114+
throw Error('Not implemented')
115+
}
116+
113117
/**
114118
* This method verifies the connectivity of the database by trying to acquire a connection
115119
* for each server available in the cluster.

packages/neo4j-driver-deno/lib/core/driver.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ type CreateSession = (args: {
9797
notificationFilter?: NotificationFilter
9898
auth?: AuthToken
9999
log: Logger
100+
homeDatabaseCallback?: (user: string, databaseName: string) => void
100101
}) => Session
101102

102103
type CreateQueryExecutor = (createSession: (config: { database?: string, bookmarkManager?: BookmarkManager }) => Session) => QueryExecutor
@@ -470,6 +471,8 @@ class Driver {
470471
private readonly _createSession: CreateSession
471472
private readonly _defaultExecuteQueryBookmarkManager: BookmarkManager
472473
private readonly _queryExecutor: QueryExecutor
474+
homeDatabaseCache: Map<string, string>
475+
freshRoutingTablePromise: Promise<void>
473476

474477
/**
475478
* You should not be calling this directly, instead use {@link driver}.
@@ -509,6 +512,8 @@ class Driver {
509512
*/
510513
this._connectionProvider = null
511514

515+
this.homeDatabaseCache = new Map<string, string>()
516+
512517
this._afterConstruction()
513518
}
514519

@@ -863,6 +868,10 @@ class Driver {
863868
}): Session {
864869
const sessionMode = Session._validateSessionMode(defaultAccessMode)
865870
const connectionProvider = this._getOrCreateConnectionProvider()
871+
const homeDatabase = this.homeDatabaseCache.get(impersonatedUser ?? auth?.principal ?? "")
872+
if (homeDatabase !== undefined && homeDatabase !== "") {
873+
void connectionProvider.ensureFreshRoutingTable({database: homeDatabase})
874+
}
866875
const bookmarks = bookmarkOrBookmarks != null
867876
? new Bookmarks(bookmarkOrBookmarks)
868877
: Bookmarks.empty()
@@ -879,10 +888,15 @@ class Driver {
879888
bookmarkManager,
880889
notificationFilter,
881890
auth,
882-
log: this._log
891+
log: this._log,
892+
homeDatabaseCallback: this._homeDatabaseCallback.bind(this)
883893
})
884894
}
885895

896+
_homeDatabaseCallback(user: string, databaseName: string): void {
897+
this.homeDatabaseCache.set(user, databaseName)
898+
}
899+
886900
/**
887901
* @private
888902
*/

0 commit comments

Comments
 (0)