Skip to content

Commit 2b9a065

Browse files
committed
Connection pool - first pass
Just outlining what the connection pool would probably look like.
1 parent b424aa3 commit 2b9a065

File tree

4 files changed

+101
-2
lines changed

4 files changed

+101
-2
lines changed

dist/index.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ export * from './vfs.mjs';
44
export * from './func.mjs';
55
export * from './sql.mjs';
66
export * from './blob.mjs';
7+
export * from './pool.mjs';
78
export { default as opfs } from './opfs.mjs';

dist/pool.mjs

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import { OutOfMemError } from "./asyncify.mjs";
2+
import { sqlite3, initialized, alloc_str, handle_error } from "./sqlite.mjs";
3+
import { SQLITE_OPEN_READWRITE, SQLITE_OPEN_CREATE, SQLITE_OPEN_EXRESCODE } from "./sqlite_def.mjs";
4+
5+
export class ConnPool {
6+
initialized;
7+
#waiters = [];
8+
#conns = [];
9+
#pathname_ptr;
10+
#conn_ptr;
11+
#vfs_ptr;
12+
#flags;
13+
#max_delay_sec;
14+
#rollback_ptr;
15+
#conn_init_func;
16+
17+
constructor(pathname, {
18+
pool_size = 3,
19+
max_delay_sec = 30,
20+
vfs = false,
21+
flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_EXRESCODE,
22+
init_func = false,
23+
conn_init_func = false
24+
} = {}) {
25+
this.initialized = (async () => {
26+
try {
27+
// Wait for sqlite to be initialized:
28+
await initialized;
29+
30+
this.#pathname_ptr = alloc_str(pathname);
31+
this.#conn_ptr = sqlite3.malloc(4);
32+
this.#vfs_ptr = (typeof vfs == 'string') ? alloc_str(vfs) : 0;
33+
this.#rollback_ptr = alloc_str("ROLLBACK");
34+
if (!this.#pathname_ptr || !this.#conn_ptr || (vfs && !this.#vfs_ptr) || !this.#rollback_ptr) throw new OutOfMemError();
35+
this.#flags = flags;
36+
this.#max_delay_sec = max_delay_sec;
37+
this.#conn_init_func = conn_init_func;
38+
39+
if (init_func) await init_func();
40+
41+
// Allocate the conns:
42+
for (let i = 0; i < pool_size; ++i) {
43+
await this.allocate_conn();
44+
}
45+
} catch (e) {
46+
this.close();
47+
throw e;
48+
}
49+
})();
50+
}
51+
async allocate_conn() {
52+
let conn;
53+
try {
54+
const res = await sqlite3.sqlite3_open_v2(this.#pathname_ptr, this.#conn_ptr, this.#flags, this.#vfs_ptr);
55+
conn = memdv().getInt32(this.#conn_ptr, true);
56+
handle_error(res);
57+
58+
if (this.#conn_init_func) await this.#conn_init_func(conn);
59+
60+
await this.return_conn(conn);
61+
} catch (e) {
62+
sqlite3.sqlite3_close_v2(conn);
63+
}
64+
}
65+
async get_conn() {
66+
if (!this.#conns.length) {
67+
let t;
68+
await new Promise((res, rej) => {
69+
t = setTimeout(rej, this.#max_delay_sec * 1000);
70+
this.#waiters.push(res);
71+
});
72+
clearTimeout(t);
73+
}
74+
75+
return this.#conns.pop();
76+
}
77+
async return_conn(conn) {
78+
// Check if the conn needs to be rolled back:
79+
const auto_commit = sqlite3.sqlite3_get_autocommit(conn);
80+
if (!auto_commit) {
81+
console.warn("Rolling back uncommitted transaction on a connection before returning it to the pool.");
82+
const res = await sqlite3.sqlite3_exec(conn, this.#rollback_ptr, 0, 0, 0);
83+
handle_error(res);
84+
}
85+
this.#conns.push(conn);
86+
const waiter = this.#waiters.shift();
87+
if (waiter) waiter();
88+
}
89+
close() {
90+
sqlite3.free(this.#pathname_ptr);
91+
sqlite3.free(this.#conn_ptr);
92+
sqlite3.free(this.#vfs_ptr);
93+
sqlite3.free(this.#rollback_ptr);
94+
for (const conn of this.#conns) {
95+
sqlite3.sqlite3_close_v2(conn);
96+
}
97+
}
98+
}

dist/sql.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010

1111
export async function open(pathname, flags = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_EXRESCODE) {
1212
let pathname_ptr, conn_ptr;
13-
let conn;
13+
let conn = 0;
1414
try {
1515
pathname_ptr = alloc_str(pathname);
1616
conn_ptr = sqlite3.malloc(4);

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "sql.mjs",
3-
"version": "0.5.0",
3+
"version": "0.6.0",
44
"description": "SQLite Compiled to WASM, asyncified, and then wrapped in a little JavaScript.",
55
"keywords": [
66
"sqlite",

0 commit comments

Comments
 (0)