Skip to content

Commit ca3a0fb

Browse files
author
Daniele Briggi
committed
fix(connection): improve connection management
- resolve the creation of two connections. The dynamic import of the connection modules delayed the initialization of the SQLiteCloudConnection object. Between the initialization of the Database object and the call to sql() method, the connection was not yet initialized - connection to the database and the commands are put in queue to ensure the connection to be ready (the socket connection is a background operation) - remove the implicit connection to the database in the sql() methods. We want the user be aware of the status of the connection (eg, due to open transactions) - enable TCP keep alive to be notified of the most of the cases of errors on the TCP socket
1 parent 717b862 commit ca3a0fb

File tree

4 files changed

+168
-161
lines changed

4 files changed

+168
-161
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@sqlitecloud/drivers",
3-
"version": "1.0.417",
3+
"version": "1.0.421",
44
"description": "SQLiteCloud drivers for Typescript/Javascript in edge, web and node clients",
55
"main": "./lib/index.js",
66
"types": "./lib/index.d.ts",

src/drivers/connection-tls.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,21 @@
22
* connection-tls.ts - connection via tls socket and sqlitecloud protocol
33
*/
44

5-
import { type SQLiteCloudConfig, SQLiteCloudError, type ErrorCallback, type ResultsCallback, SQLiteCloudCommand } from './types'
65
import { SQLiteCloudConnection } from './connection'
7-
import { getInitializationCommands } from './utilities'
86
import {
7+
bufferEndsWith,
8+
CMD_COMPRESSED,
9+
CMD_ROWSET_CHUNK,
10+
decompressBuffer,
911
formatCommand,
1012
hasCommandLength,
1113
parseCommandLength,
12-
popData,
13-
decompressBuffer,
1414
parseRowsetChunks,
15-
CMD_COMPRESSED,
16-
CMD_ROWSET_CHUNK,
17-
bufferEndsWith,
15+
popData,
1816
ROWSET_CHUNKS_END
1917
} from './protocol'
18+
import { type ErrorCallback, type ResultsCallback, SQLiteCloudCommand, type SQLiteCloudConfig, SQLiteCloudError } from './types'
19+
import { getInitializationCommands } from './utilities'
2020

2121
// explicitly importing buffer library to allow cross-platform support by replacing it
2222
import { Buffer } from 'buffer'
@@ -77,6 +77,10 @@ export class SQLiteCloudTlsConnection extends SQLiteCloudConnection {
7777
callback?.call(this, error)
7878
})
7979
})
80+
this.socket.setKeepAlive(true)
81+
// disable Nagle algorithm because we want our writes to be sent ASAP
82+
// https://brooker.co.za/blog/2024/05/09/nagle.html
83+
this.socket.setNoDelay(true)
8084

8185
this.socket.on('data', data => {
8286
this.processCommandsData(data)
@@ -97,6 +101,11 @@ export class SQLiteCloudTlsConnection extends SQLiteCloudConnection {
97101
this.processCommandsFinish(new SQLiteCloudError('Connection closed', { errorCode: 'ERR_CONNECTION_CLOSED' }))
98102
})
99103

104+
this.socket.on('timeout', () => {
105+
this.close()
106+
this.processCommandsFinish(new SQLiteCloudError('Connection ened due to timeout', { errorCode: 'ERR_CONNECTION_TIMEOUT' }))
107+
})
108+
100109
return this
101110
}
102111

src/drivers/connection-ws.ts

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
* transport-ws.ts - handles low level communication with sqlitecloud server via socket.io websocket
33
*/
44

5-
import { SQLiteCloudConfig, SQLiteCloudError, ErrorCallback, ResultsCallback, SQLiteCloudCommand, SQLiteCloudDataTypes } from './types'
6-
import { SQLiteCloudRowset } from './rowset'
7-
import { SQLiteCloudConnection } from './connection'
85
import { io, Socket } from 'socket.io-client'
6+
import { SQLiteCloudConnection } from './connection'
7+
import { SQLiteCloudRowset } from './rowset'
8+
import { ErrorCallback, ResultsCallback, SQLiteCloudCommand, SQLiteCloudConfig, SQLiteCloudError } from './types'
99

1010
/**
1111
* Implementation of TransportConnection that connects to the database indirectly
@@ -19,7 +19,7 @@ export class SQLiteCloudWebsocketConnection extends SQLiteCloudConnection {
1919

2020
/** True if connection is open */
2121
get connected(): boolean {
22-
return !!this.socket
22+
return !!(this.socket && this.socket?.connected)
2323
}
2424

2525
/* Opens a connection with the server and sends the initialization commands. Will throw in case of errors. */
@@ -32,11 +32,25 @@ export class SQLiteCloudWebsocketConnection extends SQLiteCloudConnection {
3232
const connectionstring = this.config.connectionstring as string
3333
const gatewayUrl = this.config?.gatewayurl || `${this.config.host === 'localhost' ? 'ws' : 'wss'}://${this.config.host as string}:4000`
3434
this.socket = io(gatewayUrl, { auth: { token: connectionstring } })
35+
36+
this.socket.on('connect', () => {
37+
callback?.call(this, null)
38+
})
39+
40+
this.socket.on('disconnect', (reason) => {
41+
this.close()
42+
callback?.call(this, new SQLiteCloudError('Disconnected', { errorCode: 'ERR_CONNECTION_DISCONNECTED', cause: reason }))
43+
})
44+
45+
this.socket.on('error', (error: Error) => {
46+
this.close()
47+
callback?.call(this, new SQLiteCloudError('Connection error', { errorCode: 'ERR_CONNECTION_ERROR', cause: error }))
48+
})
3549
}
36-
callback?.call(this, null)
3750
} catch (error) {
3851
callback?.call(this, error as Error)
3952
}
53+
4054
return this
4155
}
4256

@@ -79,10 +93,11 @@ export class SQLiteCloudWebsocketConnection extends SQLiteCloudConnection {
7993
console.assert(this.socket !== null, 'SQLiteCloudWebsocketConnection.close - connection already closed')
8094
if (this.socket) {
8195
this.socket?.close()
96+
this.socket?.removeAllListeners()
8297
this.socket = undefined
8398
}
99+
84100
this.operations.clear()
85-
this.socket = undefined
86101
return this
87102
}
88103
}

0 commit comments

Comments
 (0)