Skip to content

Commit 3a02d48

Browse files
authored
abstract registration functions into a protocol (#75)
motivation: allow frameworks that want to expose the lifecycle so that their downstream dependencies could register additional items changes: abstract registration functions into a protocol and conform ComponentLifecycle and ServiceLifecycle to it
1 parent adb3939 commit 3a02d48

File tree

2 files changed

+60
-82
lines changed

2 files changed

+60
-82
lines changed

Sources/Lifecycle/Lifecycle.swift

Lines changed: 40 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ public struct LifecycleHandler {
8181

8282
// MARK: - ServiceLifecycle
8383

84+
/// `ServiceLifecycle` provides a basic mechanism to cleanly startup and shutdown the application, freeing resources in order before exiting.
85+
/// By default, also install shutdown hooks based on `Signal` and backtraces.
8486
public struct ServiceLifecycle {
8587
private let configuration: Configuration
8688

@@ -194,41 +196,10 @@ extension ServiceLifecycle {
194196
}
195197
}
196198

197-
public extension ServiceLifecycle {
198-
/// Adds a `LifecycleTask` to a `LifecycleTasks` collection.
199-
///
200-
/// - parameters:
201-
/// - tasks: one or more `LifecycleTask`.
202-
func register(_ tasks: LifecycleTask ...) {
203-
self.underlying.register(tasks)
204-
}
205-
206-
/// Adds a `LifecycleTask` to a `LifecycleTasks` collection.
207-
///
208-
/// - parameters:
209-
/// - tasks: array of `LifecycleTask`.
210-
func register(_ tasks: [LifecycleTask]) {
199+
extension ServiceLifecycle: LifecycleTasksContainer {
200+
public func register(_ tasks: [LifecycleTask]) {
211201
self.underlying.register(tasks)
212202
}
213-
214-
/// Adds a `LifecycleTask` to a `LifecycleTasks` collection.
215-
///
216-
/// - parameters:
217-
/// - label: label of the item, useful for debugging.
218-
/// - start: `LifecycleHandler` to perform the startup.
219-
/// - shutdown: `LifecycleHandler` to perform the shutdown.
220-
func register(label: String, start: LifecycleHandler, shutdown: LifecycleHandler) {
221-
self.underlying.register(label: label, start: start, shutdown: shutdown)
222-
}
223-
224-
/// Adds a `LifecycleTask` to a `LifecycleTasks` collection.
225-
///
226-
/// - parameters:
227-
/// - label: label of the item, useful for debugging.
228-
/// - handler: `LifecycleHandler` to perform the shutdown.
229-
func registerShutdown(label: String, _ handler: LifecycleHandler) {
230-
self.underlying.registerShutdown(label: label, handler)
231-
}
232203
}
233204

234205
extension ServiceLifecycle {
@@ -265,7 +236,7 @@ struct ShutdownError: Error {
265236

266237
// MARK: - ComponentLifecycle
267238

268-
/// `Lifecycle` provides a basic mechanism to cleanly startup and shutdown the application, freeing resources in order before exiting.
239+
/// `ComponentLifecycle` provides a basic mechanism to cleanly startup and shutdown a subsystem in a larger application, freeing resources in order before exiting.
269240
public class ComponentLifecycle: LifecycleTask {
270241
public let label: String
271242
private let logger: Logger
@@ -480,42 +451,35 @@ public class ComponentLifecycle: LifecycleTask {
480451
}
481452
}
482453

483-
public extension ComponentLifecycle {
484-
internal struct Task: LifecycleTask {
485-
let label: String
486-
let start: LifecycleHandler
487-
let shutdown: LifecycleHandler
488-
489-
func start(_ callback: @escaping (Error?) -> Void) {
490-
self.start.run(callback)
454+
extension ComponentLifecycle: LifecycleTasksContainer {
455+
public func register(_ tasks: [LifecycleTask]) {
456+
self.stateLock.withLock {
457+
guard case .idle = self.state else {
458+
preconditionFailure("invalid state, \(self.state)")
459+
}
491460
}
492-
493-
func shutdown(_ callback: @escaping (Error?) -> Void) {
494-
self.shutdown.run(callback)
461+
self.tasksLock.withLock {
462+
self.tasks.append(contentsOf: tasks)
495463
}
496464
}
465+
}
497466

467+
/// A container of `LifecycleTask`, used to register additional `LifecycleTask`
468+
public protocol LifecycleTasksContainer {
498469
/// Adds a `LifecycleTask` to a `LifecycleTasks` collection.
499470
///
500471
/// - parameters:
501-
/// - tasks: one or more `LifecycleTask`.
502-
func register(_ tasks: LifecycleTask ...) {
503-
self.register(tasks)
504-
}
472+
/// - tasks: array of `LifecycleTask`.
473+
func register(_ tasks: [LifecycleTask])
474+
}
505475

476+
extension LifecycleTasksContainer {
506477
/// Adds a `LifecycleTask` to a `LifecycleTasks` collection.
507478
///
508479
/// - parameters:
509-
/// - tasks: array of `LifecycleTask`.
510-
func register(_ tasks: [LifecycleTask]) {
511-
self.stateLock.withLock {
512-
guard case .idle = self.state else {
513-
preconditionFailure("invalid state, \(self.state)")
514-
}
515-
}
516-
self.tasksLock.withLock {
517-
self.tasks.append(contentsOf: tasks)
518-
}
480+
/// - tasks: one or more `LifecycleTask`.
481+
public func register(_ tasks: LifecycleTask ...) {
482+
self.register(tasks)
519483
}
520484

521485
/// Adds a `LifecycleTask` to a `LifecycleTasks` collection.
@@ -524,16 +488,30 @@ public extension ComponentLifecycle {
524488
/// - label: label of the item, useful for debugging.
525489
/// - start: `Handler` to perform the startup.
526490
/// - shutdown: `Handler` to perform the shutdown.
527-
func register(label: String, start: LifecycleHandler, shutdown: LifecycleHandler) {
528-
self.register(Task(label: label, start: start, shutdown: shutdown))
491+
public func register(label: String, start: LifecycleHandler, shutdown: LifecycleHandler) {
492+
self.register(_LifecycleTask(label: label, start: start, shutdown: shutdown))
529493
}
530494

531495
/// Adds a `LifecycleTask` to a `LifecycleTasks` collection.
532496
///
533497
/// - parameters:
534498
/// - label: label of the item, useful for debugging.
535499
/// - handler: `Handler` to perform the shutdown.
536-
func registerShutdown(label: String, _ handler: LifecycleHandler) {
500+
public func registerShutdown(label: String, _ handler: LifecycleHandler) {
537501
self.register(label: label, start: .none, shutdown: handler)
538502
}
539503
}
504+
505+
internal struct _LifecycleTask: LifecycleTask {
506+
let label: String
507+
let start: LifecycleHandler
508+
let shutdown: LifecycleHandler
509+
510+
func start(_ callback: @escaping (Error?) -> Void) {
511+
self.start.run(callback)
512+
}
513+
514+
func shutdown(_ callback: @escaping (Error?) -> Void) {
515+
self.shutdown.run(callback)
516+
}
517+
}

Tests/LifecycleTests/ComponentLifecycleTests.swift

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,16 @@ final class ComponentLifecycleTests: XCTestCase {
4343

4444
let items = (1 ... Int.random(in: 10 ... 20)).map { index -> LifecycleTask in
4545
let id = "item-\(index)"
46-
return ComponentLifecycle.Task(label: id,
47-
start: .sync {
48-
dispatchPrecondition(condition: .onQueue(.global()))
49-
startCalls.append(id)
50-
},
51-
shutdown: .sync {
52-
dispatchPrecondition(condition: .onQueue(.global()))
53-
XCTAssertTrue(startCalls.contains(id))
54-
stopCalls.append(id)
55-
})
46+
return _LifecycleTask(label: id,
47+
start: .sync {
48+
dispatchPrecondition(condition: .onQueue(.global()))
49+
startCalls.append(id)
50+
},
51+
shutdown: .sync {
52+
dispatchPrecondition(condition: .onQueue(.global()))
53+
XCTAssertTrue(startCalls.contains(id))
54+
stopCalls.append(id)
55+
})
5656
}
5757
lifecycle.register(items)
5858

@@ -81,16 +81,16 @@ final class ComponentLifecycleTests: XCTestCase {
8181

8282
let items = (1 ... Int.random(in: 10 ... 20)).map { index -> LifecycleTask in
8383
let id = "item-\(index)"
84-
return ComponentLifecycle.Task(label: id,
85-
start: .sync {
86-
dispatchPrecondition(condition: .onQueue(testQueue))
87-
startCalls.append(id)
88-
},
89-
shutdown: .sync {
90-
dispatchPrecondition(condition: .onQueue(testQueue))
91-
XCTAssertTrue(startCalls.contains(id))
92-
stopCalls.append(id)
93-
})
84+
return _LifecycleTask(label: id,
85+
start: .sync {
86+
dispatchPrecondition(condition: .onQueue(testQueue))
87+
startCalls.append(id)
88+
},
89+
shutdown: .sync {
90+
dispatchPrecondition(condition: .onQueue(testQueue))
91+
XCTAssertTrue(startCalls.contains(id))
92+
stopCalls.append(id)
93+
})
9494
}
9595
lifecycle.register(items)
9696

0 commit comments

Comments
 (0)