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

supabase / storage / 29148700684

11 Jul 2026 10:02AM UTC coverage: 79.824% (+0.4%) from 79.376%
29148700684

Pull #1043

github

web-flow
Merge be6c21cdc into b6b815fbd
Pull Request #1043: feat: add queue management handlers

5537 of 7500 branches covered (73.83%)

Branch coverage included in aggregate %.

282 of 311 new or added lines in 11 files covered. (90.68%)

10767 of 12925 relevant lines covered (83.3%)

417.27 hits per line

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

74.24
/src/internal/queue/database.ts
1
import EventEmitter from 'node:events'
2
import { ERRORS } from '@internal/errors'
3
import pg from 'pg'
4
import { Db } from 'pg-boss'
5
import {
6
  type PgBeginTransactionOptions,
7
  type PgExecutor,
8
  PgPoolExecutor,
9
} from '../database/pg-connection'
10

11
export { quoteIdentifier } from '../database/sql'
12

13
export class QueueDB extends EventEmitter implements Db {
14
  opened = false
2✔
15
  isOurs = true
2✔
16
  events = {
2✔
17
    error: 'error',
18
  }
19
  protected config: pg.PoolConfig
20
  protected pool?: pg.Pool
21

22
  constructor(config: pg.PoolConfig) {
23
    super()
2✔
24
    this.config = config
2✔
25
  }
26

27
  async open() {
28
    this.pool = new pg.Pool({ ...this.config, min: 0 })
2✔
29
    this.pool.on('error', (error) => this.emit('error', error))
2✔
30

31
    this.opened = true
2✔
32
  }
33

34
  async close() {
35
    this.opened = false
2✔
36
    await this.pool?.end()
2✔
37
  }
38

39
  beginTransaction(options?: PgBeginTransactionOptions) {
40
    if (!this.opened || !this.pool) {
20!
NEW
41
      throw ERRORS.InternalError(undefined, `QueueDB not opened ${this.opened}`)
×
42
    }
43

44
    return new PgPoolExecutor(this.pool).beginTransaction(options)
20✔
45
  }
46

47
  protected async useTransaction<T>(fn: (client: pg.PoolClient) => Promise<T>): Promise<T> {
48
    if (!this.opened || !this.pool) {
13!
49
      throw ERRORS.InternalError(undefined, `QueueDB not opened ${this.opened}`)
×
50
    }
51

52
    const client = await this.pool.connect()
13✔
53

54
    // Create a promise that rejects if the client emits an error
55
    // (e.g. connection lost, statement_timeout at the backend level)
56
    let clientError: Error | undefined
57
    const onError = (e: Error) => {
13✔
58
      clientError = e
×
59
    }
60
    client.on('error', onError)
13✔
61

62
    try {
13✔
63
      await client.query('BEGIN')
13✔
64

65
      if (this.config.statement_timeout && this.config.statement_timeout > 0) {
13!
66
        await client.query(`SET LOCAL statement_timeout = ${this.config.statement_timeout}`)
13✔
67
      }
68

69
      const result = await fn(client)
13✔
70

71
      if (clientError) {
13!
72
        throw clientError
×
73
      }
74

75
      await client.query('COMMIT')
13✔
76
      return result
13✔
77
    } catch (err) {
78
      const rollbackErr = await client.query('ROLLBACK').catch((e) => e as Error)
×
79

80
      const errors = [err as Error, clientError, rollbackErr].filter(
×
81
        (e): e is Error => e instanceof Error
×
82
      )
83

84
      if (errors.length === 1) throw errors[0]
×
85
      throw new AggregateError(errors, 'Queue transaction failed')
×
86
    } finally {
87
      client.off('error', onError)
13✔
88
      client.release(clientError)
13✔
89
    }
90
  }
91

92
  async executeSql(text: string, values: unknown[]): Promise<{ rows: unknown[] }> {
93
    if (this.opened && this.pool) {
13!
94
      return this.useTransaction((client) => client.query(text, values))
13✔
95
    }
96

97
    throw ERRORS.InternalError(undefined, `QueueDB not opened ${this.opened} ${text}`)
×
98
  }
99
}
100

101
export class PgQueueDB extends EventEmitter implements Db {
102
  events = {
2✔
103
    error: 'error',
104
  }
105

106
  constructor(protected readonly db: PgExecutor) {
2✔
107
    super()
2✔
108
  }
109

110
  async executeSql(text: string, values: unknown[]): Promise<{ rows: unknown[] }> {
111
    const result = await this.db.query({
1✔
112
      text,
113
      values: values.map((value) => (value === undefined ? null : value)),
3✔
114
    })
115

116
    return { rows: result.rows }
1✔
117
  }
118
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc