@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@budibase/backend-core",
3
- "version": "2.6.19-alpha.4",
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.4",
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
- "gitHead": "9a9aab1169f9639b28a0feef6f63577c3cbd0251"
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)
@@ -96,6 +96,7 @@ if (!env.DISABLE_PINO_LOGGER) {
96
96
 
97
97
  const mergingObject: any = {
98
98
  err: error,
99
+ pid: process.pid,
99
100
  ...contextObject,
100
101
  }
101
102
 
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
- utils.Databases.WRITE_THROUGH,
19
- utils.SelectableDatabase.WRITE_THROUGH
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
+ }
@@ -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))
@@ -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
- const getClient = async (
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
- const newRedlock = async (opts: Redlock.Options = {}) => {
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
- export const doWithLock = async <T>(
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
- // 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
-
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)
@@ -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
- WRITE_THROUGH = 1,
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) => {