Skip to content

Commit 382b725

Browse files
Add setting to specify read transactions on user cypher queries (#1954)
* add setting for read transactions * fix unit tests * remove lock file
1 parent da14e1b commit 382b725

File tree

9 files changed

+12649
-43340
lines changed

9 files changed

+12649
-43340
lines changed

Diff for: package-lock.json

-30,215
This file was deleted.

Diff for: src/browser/modules/Sidebar/UserSettings.tsx

+8
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,14 @@ const visualSettings = [
102102
'The timeout in milliseconds when establishing a connection to Neo4j.',
103103
type: 'input'
104104
}
105+
},
106+
{
107+
useReadTransactions: {
108+
displayName: 'Use read transactions for cypher queries.',
109+
tooltip:
110+
'This setting can be useful in a cluster environment where you want to ensure that read queries are sent to secondaries.',
111+
type: 'checkbox'
112+
}
105113
}
106114
]
107115
},

Diff for: src/shared/modules/commands/cypher.test.ts

+21-11
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,14 @@ jest.mock('shared/modules/dbMeta/dbMetaDuck', () => {
5757
}
5858
})
5959

60+
jest.mock('shared/modules/settings/settingsDuck', () => {
61+
const orig = require.requireActual('shared/modules/dbMeta/dbMetaDuck')
62+
return {
63+
...orig,
64+
shouldUseReadTransactions: () => false
65+
}
66+
})
67+
6068
describe('tx metadata with cypher', () => {
6169
afterEach(() => {
6270
bolt.routedWriteTransaction.mockClear()
@@ -153,24 +161,26 @@ multiline comment
153161
action.$$responseChannel = $$responseChannel
154162

155163
bus.send(action.type, action)
156-
flushPromises().then(() => {
157-
expect(bolt.routedWriteTransaction).toHaveBeenCalledTimes(1)
158-
expect(bolt.routedWriteTransaction).toHaveBeenCalledWith(
159-
`// comment
164+
flushPromises()
165+
.then(() => {
166+
expect(bolt.routedWriteTransaction).toHaveBeenCalledTimes(1)
167+
expect(bolt.routedWriteTransaction).toHaveBeenCalledWith(
168+
`// comment
160169
/*
161170
multiline comment
162171
*/
163172
// comment
164173
165174
// comment
166175
/*:auto*/ RETURN ":auto"`,
167-
{},
168-
expect.objectContaining({
169-
autoCommit: true
170-
})
171-
)
172-
done()
173-
})
176+
{},
177+
expect.objectContaining({
178+
autoCommit: true
179+
})
180+
)
181+
done()
182+
})
183+
.catch(e => console.error(e))
174184
})
175185
test('it sends the autoCommit flag = false to tx functions on regular cypher', done => {
176186
// Given

Diff for: src/shared/modules/commands/helpers/cypher.ts

+15-11
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import bolt from 'services/bolt/bolt'
2323
import { applyGraphTypes } from 'services/bolt/boltMappings'
2424
import { arrayToObject } from 'services/utils'
2525
import { send } from 'shared/modules/requests/requestsDuck'
26+
import { v4 } from 'uuid'
2627

2728
export const applyParamGraphTypes = (params = {} as any) =>
2829
arrayToObject(
@@ -38,17 +39,20 @@ export const handleCypherCommand = (
3839
txMetadata = {},
3940
autoCommit = false
4041
): [string, Promise<QueryResult>] => {
41-
const [id, request] = bolt.routedWriteTransaction(
42-
action.query,
43-
applyParamGraphTypes(params),
44-
{
45-
requestId: action.requestId,
46-
cancelable: true,
47-
...txMetadata,
48-
autoCommit,
49-
useDb: action.useDb
50-
}
51-
)
42+
const parameters = applyParamGraphTypes(params)
43+
const requestMetaData = {
44+
requestId: action.requestId || v4(),
45+
cancelable: true,
46+
...txMetadata,
47+
autoCommit,
48+
useDb: action.useDb
49+
}
50+
51+
const id = requestMetaData.requestId
52+
const request = action.useReadTransaction
53+
? bolt.routedReadTransaction(action.query, parameters, requestMetaData)
54+
: bolt.routedWriteTransaction(action.query, parameters, requestMetaData)[1]
55+
5256
put(send(id))
5357
return [id, request]
5458
}

Diff for: src/shared/modules/commands/use-db-ww.test.ts

+8
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,14 @@ jest.mock('shared/modules/params/paramsDuck', () => {
4141
}
4242
})
4343

44+
jest.mock('shared/modules/settings/settingsDuck', () => {
45+
const orig = require.requireActual('shared/modules/dbMeta/dbMetaDuck')
46+
return {
47+
...orig,
48+
shouldUseReadTransactions: () => false
49+
}
50+
})
51+
4452
jest.mock('shared/modules/dbMeta/dbMetaDuck', () => {
4553
const orig = jest.requireActual('shared/modules/dbMeta/dbMetaDuck')
4654
return {

Diff for: src/shared/modules/settings/__snapshots__/settingsDuck.test.ts.snap

+1
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,6 @@ Object {
2525
"showWheelZoomInfo": true,
2626
"theme": "auto",
2727
"useBoltRouting": false,
28+
"useReadTransactions": false,
2829
}
2930
`;

Diff for: src/shared/modules/settings/settingsDuck.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ export const shouldEnableMultiStatementMode = (state: any) =>
7070
state[NAME].enableMultiStatementMode
7171
export const shouldShowPerformanceOverlay = (state: any): boolean =>
7272
state[NAME].showPerformanceOverlay === true
73+
export const shouldUseReadTransactions = (state: any) =>
74+
state[NAME].useReadTransactions || initialState.useReadTransactions
7375

7476
const browserSyncConfig = (host = 'https://auth.neo4j.com') => ({
7577
authWindowUrl: `${host}/indexNewBrowser.html`,
@@ -122,6 +124,7 @@ export type SettingsState = {
122124
allowCrashReports: boolean
123125
allowUserStats: boolean
124126
showWheelZoomInfo: boolean
127+
useReadTransactions: boolean
125128
}
126129

127130
export const initialState: SettingsState = {
@@ -146,7 +149,8 @@ export const initialState: SettingsState = {
146149
showPerformanceOverlay: false,
147150
allowCrashReports: true,
148151
allowUserStats: true,
149-
showWheelZoomInfo: true
152+
showWheelZoomInfo: true,
153+
useReadTransactions: false
150154
}
151155

152156
export default function settings(state = initialState, action: any) {

Diff for: src/shared/services/commandInterpreterHelper.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,10 @@ import {
9595
getRequest,
9696
update as updateQueryResult
9797
} from 'shared/modules/requests/requestsDuck'
98-
import { getSettings } from 'shared/modules/settings/settingsDuck'
98+
import {
99+
getSettings,
100+
shouldUseReadTransactions
101+
} from 'shared/modules/settings/settingsDuck'
99102
import { open } from 'shared/modules/sidebar/sidebarDuck'
100103
import {
101104
backgroundTxMetadata,
@@ -439,6 +442,7 @@ const availableCommands = [
439442
query.substring(prefixIndex + autoPrefix.length)
440443

441444
action.query = isAutocommit ? withoutAutoPrefix : query
445+
action.useReadTransaction = shouldUseReadTransactions(state)
442446

443447
const [id, request] = handleCypherCommand(
444448
action,

0 commit comments

Comments
 (0)