-
-
Notifications
You must be signed in to change notification settings - Fork 20
Expand file tree
/
Copy pathsqlite-backend.ts
More file actions
95 lines (86 loc) · 2.6 KB
/
Copy pathsqlite-backend.ts
File metadata and controls
95 lines (86 loc) · 2.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import { safeParseJobData, SQLBackend, SQLDriverConfig } from "@sidequest/backend";
import { JobData } from "@sidequest/core";
import createKnex, { Knex } from "knex";
import { hostname } from "os";
import path from "path";
const defaultKnexConfig = {
client: "better-sqlite3",
useNullAsDefault: true,
migrations: {
directory: path.join(import.meta.dirname, "..", "migrations"),
tableName: "sidequest_migrations",
extension: "cjs",
},
};
/**
* Represents a backend implementation for SQLite databases using Knex.
*
* This class extends the `SQLBackend` and configures a Knex instance
* for better-sqlite3, specifying the database file path, migration directory,
* migration table name, and file extension for migration files.
*
* @example
* ```typescript
* const backend = new SqliteBackend('./mydb.sqlite');
* ```
*
* @extends SQLBackend
*/
export default class SqliteBackend extends SQLBackend {
constructor(dbConfig: string | SQLDriverConfig = "./sidequest.sqlite") {
const knexConfig: Knex.Config = {
...defaultKnexConfig,
...(typeof dbConfig === "string"
? {
connection: {
filename: dbConfig,
},
}
: dbConfig),
};
const knex = createKnex(knexConfig);
super(knex);
}
async claimPendingJob(queue: string, quantity = 1): Promise<JobData[]> {
const workerName = `sidequest@${hostname()}-${process.pid}`;
const rowsToUpdate = (await this.knex("sidequest_jobs")
.select("id")
.where("state", "waiting")
.andWhere("queue", queue)
.andWhere("available_at", "<=", new Date())
.orderBy("inserted_at")
.limit(quantity)) as { id: number }[];
if (rowsToUpdate.length === 0) {
return [];
}
const result = (await this.knex("sidequest_jobs")
.update({
claimed_by: workerName,
claimed_at: new Date(),
state: "claimed",
})
.where("state", "waiting")
.andWhere(
"id",
"in",
rowsToUpdate.map((row) => row.id),
)
.returning("*")) as JobData[];
return result.map(safeParseJobData);
}
truncDate(date: string, unit: "m" | "h" | "d"): string {
let format: string;
switch (unit) {
case "m":
format = "%Y-%m-%dT%H:%M:00.000"; // Truncate to minute
break;
case "h":
format = "%Y-%m-%dT%H:00:00.000"; // Truncate to hour
break;
case "d":
format = "%Y-%m-%dT00:00:00.000"; // Truncate to day
break;
}
return this.knex.raw(`strftime(?, datetime(${date} / 1000, 'unixepoch', 'localtime'))`, [format]).toQuery();
}
}