8000 Merge pull request #162 from supabase/feat/pg-meta-cache · sasajib/postgres-meta@82ecaab · GitHub
[go: up one dir, main page]

Skip to content

Commit 82ecaab

Browse files
authored
Merge pull request supabase#162 from supabase/feat/pg-meta-cache
feat(server): cache pg-meta connections
2 parents 5cb1917 + 0da1678 commit 82ecaab

19 files changed

+234
-153
lines changed

package-lock.json

Lines changed: 131 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
},
5858
"dependencies": {
5959
"@sinclair/typebox": "^0.25.1",
60+
"lru-cache": "^7.18.1",
6061
"pg": "^8.7.1",
6162
"pg-format": "^1.0.4",
6263
"pgsql-parser": "^13.3.0",
@@ -70,6 +71,7 @@
7071
"@fastify/type-provider-typebox": "^2.4.0",
7172
"@types/crypto-js": "^4.1.1",
7273
"@types/jest": "^29.2.4",
74+
"@types/lru-cache": "^7.10.10",
7375
"@types/node": "^16.18.3",
7476
"@types/pg": "^8.6.5",
7577
"@types/pg-format": "^1.0.1",

src/server/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,6 @@ export const GENERATE_TYPES =
2525
export const GENERATE_TYPES_INCLUDED_SCHEMAS =
2626
GENERATE_TYPES && process.argv[5] === '--include-schemas' ? process.argv[6]?.split(',') ?? [] : []
2727

28+
export const CONNECTIONS_CACHE_SIZE = Number(process.env.PG_META_CONNECTIONS_CACHE_SIZE || '100')
2829
export const DEFAULT_POOL_CONFIG = { max: 1, connectionTimeoutMillis: PG_CONN_TIMEOUT_SECS * 1000 }
2930
export const PG_META_REQ_HEADER = process.env.PG_META_REQ_HEADER || 'request-id'

src/server/pgMetaCache.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import LruCache from 'lru-cache'
2+
import PostgresMeta from '../lib/PostgresMeta.js'
3+
import { CONNECTIONS_CACHE_SIZE, DEFAULT_POOL_CONFIG } from './constants.js'
4+
5+
const cache = new LruCache<string, PostgresMeta>({
6+
max: CONNECTIONS_CACHE_SIZE,
7+
dispose: async (value) => {
8+
await value.end()
9+
},
10+
})
11+
12+
/**
13+
* Retrieve a PostgresMeta handle from the cache. If it doesn't exist, create
14+
* the handle and insert it into the cache.
15+
*/
16+
const get = (connectionString: string): PostgresMeta => {
17+
let pgMeta: PostgresMeta | undefined = cache.get(connectionString)
18+
19+
if (pgMeta === undefined) {
20+
pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString })
21+
cache.set(connectionString, pgMeta)
22+
}
23+
24+
return pgMeta
25+
}
26+
27+
export default {
28+
get,
29+
}

src/server/routes/columns.ts

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { FastifyInstance } from 'fastify'
2-
import { PostgresMeta } from '../../lib/index.js'
3-
import { DEFAULT_POOL_CONFIG } from '../constants.js'
2+
import PgMetaCache from '../pgMetaCache.js'
43
import { extractRequestForLogging } from '../utils.js'
54

65
export default async (fastify: FastifyInstance) => {
@@ -22,15 +21,14 @@ export default async (fastify: FastifyInstance) => {
2221
const limit = request.query.limit
2322
const offset = request.query.offset
2423

25-
const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString })
24+
const pgMeta = PgMetaCache.get(connectionString)
2625
const { data, error } = await pgMeta.columns.list({
2726
includeSystemSchemas,
2827
includedSchemas,
2928
excludedSchemas,
3029
limit,
3130
offset,
3231
})
33-
await pgMeta.end()
3432
if (error) {
3533
request.log.error({ error, request: extractRequestForLogging(request) })
3634
reply.code(500)
@@ -60,14 +58,13 @@ export default async (fastify: FastifyInstance) => {
6058
} = request
6159
const includeSystemSchemas = request.query.include_system_schemas === 'true'
6260

63-
const pgMeta: PostgresMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString })
61+
const pgMeta = PgMetaCache.get(connectionString)
6462
const { data, error } = await pgMeta.columns.list({
6563
tableId: Number(tableId),
6664
includeSystemSchemas,
6765
limit: Number(limit),
6866
offset: Number(offset),
6967
})
70-
await pgMeta.end()
7168
if (error) {
7269
request.log.error({ error, request: extractRequestForLogging(request) })
7370
reply.code(500)
@@ -82,9 +79,8 @@ export default async (fastify: FastifyInstance) => {
8279
} = request
8380
const ordinalPosition = ordinalPositionWithDot.slice(1)
8481

85-
const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString })
82+
const pgMeta = PgMetaCache.get(connectionString)
8683
const { data, error } = await pgMeta.columns.retrieve({ id: `${tableId}.${ordinalPosition}` })
87-
await pgMeta.end()
8884
if (error) {
8985
request.log.error({ error, request: extractRequestForLogging(request) })
9086
reply.code(400)
@@ -104,9 +100,8 @@ export default async (fastify: FastifyInstance) => {
104100
}>('/', async (request, reply) => {
105101
const connectionString = request.headers.pg
106102

107-
const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString })
103+
const pgMeta = PgMetaCache.get(connectionString)
108104
const { data, error } = await pgMeta.columns.create(request.body as any)
109-
await pgMeta.end()
110105
if (error) {
111106
request.log.error({ error, request: extractRequestForLogging(request) })
112107
reply.code(400)
@@ -126,9 +121,8 @@ export default async (fastify: FastifyInstance) => {
126121
}>('/:id(\\d+\\.\\d+)', async (request, reply) => {
127122
const connectionString = request.headers.pg
128123

129-
const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString })
124+
const pgMeta = PgMetaCache.get(connectionString)
130125
const { data, error } = await pgMeta.columns.update(request.params.id, request.body as any)
131-
await pgMeta.end()
132126
if (error) {
133127
request.log.error({ error, request: extractRequestForLogging(request) })
134128
reply.code(400)
@@ -151,9 +145,8 @@ export default async (fastify: FastifyInstance) => {
151145
const connectionString = request.headers.pg
152146
const cascade = request.query.cascade === 'true'
153147

154-
const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString })
148+
const pgMeta = PgMetaCache.get(connectionString)
155149
const { data, error } = await pgMeta.columns.remove(request.params.id, { cascade })
156-
await pgMeta.end()
157150
if (error) {
158151
request.log.error({ error, request: extractRequestForLogging(request) })
159152
reply.code(400)

0 commit comments

Comments
 (0)
0