Skip to content

Commit 8df2c78

Browse files
authored
Migration service (#47)
1 parent 1b322da commit 8df2c78

File tree

2 files changed

+98
-0
lines changed

2 files changed

+98
-0
lines changed
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Hummingbird server framework project
4+
//
5+
// Copyright (c) 2025 the Hummingbird authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See hummingbird/CONTRIBUTORS.txt for the list of Hummingbird authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
import Logging
16+
import PostgresNIO
17+
import ServiceLifecycle
18+
19+
/// Service that runs a database migration
20+
public struct DatabaseMigrationService: Service {
21+
let client: PostgresClient
22+
let groups: [DatabaseMigrationGroup]
23+
let migrations: DatabaseMigrations
24+
let logger: Logger
25+
let dryRun: Bool
26+
27+
/// Initialize DatabaseMigrationService
28+
/// - Parameters:
29+
/// - client: Postgres client
30+
/// - migrations: Migrations to apply
31+
/// - groups: Migration groups to apply
32+
/// - logger: logger
33+
/// - dryRun: Is this a dry run
34+
public init(
35+
client: PostgresClient,
36+
migrations: DatabaseMigrations,
37+
groups: [DatabaseMigrationGroup] = [],
38+
logger: Logger,
39+
dryRun: Bool
40+
) {
41+
self.client = client
42+
self.groups = groups
43+
self.migrations = migrations
44+
self.logger = logger
45+
self.dryRun = dryRun
46+
}
47+
48+
public func run() async throws {
49+
try await self.migrations.apply(client: self.client, groups: self.groups, logger: self.logger, dryRun: self.dryRun)
50+
try? await gracefulShutdown()
51+
}
52+
}

Tests/PostgresMigrationsTests/MigrationTests.swift

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import Atomics
22
import Foundation
33
import Logging
44
import PostgresNIO
5+
import ServiceLifecycle
56
import XCTest
67

78
@testable import PostgresMigrations
@@ -423,6 +424,51 @@ final class MigrationTests: XCTestCase {
423424
try await migrations.apply(client: client, groups: [.default, .test], logger: Self.logger, dryRun: false)
424425
}
425426
}
427+
428+
func testMigrationService() async throws {
429+
struct WaitRevertMigrationService: Service {
430+
let client: PostgresClient
431+
let migrations: DatabaseMigrations
432+
let logger: Logger
433+
func run() async throws {
434+
try await migrations.waitUntilCompleted()
435+
try await migrations.revert(client: client, groups: [.test], logger: logger, dryRun: false)
436+
}
437+
}
438+
let logger = {
439+
var logger = Logger(label: "MigrationTests")
440+
logger.logLevel = .debug
441+
return logger
442+
}()
443+
let client = try await PostgresClient(
444+
configuration: getPostgresConfiguration(),
445+
backgroundLogger: logger
446+
)
447+
let migrations = DatabaseMigrations()
448+
await migrations.add(TestMigration(name: "testMigrationService", group: .test))
449+
let serviceGroup = ServiceGroup(
450+
configuration: .init(
451+
services: [
452+
client,
453+
DatabaseMigrationService(
454+
client: client,
455+
migrations: migrations,
456+
groups: [.test],
457+
logger: logger,
458+
dryRun: false
459+
),
460+
WaitRevertMigrationService(client: client, migrations: migrations, logger: logger),
461+
],
462+
gracefulShutdownSignals: [.sigterm, .sigint],
463+
logger: logger
464+
)
465+
)
466+
do {
467+
try await serviceGroup.run()
468+
} catch let error as ServiceGroupError where error == .serviceFinishedUnexpectedly() {
469+
// ... we're good
470+
}
471+
}
426472
}
427473

428474
extension DatabaseMigrationGroup {

0 commit comments

Comments
 (0)