@budibase/backend-core 2.6.19-alpha.4 → 2.6.19-alpha.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/package.json +17 -3
- package/dist/src/logging/pino/logger.js +1 -1
- package/dist/src/logging/pino/logger.js.map +1 -1
- package/dist/src/redis/init.d.ts +1 -0
- package/dist/src/redis/init.js +15 -3
- package/dist/src/redis/init.js.map +1 -1
- package/dist/src/redis/redis.d.ts +1 -0
- package/dist/src/redis/redis.js +9 -0
- package/dist/src/redis/redis.js.map +1 -1
- package/dist/src/redis/redlockImpl.d.ts +3 -1
- package/dist/src/redis/redlockImpl.js +79 -63
- package/dist/src/redis/redlockImpl.js.map +1 -1
- package/dist/src/redis/utils.d.ts +3 -2
- package/dist/src/redis/utils.js +2 -1
- package/dist/src/redis/utils.js.map +1 -1
- package/dist/tests/core/utilities/mocks/licenses.d.ts +1 -0
- package/dist/tests/core/utilities/mocks/licenses.js +5 -1
- package/dist/tests/core/utilities/mocks/licenses.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +17 -3
- package/src/cache/tests/writethrough.spec.ts +1 -5
- package/src/logging/pino/logger.ts +1 -0
- package/src/redis/init.ts +14 -4
- package/src/redis/redis.ts +8 -0
- package/src/redis/redlockImpl.ts +24 -15
- package/src/redis/utils.ts +2 -1
- package/tests/core/utilities/mocks/licenses.ts +4 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@budibase/backend-core",
|
|
3
|
-
"version": "2.6.19-alpha.
|
|
3
|
+
"version": "2.6.19-alpha.41",
|
|
4
4
|
"description": "Budibase backend core libraries used in server and worker",
|
|
5
5
|
"main": "dist/src/index.js",
|
|
6
6
|
"types": "dist/src/index.d.ts",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"@budibase/nano": "10.1.2",
|
|
24
24
|
"@budibase/pouchdb-replication-stream": "1.2.10",
|
|
25
|
-
"@budibase/types": "2.6.19-alpha.
|
|
25
|
+
"@budibase/types": "2.6.19-alpha.41",
|
|
26
26
|
"@shopify/jest-koa-mocks": "5.0.1",
|
|
27
27
|
"@techpass/passport-openidconnect": "0.3.2",
|
|
28
28
|
"aws-cloudfront-sign": "2.2.0",
|
|
@@ -88,5 +88,19 @@
|
|
|
88
88
|
"tsconfig-paths": "4.0.0",
|
|
89
89
|
"typescript": "4.7.3"
|
|
90
90
|
},
|
|
91
|
-
"
|
|
91
|
+
"nx": {
|
|
92
|
+
"targets": {
|
|
93
|
+
"build": {
|
|
94
|
+
"dependsOn": [
|
|
95
|
+
{
|
|
96
|
+
"projects": [
|
|
97
|
+
"@budibase/types"
|
|
98
|
+
],
|
|
99
|
+
"target": "build"
|
|
100
|
+
}
|
|
101
|
+
]
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
"gitHead": "b45483f4b33be53615d8e5d1e3df8915f06bf0dd"
|
|
92
106
|
}
|
|
@@ -72,16 +72,12 @@ describe("writethrough", () => {
|
|
|
72
72
|
writethrough.put({ ...current, value: 4 }),
|
|
73
73
|
])
|
|
74
74
|
|
|
75
|
+
// with a lock, this will work
|
|
75
76
|
const newRev = responses.map(x => x.rev).find(x => x !== current._rev)
|
|
76
77
|
expect(newRev).toBeDefined()
|
|
77
78
|
expect(responses.map(x => x.rev)).toEqual(
|
|
78
79
|
expect.arrayContaining([current._rev, current._rev, newRev])
|
|
79
80
|
)
|
|
80
|
-
expectFunctionWasCalledTimesWith(
|
|
81
|
-
mocks.alerts.logWarn,
|
|
82
|
-
2,
|
|
83
|
-
"Ignoring redlock conflict in write-through cache"
|
|
84
|
-
)
|
|
85
81
|
|
|
86
82
|
const output = await db.get(current._id)
|
|
87
83
|
expect(output.value).toBe(4)
|
package/src/redis/init.ts
CHANGED
|
@@ -6,7 +6,8 @@ let userClient: Client,
|
|
|
6
6
|
appClient: Client,
|
|
7
7
|
cacheClient: Client,
|
|
8
8
|
writethroughClient: Client,
|
|
9
|
-
lockClient: Client
|
|
9
|
+
lockClient: Client,
|
|
10
|
+
socketClient: Client
|
|
10
11
|
|
|
11
12
|
async function init() {
|
|
12
13
|
userClient = await new Client(utils.Databases.USER_CACHE).init()
|
|
@@ -14,9 +15,10 @@ async function init() {
|
|
|
14
15
|
appClient = await new Client(utils.Databases.APP_METADATA).init()
|
|
15
16
|
cacheClient = await new Client(utils.Databases.GENERIC_CACHE).init()
|
|
16
17
|
lockClient = await new Client(utils.Databases.LOCKS).init()
|
|
17
|
-
writethroughClient = await new Client(
|
|
18
|
-
|
|
19
|
-
utils.
|
|
18
|
+
writethroughClient = await new Client(utils.Databases.WRITE_THROUGH).init()
|
|
19
|
+
socketClient = await new Client(
|
|
20
|
+
utils.Databases.SOCKET_IO,
|
|
21
|
+
utils.SelectableDatabase.SOCKET_IO
|
|
20
22
|
).init()
|
|
21
23
|
}
|
|
22
24
|
|
|
@@ -27,6 +29,7 @@ export async function shutdown() {
|
|
|
27
29
|
if (cacheClient) await cacheClient.finish()
|
|
28
30
|
if (writethroughClient) await writethroughClient.finish()
|
|
29
31
|
if (lockClient) await lockClient.finish()
|
|
32
|
+
if (socketClient) await socketClient.finish()
|
|
30
33
|
}
|
|
31
34
|
|
|
32
35
|
process.on("exit", async () => {
|
|
@@ -74,3 +77,10 @@ export async function getLockClient() {
|
|
|
74
77
|
}
|
|
75
78
|
return lockClient
|
|
76
79
|
}
|
|
80
|
+
|
|
81
|
+
export async function getSocketClient() {
|
|
82
|
+
if (!socketClient) {
|
|
83
|
+
await init()
|
|
84
|
+
}
|
|
85
|
+
return socketClient
|
|
86
|
+
}
|
package/src/redis/redis.ts
CHANGED
|
@@ -183,6 +183,9 @@ class RedisWrapper {
|
|
|
183
183
|
CLOSED = false
|
|
184
184
|
init(this._select)
|
|
185
185
|
await waitForConnection(this._select)
|
|
186
|
+
if (this._select && !env.isTest()) {
|
|
187
|
+
this.getClient().select(this._select)
|
|
188
|
+
}
|
|
186
189
|
return this
|
|
187
190
|
}
|
|
188
191
|
|
|
@@ -209,6 +212,11 @@ class RedisWrapper {
|
|
|
209
212
|
return this.getClient().keys(addDbPrefix(db, pattern))
|
|
210
213
|
}
|
|
211
214
|
|
|
215
|
+
async exists(key: string) {
|
|
216
|
+
const db = this._db
|
|
217
|
+
return await this.getClient().exists(addDbPrefix(db, key))
|
|
218
|
+
}
|
|
219
|
+
|
|
212
220
|
async get(key: string) {
|
|
213
221
|
const db = this._db
|
|
214
222
|
let response = await this.getClient().get(addDbPrefix(db, key))
|
package/src/redis/redlockImpl.ts
CHANGED
|
@@ -4,10 +4,10 @@ import { LockOptions, LockType } from "@budibase/types"
|
|
|
4
4
|
import * as context from "../context"
|
|
5
5
|
import env from "../environment"
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
async function getClient(
|
|
8
8
|
type: LockType,
|
|
9
9
|
opts?: Redlock.Options
|
|
10
|
-
): Promise<Redlock>
|
|
10
|
+
): Promise<Redlock> {
|
|
11
11
|
if (type === LockType.CUSTOM) {
|
|
12
12
|
return newRedlock(opts)
|
|
13
13
|
}
|
|
@@ -18,6 +18,9 @@ const getClient = async (
|
|
|
18
18
|
case LockType.TRY_ONCE: {
|
|
19
19
|
return newRedlock(OPTIONS.TRY_ONCE)
|
|
20
20
|
}
|
|
21
|
+
case LockType.TRY_TWICE: {
|
|
22
|
+
return newRedlock(OPTIONS.TRY_TWICE)
|
|
23
|
+
}
|
|
21
24
|
case LockType.DEFAULT: {
|
|
22
25
|
return newRedlock(OPTIONS.DEFAULT)
|
|
23
26
|
}
|
|
@@ -35,6 +38,9 @@ const OPTIONS = {
|
|
|
35
38
|
// immediately throws an error if the lock is already held
|
|
36
39
|
retryCount: 0,
|
|
37
40
|
},
|
|
41
|
+
TRY_TWICE: {
|
|
42
|
+
retryCount: 1,
|
|
43
|
+
},
|
|
38
44
|
TEST: {
|
|
39
45
|
// higher retry count in unit tests
|
|
40
46
|
// due to high contention.
|
|
@@ -62,7 +68,7 @@ const OPTIONS = {
|
|
|
62
68
|
},
|
|
63
69
|
}
|
|
64
70
|
|
|
65
|
-
|
|
71
|
+
export async function newRedlock(opts: Redlock.Options = {}) {
|
|
66
72
|
let options = { ...OPTIONS.DEFAULT, ...opts }
|
|
67
73
|
const redisWrapper = await getLockClient()
|
|
68
74
|
const client = redisWrapper.getClient()
|
|
@@ -81,22 +87,26 @@ type RedlockExecution<T> =
|
|
|
81
87
|
| SuccessfulRedlockExecution<T>
|
|
82
88
|
| UnsuccessfulRedlockExecution
|
|
83
89
|
|
|
84
|
-
|
|
90
|
+
function getLockName(opts: LockOptions) {
|
|
91
|
+
// determine lock name
|
|
92
|
+
// by default use the tenantId for uniqueness, unless using a system lock
|
|
93
|
+
const prefix = opts.systemLock ? "system" : context.getTenantId()
|
|
94
|
+
let name: string = `lock:${prefix}_${opts.name}`
|
|
95
|
+
// add additional unique name if required
|
|
96
|
+
if (opts.resource) {
|
|
97
|
+
name = name + `_${opts.resource}`
|
|
98
|
+
}
|
|
99
|
+
return name
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export async function doWithLock<T>(
|
|
85
103
|
opts: LockOptions,
|
|
86
104
|
task: () => Promise<T>
|
|
87
|
-
): Promise<RedlockExecution<T>>
|
|
105
|
+
): Promise<RedlockExecution<T>> {
|
|
88
106
|
const redlock = await getClient(opts.type, opts.customOptions)
|
|
89
107
|
let lock
|
|
90
108
|
try {
|
|
91
|
-
|
|
92
|
-
// by default use the tenantId for uniqueness, unless using a system lock
|
|
93
|
-
const prefix = opts.systemLock ? "system" : context.getTenantId()
|
|
94
|
-
let name: string = `lock:${prefix}_${opts.name}`
|
|
95
|
-
|
|
96
|
-
// add additional unique name if required
|
|
97
|
-
if (opts.resource) {
|
|
98
|
-
name = name + `_${opts.resource}`
|
|
99
|
-
}
|
|
109
|
+
const name = getLockName(opts)
|
|
100
110
|
|
|
101
111
|
// create the lock
|
|
102
112
|
lock = await redlock.lock(name, opts.ttl)
|
|
@@ -112,7 +122,6 @@ export const doWithLock = async <T>(
|
|
|
112
122
|
if (opts.type === LockType.TRY_ONCE) {
|
|
113
123
|
// don't throw for try-once locks, they will always error
|
|
114
124
|
// due to retry count (0) exceeded
|
|
115
|
-
console.warn(e)
|
|
116
125
|
return { executed: false }
|
|
117
126
|
} else {
|
|
118
127
|
console.error(e)
|
package/src/redis/utils.ts
CHANGED
|
@@ -27,6 +27,7 @@ export enum Databases {
|
|
|
27
27
|
GENERIC_CACHE = "data_cache",
|
|
28
28
|
WRITE_THROUGH = "writeThrough",
|
|
29
29
|
LOCKS = "locks",
|
|
30
|
+
SOCKET_IO = "socket_io",
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
/**
|
|
@@ -40,7 +41,7 @@ export enum Databases {
|
|
|
40
41
|
*/
|
|
41
42
|
export enum SelectableDatabase {
|
|
42
43
|
DEFAULT = 0,
|
|
43
|
-
|
|
44
|
+
SOCKET_IO = 1,
|
|
44
45
|
UNUSED_1 = 2,
|
|
45
46
|
UNUSED_2 = 3,
|
|
46
47
|
UNUSED_3 = 4,
|
|
@@ -90,6 +90,10 @@ export const useScimIntegration = () => {
|
|
|
90
90
|
return useFeature(Feature.SCIM)
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
+
export const useSyncAutomations = () => {
|
|
94
|
+
return useFeature(Feature.SYNC_AUTOMATIONS)
|
|
95
|
+
}
|
|
96
|
+
|
|
93
97
|
// QUOTAS
|
|
94
98
|
|
|
95
99
|
export const setAutomationLogsQuota = (value: number) => {
|