-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathkysely.ts
More file actions
99 lines (84 loc) 路 2.64 KB
/
Copy pathkysely.ts
File metadata and controls
99 lines (84 loc) 路 2.64 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
96
97
98
99
import { PostgresAdapter, type Kysely } from 'kysely'
import { DatabaseStore } from './database.js'
import type { DatabaseAdapter, KyselyOptions } from '../types/main.js'
/**
* Create a new Kysely store
*/
export function kyselyStore(config: KyselyOptions) {
return {
config,
factory: () => {
const adapter = new KyselyAdapter(config.connection)
return new DatabaseStore(adapter, config)
},
}
}
/**
* Kysely adapter for the DatabaseStore
*/
export class KyselyAdapter implements DatabaseAdapter {
#connection: Kysely<any>
#tableName!: string
constructor(connection: Kysely<any>) {
this.#connection = connection
}
setTableName(tableName: string) {
this.#tableName = tableName
}
async createTableIfNotExists() {
const isPg = this.#connection.getExecutor().adapter instanceof PostgresAdapter
await this.#connection.schema
.createTable(this.#tableName)
.addColumn('key', 'varchar(255)', (col) => col.primaryKey().notNull())
.addColumn('owner', 'varchar(255)', (col) => col.notNull())
.addColumn('expiration', 'bigint', (col) => {
if (!isPg) col.unsigned()
return col
})
.ifNotExists()
.execute()
}
async insertLock(lock: { key: string; owner: string; expiration: number | null }) {
await this.#connection
.insertInto(this.#tableName)
.values({
key: lock.key,
owner: lock.owner,
expiration: lock.expiration,
})
.execute()
}
async acquireLock(lock: { key: string; owner: string; expiration: number | null }) {
const updated = await this.#connection
.updateTable(this.#tableName)
.where('key', '=', lock.key)
.where('expiration', '<=', Date.now())
.set({ owner: lock.owner, expiration: lock.expiration })
.executeTakeFirst()
return Number(updated.numUpdatedRows)
}
async deleteLock(key: string, owner?: string | undefined) {
await this.#connection
.deleteFrom(this.#tableName)
.where('key', '=', key)
.$if(owner !== undefined, (query) => query.where('owner', '=', owner))
.execute()
}
async extendLock(key: string, owner: string, duration: number) {
const updated = await this.#connection
.updateTable(this.#tableName)
.where('key', '=', key)
.where('owner', '=', owner)
.set({ expiration: Date.now() + duration })
.executeTakeFirst()
return Number(updated.numUpdatedRows)
}
async getLock(key: string) {
const result = await this.#connection
.selectFrom(this.#tableName)
.where('key', '=', key)
.select(['owner', 'expiration'])
.executeTakeFirst()
return result
}
}