Skip to content

Commit 4adae5d

Browse files
committed
Async hooks
1 parent 0a4e3bd commit 4adae5d

19 files changed

+192
-40
lines changed

Chapter 15/myProject/Sources/App/Framework/Hooks/Application+Hooks.swift renamed to Chapter 15/myProject/Sources/App/Framework/Hooks/Application+HookStorage.swift

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,3 @@ extension Application {
2727
}
2828
}
2929
}
30-
31-
extension Application {
32-
33-
func invoke<ReturnType>(_ name: String, args: HookArguments = [:]) -> ReturnType? {
34-
let ctxArgs = args.merging(["app": self]) { (_, new) in new }
35-
return hooks.invoke(name, args: ctxArgs)
36-
}
37-
38-
func invokeAll<ReturnType>(_ name: String, args: HookArguments = [:]) -> [ReturnType] {
39-
let ctxArgs = args.merging(["app": self]) { (_, new) in new }
40-
return hooks.invokeAll(name, args: ctxArgs)
41-
}
42-
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//
2+
// File.swift
3+
//
4+
//
5+
// Created by Tibor Bodecs on 2022. 01. 08..
6+
//
7+
8+
import Vapor
9+
10+
extension Application {
11+
12+
func invokeAsync<ReturnType>(_ name: String, args: HookArguments = [:]) async throws -> ReturnType? {
13+
let ctxArgs = args.merging(["app": self]) { (_, new) in new }
14+
return try await hooks.invokeAsync(name, args: ctxArgs)
15+
}
16+
17+
func invokeAllAsync<ReturnType>(_ name: String, args: HookArguments = [:]) async throws -> [ReturnType] {
18+
let ctxArgs = args.merging(["app": self]) { (_, new) in new }
19+
return try await hooks.invokeAllAsync(name, args: ctxArgs)
20+
}
21+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//
2+
// File.swift
3+
//
4+
//
5+
// Created by Tibor Bodecs on 2022. 01. 08..
6+
//
7+
8+
struct AsyncAnyHookFunction: AsyncHookFunction {
9+
10+
private let functionBlock: AsyncHookFunctionSignature<Any>
11+
12+
init(_ functionBlock: @escaping AsyncHookFunctionSignature<Any>) {
13+
self.functionBlock = functionBlock
14+
}
15+
16+
func invokeAsync(_ args: HookArguments) async throws -> Any {
17+
try await functionBlock(args)
18+
}
19+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//
2+
// File.swift
3+
//
4+
//
5+
// Created by Tibor Bodecs on 2022. 01. 08..
6+
//
7+
8+
protocol AsyncHookFunction {
9+
func invokeAsync(_: HookArguments) async throws -> Any
10+
}
11+
12+
typealias AsyncHookFunctionSignature<T> = (HookArguments) async throws -> T
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//
2+
// File.swift
3+
//
4+
//
5+
// Created by Tibor Bodecs on 2022. 01. 08..
6+
//
7+
8+
extension HookStorage {
9+
10+
func registerAsync<ReturnType>(_ name: String, use block: @escaping AsyncHookFunctionSignature<ReturnType>) {
11+
let function = AsyncAnyHookFunction { args -> Any in
12+
try await block(args)
13+
}
14+
let pointer = HookFunctionPointer<AsyncHookFunction>(name: name, function: function, returnType: ReturnType.self)
15+
asyncPointers.append(pointer)
16+
}
17+
18+
func invokeAsync<ReturnType>(_ name: String, args: HookArguments = [:]) async throws -> ReturnType? {
19+
try await asyncPointers.first { $0.name == name && $0.returnType == ReturnType.self }?.pointer.invokeAsync(args) as? ReturnType
20+
}
21+
22+
func invokeAllAsync<ReturnType>(_ name: String, args: HookArguments = [:]) async throws -> [ReturnType] {
23+
let fns = asyncPointers.filter { $0.name == name && $0.returnType == ReturnType.self }
24+
var result: [ReturnType] = []
25+
for fn in fns {
26+
if let res = try await fn.pointer.invokeAsync(args) as? ReturnType {
27+
result.append(res)
28+
}
29+
}
30+
return result
31+
}
32+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//
2+
// File.swift
3+
//
4+
//
5+
// Created by Tibor Bodecs on 2022. 01. 08..
6+
//
7+
8+
import Vapor
9+
10+
extension Request {
11+
12+
func invokeAsync<ReturnType>(_ name: String, args: HookArguments = [:]) async throws -> ReturnType? {
13+
let ctxArgs = args.merging(["req": self]) { (_, new) in new }
14+
return try await application.invokeAsync(name, args: ctxArgs)
15+
}
16+
17+
func invokeAllAsync<ReturnType>(_ name: String, args: HookArguments = [:]) async throws -> [ReturnType] {
18+
let ctxArgs = args.merging(["req": self]) { (_, new) in new }
19+
return try await application.invokeAllAsync(name, args: ctxArgs)
20+
}
21+
}
22+
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
//
2+
// File.swift
3+
//
4+
//
5+
// Created by Tibor Bodecs on 2022. 01. 08..
6+
//
7+
8+
typealias HookArguments = [String: Any]

Chapter 15/myProject/Sources/App/Framework/Hooks/HookStorage.swift

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,12 @@
77

88
final class HookStorage {
99

10-
private var pointers: [HookFunctionPointer<HookFunction>]
11-
10+
var pointers: [HookFunctionPointer<HookFunction>]
11+
var asyncPointers: [HookFunctionPointer<AsyncHookFunction>]
12+
1213
init() {
1314
self.pointers = []
14-
}
15-
16-
func register<ReturnType>(_ name: String, use block: @escaping HookFunctionSignature<ReturnType>) {
17-
let function = AnyHookFunction { args -> Any in
18-
block(args)
19-
}
20-
let pointer = HookFunctionPointer<HookFunction>(name: name, function: function, returnType: ReturnType.self)
21-
pointers.append(pointer)
22-
}
23-
24-
func invoke<ReturnType>(_ name: String, args: HookArguments = [:]) -> ReturnType? {
25-
pointers.first { $0.name == name && $0.returnType == ReturnType.self }?.pointer.invoke(args) as? ReturnType
26-
}
27-
28-
func invokeAll<ReturnType>(_ name: String, args: HookArguments = [:]) -> [ReturnType] {
29-
let fn = pointers.filter { $0.name == name && $0.returnType == ReturnType.self }
30-
return fn.compactMap { $0.pointer.invoke(args) as? ReturnType }
31-
}
15+
self.asyncPointers = []
16+
}
3217
}
3318

Chapter 15/myProject/Sources/App/Framework/Hooks/AnyHookFunction.swift renamed to Chapter 15/myProject/Sources/App/Framework/Hooks/Sync/AnyHookFunction.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,10 @@ struct AnyHookFunction: HookFunction {
99

1010
private let functionBlock: HookFunctionSignature<Any>
1111

12-
/// anonymous hooks can be initialized using a function block
1312
init(_ functionBlock: @escaping HookFunctionSignature<Any>) {
1413
self.functionBlock = functionBlock
1514
}
1615

17-
/// since they are hook functions they can be invoked with a given argument
1816
func invoke(_ args: HookArguments) -> Any {
1917
functionBlock(args)
2018
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//
2+
// File.swift
3+
//
4+
//
5+
// Created by Tibor Bodecs on 2022. 01. 08..
6+
//
7+
8+
import Vapor
9+
10+
extension Application {
11+
12+
func invoke<ReturnType>(_ name: String, args: HookArguments = [:]) -> ReturnType? {
13+
let ctxArgs = args.merging(["app": self]) { (_, new) in new }
14+
return hooks.invoke(name, args: ctxArgs)
15+
}
16+
17+
func invokeAll<ReturnType>(_ name: String, args: HookArguments = [:]) -> [ReturnType] {
18+
let ctxArgs = args.merging(["app": self]) { (_, new) in new }
19+
return hooks.invokeAll(name, args: ctxArgs)
20+
}
21+
}

0 commit comments

Comments
 (0)