Skip to content

Commit

Permalink
Add setting to specify read transactions on user cypher queries (#1954)
Browse files Browse the repository at this point in the history
* add setting for read transactions

* fix unit tests

* remove lock file
  • Loading branch information
OskarDamkjaer authored Dec 6, 2023
1 parent da14e1b commit 382b725
Show file tree
Hide file tree
Showing 9 changed files with 12,649 additions and 43,340 deletions.
30,215 changes: 0 additions & 30,215 deletions package-lock.json

This file was deleted.

8 changes: 8 additions & 0 deletions src/browser/modules/Sidebar/UserSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,14 @@ const visualSettings = [
'The timeout in milliseconds when establishing a connection to Neo4j.',
type: 'input'
}
},
{
useReadTransactions: {
displayName: 'Use read transactions for cypher queries.',
tooltip:
'This setting can be useful in a cluster environment where you want to ensure that read queries are sent to secondaries.',
type: 'checkbox'
}
}
]
},
Expand Down
32 changes: 21 additions & 11 deletions src/shared/modules/commands/cypher.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@ jest.mock('shared/modules/dbMeta/dbMetaDuck', () => {
}
})

jest.mock('shared/modules/settings/settingsDuck', () => {
const orig = require.requireActual('shared/modules/dbMeta/dbMetaDuck')
return {
...orig,
shouldUseReadTransactions: () => false
}
})

describe('tx metadata with cypher', () => {
afterEach(() => {
bolt.routedWriteTransaction.mockClear()
Expand Down Expand Up @@ -153,24 +161,26 @@ multiline comment
action.$$responseChannel = $$responseChannel

bus.send(action.type, action)
flushPromises().then(() => {
expect(bolt.routedWriteTransaction).toHaveBeenCalledTimes(1)
expect(bolt.routedWriteTransaction).toHaveBeenCalledWith(
`// comment
flushPromises()
.then(() => {
expect(bolt.routedWriteTransaction).toHaveBeenCalledTimes(1)
expect(bolt.routedWriteTransaction).toHaveBeenCalledWith(
`// comment
/*
multiline comment
*/
// comment
// comment
/*:auto*/ RETURN ":auto"`,
{},
expect.objectContaining({
autoCommit: true
})
)
done()
})
{},
expect.objectContaining({
autoCommit: true
})
)
done()
})
.catch(e => console.error(e))
})
test('it sends the autoCommit flag = false to tx functions on regular cypher', done => {
// Given
Expand Down
26 changes: 15 additions & 11 deletions src/shared/modules/commands/helpers/cypher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import bolt from 'services/bolt/bolt'
import { applyGraphTypes } from 'services/bolt/boltMappings'
import { arrayToObject } from 'services/utils'
import { send } from 'shared/modules/requests/requestsDuck'
import { v4 } from 'uuid'

export const applyParamGraphTypes = (params = {} as any) =>
arrayToObject(
Expand All @@ -38,17 +39,20 @@ export const handleCypherCommand = (
txMetadata = {},
autoCommit = false
): [string, Promise<QueryResult>] => {
const [id, request] = bolt.routedWriteTransaction(
action.query,
applyParamGraphTypes(params),
{
requestId: action.requestId,
cancelable: true,
...txMetadata,
autoCommit,
useDb: action.useDb
}
)
const parameters = applyParamGraphTypes(params)
const requestMetaData = {
requestId: action.requestId || v4(),
cancelable: true,
...txMetadata,
autoCommit,
useDb: action.useDb
}

const id = requestMetaData.requestId
const request = action.useReadTransaction
? bolt.routedReadTransaction(action.query, parameters, requestMetaData)
: bolt.routedWriteTransaction(action.query, parameters, requestMetaData)[1]

put(send(id))
return [id, request]
}
8 changes: 8 additions & 0 deletions src/shared/modules/commands/use-db-ww.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ jest.mock('shared/modules/params/paramsDuck', () => {
}
})

jest.mock('shared/modules/settings/settingsDuck', () => {
const orig = require.requireActual('shared/modules/dbMeta/dbMetaDuck')
return {
...orig,
shouldUseReadTransactions: () => false
}
})

jest.mock('shared/modules/dbMeta/dbMetaDuck', () => {
const orig = jest.requireActual('shared/modules/dbMeta/dbMetaDuck')
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,6 @@ Object {
"showWheelZoomInfo": true,
"theme": "auto",
"useBoltRouting": false,
"useReadTransactions": false,
}
`;
6 changes: 5 additions & 1 deletion src/shared/modules/settings/settingsDuck.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ export const shouldEnableMultiStatementMode = (state: any) =>
state[NAME].enableMultiStatementMode
export const shouldShowPerformanceOverlay = (state: any): boolean =>
state[NAME].showPerformanceOverlay === true
export const shouldUseReadTransactions = (state: any) =>
state[NAME].useReadTransactions || initialState.useReadTransactions

const browserSyncConfig = (host = 'https://auth.neo4j.com') => ({
authWindowUrl: `${host}/indexNewBrowser.html`,
Expand Down Expand Up @@ -122,6 +124,7 @@ export type SettingsState = {
allowCrashReports: boolean
allowUserStats: boolean
showWheelZoomInfo: boolean
useReadTransactions: boolean
}

export const initialState: SettingsState = {
Expand All @@ -146,7 +149,8 @@ export const initialState: SettingsState = {
showPerformanceOverlay: false,
allowCrashReports: true,
allowUserStats: true,
showWheelZoomInfo: true
showWheelZoomInfo: true,
useReadTransactions: false
}

export default function settings(state = initialState, action: any) {
Expand Down
6 changes: 5 additions & 1 deletion src/shared/services/commandInterpreterHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,10 @@ import {
getRequest,
update as updateQueryResult
} from 'shared/modules/requests/requestsDuck'
import { getSettings } from 'shared/modules/settings/settingsDuck'
import {
getSettings,
shouldUseReadTransactions
} from 'shared/modules/settings/settingsDuck'
import { open } from 'shared/modules/sidebar/sidebarDuck'
import {
backgroundTxMetadata,
Expand Down Expand Up @@ -439,6 +442,7 @@ const availableCommands = [
query.substring(prefixIndex + autoPrefix.length)

action.query = isAutocommit ? withoutAutoPrefix : query
action.useReadTransaction = shouldUseReadTransactions(state)

const [id, request] = handleCypherCommand(
action,
Expand Down
Loading

0 comments on commit 382b725

Please sign in to comment.