Skip to content
This repository was archived by the owner on Apr 19, 2020. It is now read-only.

Commit 558ef54

Browse files
committed
Add src/*
1 parent dfe7f92 commit 558ef54

File tree

4 files changed

+557
-0
lines changed

4 files changed

+557
-0
lines changed

src/index.ts

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
import { SynorError } from '@synor/core'
2+
import { performance } from 'perf_hooks'
3+
import { Client } from 'pg'
4+
import { getQueryStore } from './queries'
5+
import { ensureMigrationRecordTable } from './utils/ensure-migration-record-table'
6+
import { getConfig } from './utils/get-config'
7+
8+
type DatabaseEngine = import('@synor/core').DatabaseEngine
9+
type DatabaseEngineFactory = import('@synor/core').DatabaseEngineFactory
10+
type MigrationSource = import('@synor/core').MigrationSource
11+
12+
export const PostgreSQLDatabaseEngine: DatabaseEngineFactory = (
13+
uri,
14+
{ baseVersion, getAdvisoryLockId, getUserInfo }
15+
): DatabaseEngine => {
16+
const [databaseConfig, engineConfig] = getConfig(uri)
17+
18+
if (typeof getAdvisoryLockId !== 'function') {
19+
throw new SynorError(`Missing: getAdvisoryLockId`)
20+
}
21+
22+
if (typeof getUserInfo !== 'function') {
23+
throw new SynorError(`Missing: getUserInfo`)
24+
}
25+
26+
const advisoryLockIds = getAdvisoryLockId(
27+
databaseConfig.database,
28+
engineConfig.schema,
29+
engineConfig.migrationRecordTable
30+
)
31+
32+
const client = new Client(databaseConfig)
33+
34+
const queryStore = getQueryStore(client, {
35+
migrationRecordTable: engineConfig.migrationRecordTable,
36+
schemaName: engineConfig.schema,
37+
databaseName: databaseConfig.database,
38+
advisoryLockIds
39+
})
40+
41+
let appliedBy = ''
42+
43+
const open: DatabaseEngine['open'] = async () => {
44+
appliedBy = await getUserInfo()
45+
await queryStore.openConnection()
46+
await ensureMigrationRecordTable(queryStore, baseVersion)
47+
}
48+
49+
const close: DatabaseEngine['close'] = async () => {
50+
await queryStore.closeConnection()
51+
}
52+
53+
const lock: DatabaseEngine['lock'] = async () => {
54+
try {
55+
await queryStore.getLock()
56+
} catch (_) {
57+
throw new SynorError('Failed to Get Lock', {
58+
lockId: advisoryLockIds
59+
})
60+
}
61+
}
62+
63+
const unlock: DatabaseEngine['unlock'] = async () => {
64+
const lockResult = await queryStore.releaseLock()
65+
if (!lockResult) {
66+
throw new SynorError('Failed to Release Lock', {
67+
lockId: advisoryLockIds
68+
})
69+
}
70+
}
71+
72+
const drop: DatabaseEngine['drop'] = async () => {
73+
const tableNames = await queryStore.getTableNames()
74+
await queryStore.dropTables(tableNames)
75+
}
76+
77+
const run: DatabaseEngine['run'] = async ({
78+
version,
79+
type,
80+
title,
81+
hash,
82+
body
83+
}: MigrationSource) => {
84+
let dirty = false
85+
86+
const startTime = performance.now()
87+
88+
try {
89+
await client.query(body)
90+
} catch (err) {
91+
dirty = true
92+
93+
throw err
94+
} finally {
95+
const endTime = performance.now()
96+
97+
await queryStore.addRecord({
98+
version,
99+
type,
100+
title,
101+
hash,
102+
appliedAt: new Date(),
103+
appliedBy,
104+
executionTime: endTime - startTime,
105+
dirty
106+
})
107+
}
108+
}
109+
110+
const repair: DatabaseEngine['repair'] = async records => {
111+
await queryStore.deleteDirtyRecords()
112+
113+
for (const { id, hash } of records) {
114+
await queryStore.updateRecord(id, { hash })
115+
}
116+
}
117+
118+
const records: DatabaseEngine['records'] = async startId => {
119+
return queryStore.getRecords(startId)
120+
}
121+
122+
return {
123+
open,
124+
close,
125+
lock,
126+
unlock,
127+
drop,
128+
run,
129+
repair,
130+
records
131+
}
132+
}
133+
134+
export default PostgreSQLDatabaseEngine

0 commit comments

Comments
 (0)