• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

supabase / storage / 30076416950

24 Jul 2026 07:43AM UTC coverage: 80.268% (-0.1%) from 80.395%
30076416950

Pull #1230

github

web-flow
Merge 71d199328 into e845f9989
Pull Request #1230: feat: Added separate Database application.

5862 of 7870 branches covered (74.49%)

Branch coverage included in aggregate %.

527 of 634 new or added lines in 22 files covered. (83.12%)

11235 of 13430 relevant lines covered (83.66%)

420.13 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

72.31
/src/http/plugins/vector.ts
1
import {
2
  attachPoolErrorHandler,
3
  getTenantConfig,
4
  multitenantPgExecutor,
5
  PgPoolExecutor,
6
} from '@internal/database'
7
import { createPostgresTypeParsers } from '@internal/database/postgres/type-parsers'
8
import { deriveVectorDatabaseUrl } from '@internal/database/vector-store-url'
9
import { ERRORS } from '@internal/errors'
10
import { logger, logSchema } from '@internal/monitoring'
11
import {
12
  BucketScopedSingleShard,
13
  PgShardStoreFactory,
14
  ShardCatalog,
15
  Sharder,
16
  SingleShard,
17
} from '@internal/sharding'
18
import {
19
  createS3VectorClient,
20
  createVectorTransactionPgResolver,
21
  PgVectorMetadataDB,
22
  PgVectorStore,
23
  S3Vector,
24
  VectorStore,
25
  VectorStoreManager,
26
} from '@storage/protocols/vector'
27
import { FastifyInstance } from 'fastify'
28
import fastifyPlugin from 'fastify-plugin'
29
import { Pool as PgPool } from 'pg'
30
import { getConfig } from '../../config'
31

32
declare module 'fastify' {
33
  interface FastifyRequest {
34
    s3Vector: VectorStoreManager
35
  }
36
}
37

38
export const s3vector = fastifyPlugin(async function (fastify: FastifyInstance) {
41✔
39
  const config = getConfig()
291✔
40
  const {
41
    vectorBucketProvider,
42
    vectorDatabaseCreate,
43
    vectorDatabaseURL,
44
    vectorS3Buckets,
45
    isMultitenant,
46
    databaseApplicationName,
47
  } = config
291✔
48

49
  let s3Adapter: S3Vector | undefined
50
  if (vectorBucketProvider === 's3' && vectorS3Buckets.length > 0) {
291✔
51
    s3Adapter = new S3Vector(createS3VectorClient())
289✔
52
  }
53

54
  // pgvector + single-tenant: VECTOR_DATABASE_URL is the maintenance URL the
55
  // migration runner used to CREATE DATABASE; the runtime pool targets the
56
  // derived `storage_vectors` database on the same server. When
57
  // VECTOR_DATABASE_CREATE=false, the runtime pool targets VECTOR_DATABASE_URL
58
  // directly.
59
  let stPgVectorAdapter: PgVectorStore | undefined
60
  let stPgVectorPool: PgPool | undefined
61
  if (vectorBucketProvider === 'pgvector' && !isMultitenant && vectorDatabaseURL) {
291✔
62
    const connectionString = vectorDatabaseCreate
1!
63
      ? deriveVectorDatabaseUrl(vectorDatabaseURL)
64
      : vectorDatabaseURL
65
    stPgVectorPool = attachPoolErrorHandler(
1✔
66
      new PgPool({
67
        connectionString,
68
        application_name: databaseApplicationName,
69
        min: 0,
70
        max: 10,
71
        types: createPostgresTypeParsers(),
72
      }),
73
      (error) => {
NEW
74
        logSchema.warning(logger, '[Vector] Idle pgvector client error', {
×
75
          type: 'db',
76
          error,
77
        })
78
      }
79
    )
80
    // TODO: watt
81
    stPgVectorAdapter = new PgVectorStore(new PgPoolExecutor(stPgVectorPool))
1✔
82
    fastify.addHook('onClose', async () => {
1✔
83
      await stPgVectorPool?.end()
1✔
84
    })
85
  }
86

87
  const featureEnabled =
88
    (vectorBucketProvider === 's3' && Boolean(s3Adapter)) ||
291✔
89
    (vectorBucketProvider === 'pgvector' && (isMultitenant || Boolean(stPgVectorAdapter)))
90

91
  fastify.addHook('preHandler', async (req) => {
291✔
92
    if (!featureEnabled) {
152✔
93
      throw ERRORS.FeatureNotEnabled('vector', 'Vector service not configured')
1✔
94
    }
95

96
    const { vectorMaxBucketsCount, vectorMaxIndexesCount } = config
151✔
97

98
    let maxBucketCount = vectorMaxBucketsCount
151✔
99
    let maxIndexCount = vectorMaxIndexesCount
151✔
100

101
    if (isMultitenant) {
151!
102
      const { features } = await getTenantConfig(req.tenantId)
×
103
      maxBucketCount = features?.vectorBuckets?.maxBuckets || vectorMaxBucketsCount
×
104
      maxIndexCount = features?.vectorBuckets?.maxIndexes || vectorMaxIndexesCount
×
105
    }
106

107
    const store = new PgVectorMetadataDB(req.db)
151✔
108

109
    let adapter: VectorStore
110
    if (vectorBucketProvider === 'pgvector') {
151!
111
      adapter = isMultitenant
×
112
        ? new PgVectorStore(createVectorTransactionPgResolver(req.db))
113
        : stPgVectorAdapter!
114
    } else {
115
      adapter = s3Adapter!
151✔
116
    }
117

118
    let shard: Sharder
119
    if (vectorBucketProvider === 'pgvector') {
151!
120
      shard = new BucketScopedSingleShard({
×
121
        keyPrefix: 'pgvector__',
122
        capacity: Number.MAX_SAFE_INTEGER,
123
      })
124
    } else if (isMultitenant) {
151!
125
      shard = new ShardCatalog(new PgShardStoreFactory(multitenantPgExecutor))
×
126
    } else {
127
      shard = new SingleShard({
151✔
128
        shardKey: vectorS3Buckets[0],
129
        capacity: 10000,
130
      })
131
    }
132

133
    req.s3Vector = new VectorStoreManager(adapter, store, shard, {
151✔
134
      tenantId: req.tenantId,
135
      maxBucketCount,
136
      maxIndexCount,
137
    })
138
  })
139
})
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc