Skip to content

Commit 95623b9

Browse files
author
Toni Sharpe
committed
Allows namespacing on request
As with the base fastify instance, the pg decoration will use namespaces. For each namespaced called to the main function, the namespace will be added to the req.pg object too, with similar checks The option to use a chosen namespace with the routeOptions is provided and we make sure that this namespace is used to extract the correct client from req.pg A test also covers this for queries wrapped in a route transaction Resolves #75
1 parent 90febc6 commit 95623b9

File tree

2 files changed

+114
-60
lines changed

2 files changed

+114
-60
lines changed

index.js

+29-7
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ function transact (fn, cb) {
5656
})
5757
}
5858

59+
function extractRequestClient (req, connectionId) {
60+
return connectionId.length ? req.pg[connectionId] : req.pg
61+
}
62+
5963
function fastifyPostgres (fastify, options, next) {
6064
let pg = defaultPg
6165

@@ -111,27 +115,45 @@ function fastifyPostgres (fastify, options, next) {
111115
}
112116

113117
fastify.addHook('onRoute', routeOptions => {
114-
const useTransaction = routeOptions.pg && routeOptions.pg.transact
118+
const transactionConnection = routeOptions.pg && routeOptions.pg.transact
115119

116-
if (useTransaction) {
120+
if (transactionConnection) {
117121
const preHandler = async (req, reply) => {
118122
const client = await pool.connect()
119-
req.pg = client
120-
req.pg.query('BEGIN')
123+
124+
if (name) {
125+
req.pg = {}
126+
if (client[name]) {
127+
throw new Error(`pg client '${name}' is a reserved keyword`)
128+
} else if (req.pg[name]) {
129+
throw new Error(`request client '${name}' has already been registered`)
130+
}
131+
132+
req.pg[name] = client
133+
} else {
134+
if (req.pg) {
135+
throw new Error('request client has already been registered')
136+
} else {
137+
req.pg = client
138+
}
139+
}
140+
141+
extractRequestClient(req, transactionConnection).query('BEGIN')
121142
}
122143

123144
const onError = (req, reply, error, done) => {
124145
req[transactionFailedSymbol] = true
125-
req.pg.query('ROLLBACK', done)
146+
extractRequestClient(req, transactionConnection).query('ROLLBACK', done)
126147
}
127148

128149
const onSend = async (req) => {
150+
const requestClient = extractRequestClient(req, transactionConnection)
129151
try {
130152
if (!req[transactionFailedSymbol]) {
131-
await req.pg.query('COMMIT')
153+
await requestClient.query('COMMIT')
132154
}
133155
} finally {
134-
req.pg.release()
156+
requestClient.release()
135157
}
136158
}
137159

test/req-initialization.test.js

+85-53
Original file line numberDiff line numberDiff line change
@@ -9,78 +9,110 @@ const { connectionString } = require('./helpers')
99
const extractUserCount = response => parseInt(JSON.parse(response.payload).rows[0].userCount)
1010

1111
test('fastify postgress useTransaction route option - ', t => {
12-
test('set to true - ', t => {
13-
test('passing queries provided', async t => {
14-
const fastify = Fastify()
15-
t.teardown(() => fastify.close())
12+
test('queries that succeed provided', async t => {
13+
const fastify = Fastify()
14+
t.teardown(() => fastify.close())
1615

17-
await fastify.register(fastifyPostgres, {
18-
connectionString
19-
})
16+
await fastify.register(fastifyPostgres, {
17+
connectionString
18+
})
19+
20+
await fastify.pg.query('TRUNCATE users')
2021

21-
await fastify.pg.query('TRUNCATE users')
22+
await fastify.get('/count-users', async (req, reply) => {
23+
const result = await fastify.pg.query('SELECT COUNT(*) AS "userCount" FROM users WHERE username=\'pass-opt-in\'')
2224

23-
await fastify.get('/count-users', async (req, reply) => {
24-
const result = await fastify.pg.query('SELECT COUNT(*) AS "userCount" FROM users WHERE username=\'pass-opt-in\'')
25+
reply.send(result)
26+
})
2527

26-
reply.send(result)
27-
})
28+
await fastify.get('/pass', { pg: { transact: true } }, async (req, reply) => {
29+
await req.pg.query('INSERT INTO users(username) VALUES($1) RETURNING id', ['pass-opt-in'])
30+
await req.pg.query('INSERT INTO users(username) VALUES($1) RETURNING id', ['pass-opt-in'])
31+
reply.send('complete')
32+
})
2833

29-
await fastify.get('/pass', { pg: { transact: true } }, async (req, reply) => {
30-
await req.pg.query('INSERT INTO users(username) VALUES($1) RETURNING id', ['pass-opt-in'])
31-
await req.pg.query('INSERT INTO users(username) VALUES($1) RETURNING id', ['pass-opt-in'])
32-
reply.send('complete')
33-
})
34+
await fastify.inject({
35+
method: 'GET',
36+
url: '/pass'
37+
})
3438

35-
await fastify.inject({
36-
method: 'GET',
37-
url: '/pass'
38-
})
39+
const response = await fastify.inject({
40+
method: 'GET',
41+
url: '/count-users'
42+
})
3943

40-
const response = await fastify.inject({
41-
method: 'GET',
42-
url: '/count-users'
43-
})
44+
t.is(extractUserCount(response), 2)
45+
})
46+
test('queries that succeed provided to a namespace', async t => {
47+
const fastify = Fastify()
48+
t.teardown(() => fastify.close())
4449

45-
t.is(extractUserCount(response), 2)
50+
await fastify.register(fastifyPostgres, {
51+
connectionString,
52+
name: 'test'
4653
})
47-
test('failing queries provided', async t => {
48-
const fastify = Fastify()
49-
t.teardown(() => fastify.close())
5054

51-
await fastify.register(fastifyPostgres, {
52-
connectionString
53-
})
55+
await fastify.pg.test.query('TRUNCATE users')
56+
57+
await fastify.get('/count-users', async (req, reply) => {
58+
const result = await fastify.pg.test.query('SELECT COUNT(*) AS "userCount" FROM users WHERE username=\'pass-opt-in\'')
5459

55-
await fastify.pg.query('TRUNCATE users')
60+
reply.send(result)
61+
})
5662

57-
await fastify.get('/count-users', async (req, reply) => {
58-
const result = await fastify.pg.query('SELECT COUNT(*) AS "userCount" FROM users WHERE username=\'fail-opt-in\'')
63+
await fastify.get('/pass', { pg: { transact: 'test' } }, async (req, reply) => {
64+
await req.pg.test.query('INSERT INTO users(username) VALUES($1) RETURNING id', ['pass-opt-in'])
65+
await req.pg.test.query('INSERT INTO users(username) VALUES($1) RETURNING id', ['pass-opt-in'])
5966

60-
reply.send(result)
61-
})
67+
reply.send('complete')
68+
})
6269

63-
await fastify.get('/fail', { pg: { transact: true } }, async (req, reply) => {
64-
await req.pg.query('INSERT INTO users(username) VALUES($1) RETURNING id', ['fail-opt-in'])
65-
await req.pg.query('INSERT INTO users(username) VALUES($1) RETURNING id', ['fail-opt-in'])
66-
await req.pg.query('INSERT INTO nope(username) VALUES($1) RETURNING id', ['fail-opt-in'])
67-
reply.send('complete')
68-
})
70+
await fastify.inject({
71+
method: 'GET',
72+
url: '/pass'
73+
})
6974

70-
await fastify.inject({
71-
method: 'GET',
72-
url: '/fail'
73-
})
75+
const response = await fastify.inject({
76+
method: 'GET',
77+
url: '/count-users'
78+
})
7479

75-
const response = await fastify.inject({
76-
method: 'GET',
77-
url: '/count-users'
78-
})
80+
t.is(extractUserCount(response), 2)
81+
})
82+
test('queries that fail provided', async t => {
83+
const fastify = Fastify()
84+
t.teardown(() => fastify.close())
85+
86+
await fastify.register(fastifyPostgres, {
87+
connectionString
88+
})
89+
90+
await fastify.pg.query('TRUNCATE users')
91+
92+
await fastify.get('/count-users', async (req, reply) => {
93+
const result = await fastify.pg.query('SELECT COUNT(*) AS "userCount" FROM users WHERE username=\'fail-opt-in\'')
94+
95+
reply.send(result)
96+
})
97+
98+
await fastify.get('/fail', { pg: { transact: true } }, async (req, reply) => {
99+
await req.pg.query('INSERT INTO users(username) VALUES($1) RETURNING id', ['fail-opt-in'])
100+
await req.pg.query('INSERT INTO users(username) VALUES($1) RETURNING id', ['fail-opt-in'])
101+
await req.pg.query('INSERT INTO nope(username) VALUES($1) RETURNING id', ['fail-opt-in'])
102+
reply.send('complete')
103+
})
104+
105+
await fastify.inject({
106+
method: 'GET',
107+
url: '/fail'
108+
})
79109

80-
t.is(extractUserCount(response), 0)
110+
const response = await fastify.inject({
111+
method: 'GET',
112+
url: '/count-users'
81113
})
82114

83-
t.end()
115+
t.is(extractUserCount(response), 0)
84116
})
85117

86118
t.end()

0 commit comments

Comments
 (0)