@budibase/worker 1.0.181 → 1.0.184
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 +5 -5
- package/scripts/load/heavyUse.js +172 -0
- package/scripts/load/users.js +97 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@budibase/worker",
|
|
3
3
|
"email": "hi@budibase.com",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.184",
|
|
5
5
|
"description": "Budibase background service",
|
|
6
6
|
"main": "src/index.ts",
|
|
7
7
|
"repository": {
|
|
@@ -32,9 +32,9 @@
|
|
|
32
32
|
"author": "Budibase",
|
|
33
33
|
"license": "GPL-3.0",
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@budibase/backend-core": "^1.0.
|
|
36
|
-
"@budibase/pro": "1.0.
|
|
37
|
-
"@budibase/string-templates": "^1.0.
|
|
35
|
+
"@budibase/backend-core": "^1.0.184",
|
|
36
|
+
"@budibase/pro": "1.0.183",
|
|
37
|
+
"@budibase/string-templates": "^1.0.184",
|
|
38
38
|
"@koa/router": "^8.0.0",
|
|
39
39
|
"@sentry/node": "6.17.7",
|
|
40
40
|
"@techpass/passport-openidconnect": "^0.3.0",
|
|
@@ -90,5 +90,5 @@
|
|
|
90
90
|
"./scripts/jestSetup.js"
|
|
91
91
|
]
|
|
92
92
|
},
|
|
93
|
-
"gitHead": "
|
|
93
|
+
"gitHead": "0a8800cb795e4b8af802bd0438aaa441591fa016"
|
|
94
94
|
}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
const fetch = require("node-fetch")
|
|
2
|
+
|
|
3
|
+
const MAX_RUNTIME_SEC = 600
|
|
4
|
+
const HOST = "http://localhost:10000"
|
|
5
|
+
const TENANT_ID = "default"
|
|
6
|
+
const RATE_MS = 500
|
|
7
|
+
|
|
8
|
+
let API_KEY = process.argv[2]
|
|
9
|
+
let STATS = {
|
|
10
|
+
iterations: 0,
|
|
11
|
+
error: 0,
|
|
12
|
+
success: 0,
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (!API_KEY) {
|
|
16
|
+
console.error("Must specify API key as first run command!")
|
|
17
|
+
process.exit(-1)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const USERS = [
|
|
21
|
+
{
|
|
22
|
+
email: "loadtest1@test.com",
|
|
23
|
+
password: "test",
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
email: "loadtest2@test.com",
|
|
27
|
+
password: "test",
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
email: "loadtest3@test.com",
|
|
31
|
+
password: "test",
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
email: "loadtest4@test.com",
|
|
35
|
+
password: "test",
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
email: "loadtest5@test.com",
|
|
39
|
+
password: "test",
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
email: "loadtest6@test.com",
|
|
43
|
+
password: "test",
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
email: "loadtest7@test.com",
|
|
47
|
+
password: "test",
|
|
48
|
+
},
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
const REQUESTS = [
|
|
52
|
+
{
|
|
53
|
+
endpoint: `/api/global/self`,
|
|
54
|
+
method: "GET",
|
|
55
|
+
},
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
function timeout() {
|
|
59
|
+
return new Promise(resolve => {
|
|
60
|
+
setTimeout(() => {
|
|
61
|
+
resolve()
|
|
62
|
+
}, MAX_RUNTIME_SEC * 1000)
|
|
63
|
+
})
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async function preTest() {
|
|
67
|
+
// check if the user exists or not
|
|
68
|
+
const response = await fetch(`${HOST}/api/global/users`, {
|
|
69
|
+
method: "GET",
|
|
70
|
+
headers: {
|
|
71
|
+
"x-budibase-api-key": API_KEY,
|
|
72
|
+
},
|
|
73
|
+
})
|
|
74
|
+
if (response.status !== 200) {
|
|
75
|
+
throw new Error("Unable to retrieve users")
|
|
76
|
+
}
|
|
77
|
+
const users = await response.json()
|
|
78
|
+
for (let user of USERS) {
|
|
79
|
+
if (users.find(u => u.email === user.email)) {
|
|
80
|
+
continue
|
|
81
|
+
}
|
|
82
|
+
const response = await fetch(`${HOST}/api/global/users`, {
|
|
83
|
+
method: "POST",
|
|
84
|
+
headers: {
|
|
85
|
+
"x-budibase-api-key": API_KEY,
|
|
86
|
+
"Content-Type": "application/json",
|
|
87
|
+
},
|
|
88
|
+
body: JSON.stringify({
|
|
89
|
+
...user,
|
|
90
|
+
roles: {},
|
|
91
|
+
status: "active",
|
|
92
|
+
}),
|
|
93
|
+
})
|
|
94
|
+
if (response.status !== 200) {
|
|
95
|
+
throw new Error(
|
|
96
|
+
`Unable to create user ${user.email}, reason: ${await response.text()}`
|
|
97
|
+
)
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
async function requests(user) {
|
|
103
|
+
let response = await fetch(`${HOST}/api/global/auth/${TENANT_ID}/login`, {
|
|
104
|
+
method: "POST",
|
|
105
|
+
body: JSON.stringify({
|
|
106
|
+
username: user.email,
|
|
107
|
+
password: user.password,
|
|
108
|
+
}),
|
|
109
|
+
headers: {
|
|
110
|
+
"Content-Type": "application/json",
|
|
111
|
+
},
|
|
112
|
+
})
|
|
113
|
+
// unable to login
|
|
114
|
+
if (response.status !== 200) {
|
|
115
|
+
STATS.error++
|
|
116
|
+
return
|
|
117
|
+
} else {
|
|
118
|
+
STATS.success++
|
|
119
|
+
}
|
|
120
|
+
const cookie = response.headers.get("set-cookie")
|
|
121
|
+
let promises = []
|
|
122
|
+
for (let request of REQUESTS) {
|
|
123
|
+
const headers = {
|
|
124
|
+
cookie,
|
|
125
|
+
}
|
|
126
|
+
if (request.body) {
|
|
127
|
+
headers["Content-Type"] = "application/json"
|
|
128
|
+
}
|
|
129
|
+
promises.push(
|
|
130
|
+
fetch(`${HOST}${request.endpoint}`, {
|
|
131
|
+
method: request.method,
|
|
132
|
+
headers: {
|
|
133
|
+
cookie,
|
|
134
|
+
},
|
|
135
|
+
})
|
|
136
|
+
)
|
|
137
|
+
}
|
|
138
|
+
const responses = await Promise.all(promises)
|
|
139
|
+
for (let resp of responses) {
|
|
140
|
+
if (resp.status !== 200) {
|
|
141
|
+
console.error(await resp.text())
|
|
142
|
+
STATS.error++
|
|
143
|
+
} else {
|
|
144
|
+
STATS.success++
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
async function run() {
|
|
150
|
+
await preTest()
|
|
151
|
+
setInterval(async () => {
|
|
152
|
+
let promises = []
|
|
153
|
+
for (let user of USERS) {
|
|
154
|
+
promises.push(requests(user))
|
|
155
|
+
}
|
|
156
|
+
await Promise.all(promises)
|
|
157
|
+
console.log(
|
|
158
|
+
`Iteration ${STATS.iterations++} - errors: ${STATS.error}, success: ${
|
|
159
|
+
STATS.success
|
|
160
|
+
}`
|
|
161
|
+
)
|
|
162
|
+
}, RATE_MS)
|
|
163
|
+
await timeout()
|
|
164
|
+
console.log(
|
|
165
|
+
`Max runtime of ${MAX_RUNTIME_SEC} seconds has been reached - stopping.`
|
|
166
|
+
)
|
|
167
|
+
process.exit(0)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
run().catch(err => {
|
|
171
|
+
console.error("Failed to run - ", err)
|
|
172
|
+
})
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
// get the JWT secret etc
|
|
2
|
+
require("../../src/environment")
|
|
3
|
+
require("@budibase/backend-core").init()
|
|
4
|
+
const {
|
|
5
|
+
getProdAppID,
|
|
6
|
+
generateGlobalUserID,
|
|
7
|
+
} = require("@budibase/backend-core/db")
|
|
8
|
+
const { doInTenant, getGlobalDB } = require("@budibase/backend-core/tenancy")
|
|
9
|
+
const { internalSaveUser } = require("@budibase/backend-core/utils")
|
|
10
|
+
const { publicApiUserFix } = require("../../src/utilities/users")
|
|
11
|
+
const { hash } = require("@budibase/backend-core/utils")
|
|
12
|
+
|
|
13
|
+
const USER_LOAD_NUMBER = 10000
|
|
14
|
+
const BATCH_SIZE = 200
|
|
15
|
+
const PASSWORD = "test"
|
|
16
|
+
const TENANT_ID = "default"
|
|
17
|
+
|
|
18
|
+
const APP_ID = process.argv[2]
|
|
19
|
+
|
|
20
|
+
const words = [
|
|
21
|
+
"test",
|
|
22
|
+
"testing",
|
|
23
|
+
"budi",
|
|
24
|
+
"mail",
|
|
25
|
+
"age",
|
|
26
|
+
"risk",
|
|
27
|
+
"load",
|
|
28
|
+
"uno",
|
|
29
|
+
"arm",
|
|
30
|
+
"leg",
|
|
31
|
+
"pen",
|
|
32
|
+
"glass",
|
|
33
|
+
"box",
|
|
34
|
+
"chicken",
|
|
35
|
+
"bottle",
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
if (!APP_ID) {
|
|
39
|
+
console.error("Must supply app ID as first CLI option!")
|
|
40
|
+
process.exit(-1)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const WORD_1 = words[Math.floor(Math.random() * words.length)]
|
|
44
|
+
const WORD_2 = words[Math.floor(Math.random() * words.length)]
|
|
45
|
+
let HASHED_PASSWORD
|
|
46
|
+
|
|
47
|
+
function generateUser(count) {
|
|
48
|
+
return {
|
|
49
|
+
_id: generateGlobalUserID(),
|
|
50
|
+
password: HASHED_PASSWORD,
|
|
51
|
+
email: `${WORD_1}${count}@${WORD_2}.com`,
|
|
52
|
+
roles: {
|
|
53
|
+
[getProdAppID(APP_ID)]: "BASIC",
|
|
54
|
+
},
|
|
55
|
+
status: "active",
|
|
56
|
+
forceResetPassword: false,
|
|
57
|
+
firstName: "John",
|
|
58
|
+
lastName: "Smith",
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async function run() {
|
|
63
|
+
HASHED_PASSWORD = await hash(PASSWORD)
|
|
64
|
+
return doInTenant(TENANT_ID, async () => {
|
|
65
|
+
const db = getGlobalDB()
|
|
66
|
+
for (let i = 0; i < USER_LOAD_NUMBER; i += BATCH_SIZE) {
|
|
67
|
+
let userSavePromises = []
|
|
68
|
+
for (let j = 0; j < BATCH_SIZE; j++) {
|
|
69
|
+
// like the public API
|
|
70
|
+
const ctx = publicApiUserFix({
|
|
71
|
+
request: {
|
|
72
|
+
body: generateUser(i + j),
|
|
73
|
+
},
|
|
74
|
+
})
|
|
75
|
+
userSavePromises.push(
|
|
76
|
+
internalSaveUser(ctx.request.body, TENANT_ID, {
|
|
77
|
+
hashPassword: false,
|
|
78
|
+
requirePassword: true,
|
|
79
|
+
bulkCreate: true,
|
|
80
|
+
})
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
const users = await Promise.all(userSavePromises)
|
|
84
|
+
await db.bulkDocs(users)
|
|
85
|
+
console.log(`${i + BATCH_SIZE} users have been created.`)
|
|
86
|
+
}
|
|
87
|
+
})
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
run()
|
|
91
|
+
.then(() => {
|
|
92
|
+
console.log(`Generated ${USER_LOAD_NUMBER} users!`)
|
|
93
|
+
})
|
|
94
|
+
.catch(err => {
|
|
95
|
+
console.error("Failed for reason: ", err)
|
|
96
|
+
process.exit(-1)
|
|
97
|
+
})
|