Skip to content

Commit 0bc2355

Browse files
committed
Start migrating blink. Also add better shutdown handling for ogcard
1 parent 46a97fa commit 0bc2355

File tree

4 files changed

+97
-27
lines changed

4 files changed

+97
-27
lines changed

.github/workflows/build-and-push-link-aws.yaml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
name: build-and-push-link-aws
22
on:
33
workflow_dispatch:
4+
pull_request:
5+
paths:
6+
- 'bskylink/**'
7+
- 'Dockerfile.bskylink'
8+
- '.github/workflows/build-and-push-link-aws.yaml'
49

510
env:
611
REGISTRY: ${{ secrets.AWS_ECR_REGISTRY_USEAST2_PACKAGES_REGISTRY }}
@@ -45,7 +50,7 @@ jobs:
4550
uses: docker/build-push-action@v4
4651
with:
4752
context: .
48-
push: ${{ github.event_name != 'pull_request' }}
53+
push: true
4954
file: ./Dockerfile.bskylink
5055
tags: ${{ steps.meta.outputs.tags }}
5156
labels: ${{ steps.meta.outputs.labels }}

bskylink/src/bin.ts

Lines changed: 55 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,62 @@
11
import {Database, envToCfg, httpLogger, LinkService, readEnv} from './index.js'
2+
23
async function main() {
3-
const env = readEnv()
4-
const cfg = envToCfg(env)
5-
if (cfg.db.migrationUrl) {
6-
const migrateDb = Database.postgres({
7-
url: cfg.db.migrationUrl,
8-
schema: cfg.db.schema,
9-
})
10-
await migrateDb.migrateToLatestOrThrow()
11-
await migrateDb.close()
12-
}
4+
try {
5+
httpLogger.info('Starting blink service')
136

14-
const link = await LinkService.create(cfg)
7+
const env = readEnv()
8+
const cfg = envToCfg(env)
159

16-
if (link.ctx.cfg.service.safelinkEnabled) {
17-
link.ctx.safelinkClient.runFetchEvents()
18-
}
10+
httpLogger.info(
11+
{
12+
port: cfg.service.port,
13+
safelinkEnabled: cfg.service.safelinkEnabled,
14+
hasDbUrl: !!cfg.db.url,
15+
hasDbMigrationUrl: !!cfg.db.migrationUrl,
16+
},
17+
'Configuration loaded',
18+
)
19+
20+
if (cfg.db.migrationUrl) {
21+
httpLogger.info('Running database migrations')
22+
const migrateDb = Database.postgres({
23+
url: cfg.db.migrationUrl,
24+
schema: cfg.db.schema,
25+
})
26+
await migrateDb.migrateToLatestOrThrow()
27+
await migrateDb.close()
28+
httpLogger.info('Database migrations completed')
29+
}
1930

20-
await link.start()
21-
httpLogger.info('link service is running')
22-
process.on('SIGTERM', async () => {
23-
httpLogger.info('link service is stopping')
24-
await link.destroy()
25-
httpLogger.info('link service is stopped')
26-
})
31+
httpLogger.info('Creating LinkService')
32+
const link = await LinkService.create(cfg)
33+
34+
if (link.ctx.cfg.service.safelinkEnabled) {
35+
httpLogger.info('Starting Safelink client')
36+
link.ctx.safelinkClient.runFetchEvents()
37+
}
38+
39+
await link.start()
40+
httpLogger.info('Link service is running')
41+
42+
process.on('SIGTERM', async () => {
43+
httpLogger.info('Link service is stopping')
44+
await link.destroy()
45+
httpLogger.info('Link service is stopped')
46+
})
47+
} catch (error) {
48+
httpLogger.error(
49+
{
50+
error: String(error),
51+
stack: error instanceof Error ? error.stack : undefined,
52+
},
53+
'Failed to start blink service',
54+
)
55+
process.exit(1)
56+
}
2757
}
2858

29-
main()
59+
main().catch(error => {
60+
console.error('Unhandled startup error:', error)
61+
process.exit(1)
62+
})

bskylink/src/db/index.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,16 @@ export class Database {
3434

3535
static postgres(opts: PgOptions): Database {
3636
const {schema, url, txLockNonce} = opts
37+
log.info(
38+
{
39+
schema,
40+
poolSize: opts.poolSize,
41+
poolMaxUses: opts.poolMaxUses,
42+
poolIdleTimeoutMs: opts.poolIdleTimeoutMs,
43+
},
44+
'Creating database connection',
45+
)
46+
3747
const pool =
3848
opts.pool ??
3949
new Pg.Pool({

bskyogcard/src/index.ts

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,10 @@ export class CardService {
6262
// Start main application server
6363
this.server = this.app.listen(this.ctx.cfg.service.port)
6464
this.server.keepAliveTimeout = 90000
65-
this.terminator = createHttpTerminator({server: this.server})
65+
this.terminator = createHttpTerminator({
66+
server: this.server,
67+
gracefulTerminationTimeout: 15000, // 15s timeout for in-flight requests
68+
})
6669
await events.once(this.server, 'listening')
6770

6871
// Start separate metrics server
@@ -73,13 +76,32 @@ export class CardService {
7376
})
7477

7578
this.metricsServer = metricsApp.listen(this.ctx.cfg.service.metricsPort)
76-
this.metricsTerminator = createHttpTerminator({server: this.metricsServer})
79+
this.metricsTerminator = createHttpTerminator({
80+
server: this.metricsServer,
81+
gracefulTerminationTimeout: 2000, // 2s timeout for metrics server
82+
})
7783
await events.once(this.metricsServer, 'listening')
7884
}
7985

8086
async destroy() {
87+
const startTime = Date.now()
88+
8189
this.ctx.abortController.abort()
82-
await this.terminator?.terminate()
83-
await this.metricsTerminator?.terminate()
90+
91+
const shutdownPromises = []
92+
93+
if (this.terminator) {
94+
shutdownPromises.push(this.terminator.terminate())
95+
}
96+
97+
if (this.metricsTerminator) {
98+
shutdownPromises.push(this.metricsTerminator.terminate())
99+
}
100+
101+
await Promise.all(shutdownPromises)
102+
103+
const elapsed = Date.now() - startTime
104+
const {httpLogger} = await import('./logger.js')
105+
httpLogger.info(`Graceful shutdown completed in ${elapsed}ms`)
84106
}
85107
}

0 commit comments

Comments
 (0)