velocious 1.0.82 → 1.0.84
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/README.md +1 -1
- package/package.json +2 -2
- package/src/database/drivers/base.js +25 -0
- package/src/database/drivers/mssql/index.js +1 -1
- package/src/database/drivers/mysql/index.js +1 -1
- package/src/database/drivers/pgsql/index.js +1 -1
- package/src/database/drivers/sqlite/base.js +4 -24
- package/src/http-server/client/request-parser.js +1 -0
- package/src/http-server/client/request-runner.js +4 -2
- package/src/http-server/client/request.js +1 -0
- package/src/http-server/index.js +5 -1
- package/src/http-server/server-client.js +12 -6
- package/src/http-server/worker-handler/index.js +1 -1
package/README.md
CHANGED
|
@@ -190,7 +190,7 @@ First create a test file under something like the following path 'src/routes/acc
|
|
|
190
190
|
import {describe, expect, it} from "velocious/src/testing/test.js"
|
|
191
191
|
import Account from "../../models/account.js"
|
|
192
192
|
|
|
193
|
-
|
|
193
|
+
describe("accounts - create", {type: "request"}, async () => {
|
|
194
194
|
it("creates an account", async ({client}) => {
|
|
195
195
|
const response = await client.post("/accounts", {account: {name: "My event company"}})
|
|
196
196
|
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"velocious": "bin/velocious.js"
|
|
4
4
|
},
|
|
5
5
|
"name": "velocious",
|
|
6
|
-
"version": "1.0.
|
|
6
|
+
"version": "1.0.84",
|
|
7
7
|
"main": "index.js",
|
|
8
8
|
"scripts": {
|
|
9
9
|
"test": "VELOCIOUS_TEST_DIR=../ cd spec/dummy && npx velocious test",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"awaitery": "^1.0.1",
|
|
26
26
|
"bcryptjs": "^3.0.2",
|
|
27
27
|
"better-localstorage": "^1.0.7",
|
|
28
|
-
"debounce": "^
|
|
28
|
+
"debounce": "^3.0.0",
|
|
29
29
|
"diggerize": "^1.0.5",
|
|
30
30
|
"ejs": "^3.1.6",
|
|
31
31
|
"env-sense": "^1.0.0",
|
|
@@ -7,6 +7,7 @@ import UUID from "pure-uuid"
|
|
|
7
7
|
import TableData from "../table-data/index.js"
|
|
8
8
|
import TableColumn from "../table-data/table-column.js"
|
|
9
9
|
import TableForeignKey from "../table-data/table-foreign-key.js"
|
|
10
|
+
import wait from "awaitery/src/wait.js"
|
|
10
11
|
|
|
11
12
|
export default class VelociousDatabaseDriversBase {
|
|
12
13
|
constructor(config, configuration) {
|
|
@@ -230,6 +231,30 @@ export default class VelociousDatabaseDriversBase {
|
|
|
230
231
|
await this.query("COMMIT")
|
|
231
232
|
}
|
|
232
233
|
|
|
234
|
+
async query(sql) {
|
|
235
|
+
let tries = 0
|
|
236
|
+
|
|
237
|
+
while(tries < 5) {
|
|
238
|
+
tries++
|
|
239
|
+
|
|
240
|
+
try {
|
|
241
|
+
return await this._queryActual(sql)
|
|
242
|
+
} catch (error) {
|
|
243
|
+
if (tries < 5 && this.retryableDatabaseError(error)) {
|
|
244
|
+
await wait(100)
|
|
245
|
+
this.logger.warn(`Retrying query because failed with: ${error.stack}`)
|
|
246
|
+
// Retry
|
|
247
|
+
} else {
|
|
248
|
+
throw error
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
retryableDatabaseError(_error) {
|
|
255
|
+
return false
|
|
256
|
+
}
|
|
257
|
+
|
|
233
258
|
async rollbackTransaction() {
|
|
234
259
|
await this._transactionsActionsMutex.sync(async () => {
|
|
235
260
|
await this._rollbackTransactionAction()
|
|
@@ -85,7 +85,7 @@ export default class VelociousDatabaseDriversMssql extends Base{
|
|
|
85
85
|
getType() { return "mssql" }
|
|
86
86
|
primaryKeyType() { return "bigint" }
|
|
87
87
|
|
|
88
|
-
async
|
|
88
|
+
async _queryActual(sql) {
|
|
89
89
|
let result, request, tries = 0
|
|
90
90
|
|
|
91
91
|
if (this._currentTransaction) {
|
|
@@ -94,7 +94,7 @@ export default class VelociousDatabaseDriversMysql extends Base{
|
|
|
94
94
|
getType() { return "mysql" }
|
|
95
95
|
primaryKeyType() { return "bigint" }
|
|
96
96
|
|
|
97
|
-
async
|
|
97
|
+
async _queryActual(sql) {
|
|
98
98
|
try {
|
|
99
99
|
return await query(this.connection, sql)
|
|
100
100
|
} catch (error) {
|
|
@@ -12,7 +12,6 @@ import Options from "./options.js"
|
|
|
12
12
|
import QueryParser from "./query-parser.js"
|
|
13
13
|
import Table from "./table.js"
|
|
14
14
|
import Update from "./sql/update.js"
|
|
15
|
-
import wait from "awaitery/src/wait.js"
|
|
16
15
|
|
|
17
16
|
export default class VelociousDatabaseDriversSqliteBase extends Base {
|
|
18
17
|
async alterTableSql(tableData) {
|
|
@@ -190,29 +189,10 @@ export default class VelociousDatabaseDriversSqliteBase extends Base {
|
|
|
190
189
|
return result
|
|
191
190
|
}
|
|
192
191
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
tries++
|
|
198
|
-
|
|
199
|
-
try {
|
|
200
|
-
return await this._queryActual(sql)
|
|
201
|
-
} catch (error) {
|
|
202
|
-
if (tries < 5 && this._retryableDatabaseError(error)) {
|
|
203
|
-
await wait(100)
|
|
204
|
-
this.logger.warn(`Retrying query because failed with: ${error.stack}`)
|
|
205
|
-
// Retry
|
|
206
|
-
} else {
|
|
207
|
-
throw error
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
_retryableDatabaseError(error) {
|
|
214
|
-
if (this.getType() == "sqlite" && error.message?.startsWith("attempt to write a readonly database")) return true
|
|
215
|
-
if (this.getType() == "sqlite" && error.message?.startsWith("database is locked")) return true
|
|
192
|
+
retryableDatabaseError(error) {
|
|
193
|
+
if (error.message?.startsWith("attempt to write a readonly database")) return true
|
|
194
|
+
if (error.message?.startsWith("database is locked")) return true
|
|
195
|
+
if (error.message?.includes("→ Caused by: Error code : database is locked")) return true
|
|
216
196
|
|
|
217
197
|
return false
|
|
218
198
|
}
|
|
@@ -39,6 +39,7 @@ export default class VelociousHttpServerClientRequestParser {
|
|
|
39
39
|
|
|
40
40
|
feed = (data) => this.requestBuffer.feed(data)
|
|
41
41
|
getHeader(name) { return this.requestBuffer.getHeader(name)?.value }
|
|
42
|
+
getHeaders() { return this.requestBuffer.getHeadersHash() }
|
|
42
43
|
getHttpMethod() { return digg(this, "requestBuffer", "httpMethod") }
|
|
43
44
|
getHttpVersion() { return digg(this, "requestBuffer", "httpVersion") }
|
|
44
45
|
|
|
@@ -27,8 +27,10 @@ export default class VelociousHttpServerClientRequestRunner {
|
|
|
27
27
|
if (!request) throw new Error("No request?")
|
|
28
28
|
|
|
29
29
|
try {
|
|
30
|
-
if
|
|
31
|
-
|
|
30
|
+
// Before we checked if the sec-fetch-mode was "cors", but it seems the sec-fetch-mode isn't always present
|
|
31
|
+
await this.logger.debug(() => ["Run CORS", {httpMethod: request.httpMethod(), secFetchMode: request.header("sec-fetch-mode")}])
|
|
32
|
+
|
|
33
|
+
if (configuration.cors) {
|
|
32
34
|
await configuration.cors({request, response})
|
|
33
35
|
}
|
|
34
36
|
|
|
@@ -14,6 +14,7 @@ export default class VelociousHttpServerClientRequest {
|
|
|
14
14
|
baseURL() { return `${this.protocol()}://${this.hostWithPort()}` }
|
|
15
15
|
feed(data) { return this.requestParser.feed(data) }
|
|
16
16
|
header(headerName) { return this.getRequestBuffer().getHeader(headerName)?.getValue() }
|
|
17
|
+
headers() { return this.getRequestBuffer().getHeadersHash() }
|
|
17
18
|
httpMethod() { return this.requestParser.getHttpMethod() }
|
|
18
19
|
httpVersion() { return this.requestParser.getHttpVersion() }
|
|
19
20
|
host() { return this.requestParser.getHost() }
|
package/src/http-server/index.js
CHANGED
|
@@ -52,11 +52,15 @@ export default class VelociousHttpServer {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
async stopClients() {
|
|
55
|
+
const promises = []
|
|
56
|
+
|
|
55
57
|
for (const clientCount in this.clients) {
|
|
56
58
|
const client = this.clients[clientCount]
|
|
57
59
|
|
|
58
|
-
|
|
60
|
+
promises.push(client.end())
|
|
59
61
|
}
|
|
62
|
+
|
|
63
|
+
await Promise.all(promises)
|
|
60
64
|
}
|
|
61
65
|
|
|
62
66
|
stopServer() {
|
|
@@ -17,9 +17,11 @@ export default class ServerClient {
|
|
|
17
17
|
|
|
18
18
|
listen = () => this.socket.on("data", this.onSocketData)
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
end() {
|
|
21
|
+
return new Promise((resolve) => {
|
|
22
|
+
this.socket.once("close", () => resolve())
|
|
23
|
+
this.socket.end()
|
|
24
|
+
})
|
|
23
25
|
}
|
|
24
26
|
|
|
25
27
|
onSocketData = (chunk) => {
|
|
@@ -37,8 +39,12 @@ export default class ServerClient {
|
|
|
37
39
|
this.events.emit("close", this)
|
|
38
40
|
}
|
|
39
41
|
|
|
40
|
-
send(data) {
|
|
41
|
-
|
|
42
|
-
|
|
42
|
+
async send(data) {
|
|
43
|
+
return new Promise((resolve) => {
|
|
44
|
+
this.logger.debug("Send", data)
|
|
45
|
+
this.socket.write(data, () => {
|
|
46
|
+
resolve()
|
|
47
|
+
})
|
|
48
|
+
})
|
|
43
49
|
}
|
|
44
50
|
}
|
|
@@ -78,7 +78,7 @@ export default class VelociousHttpServerWorker {
|
|
|
78
78
|
} else if (command == "clientClose") {
|
|
79
79
|
const {clientCount} = digs(data, "clientCount")
|
|
80
80
|
|
|
81
|
-
this.clients[clientCount]?.
|
|
81
|
+
this.clients[clientCount]?.end()
|
|
82
82
|
} else {
|
|
83
83
|
throw new Error(`Unknown command: ${command}`)
|
|
84
84
|
}
|