/src/grpc-swift/Sources/GRPC/ConnectionPool/ConnectionPool+Waiter.swift
Line | Count | Source |
1 | | /* |
2 | | * Copyright 2021, gRPC Authors All rights reserved. |
3 | | * |
4 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | | * you may not use this file except in compliance with the License. |
6 | | * You may obtain a copy of the License at |
7 | | * |
8 | | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | | * |
10 | | * Unless required by applicable law or agreed to in writing, software |
11 | | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | | * See the License for the specific language governing permissions and |
14 | | * limitations under the License. |
15 | | */ |
16 | | import NIOCore |
17 | | import NIOHTTP2 |
18 | | |
19 | | extension ConnectionPool { |
20 | | @usableFromInline |
21 | | internal final class Waiter { |
22 | | /// A promise to complete with the initialized channel. |
23 | | @usableFromInline |
24 | | internal let _promise: EventLoopPromise<Channel> |
25 | | |
26 | | @usableFromInline |
27 | 0 | internal var _channelFuture: EventLoopFuture<Channel> { |
28 | 0 | return self._promise.futureResult |
29 | 0 | } |
30 | | |
31 | | /// The channel initializer. |
32 | | @usableFromInline |
33 | | internal let _channelInitializer: @Sendable (Channel) -> EventLoopFuture<Void> |
34 | | |
35 | | /// The deadline at which the timeout is scheduled. |
36 | | @usableFromInline |
37 | | internal let _deadline: NIODeadline |
38 | | |
39 | | /// A scheduled task which fails the stream promise should the pool not provide |
40 | | /// a stream in time. |
41 | | @usableFromInline |
42 | | internal var _scheduledTimeout: Scheduled<Void>? |
43 | | |
44 | | /// An identifier for this waiter. |
45 | | @usableFromInline |
46 | 0 | internal var id: ID { |
47 | 0 | return ID(self) |
48 | 0 | } |
49 | | |
50 | | @usableFromInline |
51 | | internal init( |
52 | | deadline: NIODeadline, |
53 | | promise: EventLoopPromise<Channel>, |
54 | | channelInitializer: @escaping @Sendable (Channel) -> EventLoopFuture<Void> |
55 | 0 | ) { |
56 | 0 | self._deadline = deadline |
57 | 0 | self._promise = promise |
58 | 0 | self._channelInitializer = channelInitializer |
59 | 0 | self._scheduledTimeout = nil |
60 | 0 | } |
61 | | |
62 | | /// Schedule a timeout for this waiter. This task will be cancelled when the waiter is |
63 | | /// succeeded or failed. |
64 | | /// |
65 | | /// - Parameters: |
66 | | /// - eventLoop: The `EventLoop` to run the timeout task on. |
67 | | /// - body: The closure to execute when the timeout is fired. |
68 | | @usableFromInline |
69 | | internal func scheduleTimeout( |
70 | | on eventLoop: EventLoop, |
71 | | execute body: @escaping () -> Void |
72 | 0 | ) { |
73 | 0 | assert(self._scheduledTimeout == nil) |
74 | 0 | self._scheduledTimeout = eventLoop.scheduleTask(deadline: self._deadline, body) |
75 | 0 | } |
76 | | |
77 | | /// Returns a boolean value indicating whether the deadline for this waiter occurs after the |
78 | | /// given deadline. |
79 | | @usableFromInline |
80 | 0 | internal func deadlineIsAfter(_ other: NIODeadline) -> Bool { |
81 | 0 | return self._deadline > other |
82 | 0 | } |
83 | | |
84 | | /// Succeed the waiter with the given multiplexer. |
85 | | @usableFromInline |
86 | 0 | internal func succeed(with multiplexer: HTTP2StreamMultiplexer) { |
87 | 0 | self._scheduledTimeout?.cancel() |
88 | 0 | self._scheduledTimeout = nil |
89 | 0 | multiplexer.createStreamChannel(promise: self._promise, self._channelInitializer) |
90 | 0 | } |
91 | | |
92 | | /// Fail the waiter with `error`. |
93 | | @usableFromInline |
94 | 0 | internal func fail(_ error: Error) { |
95 | 0 | self._scheduledTimeout?.cancel() |
96 | 0 | self._scheduledTimeout = nil |
97 | 0 | self._promise.fail(error) |
98 | 0 | } |
99 | | |
100 | | /// The ID of a waiter. |
101 | | @usableFromInline |
102 | | internal struct ID: Hashable, CustomStringConvertible { |
103 | | @usableFromInline |
104 | | internal let _id: ObjectIdentifier |
105 | | |
106 | | @usableFromInline |
107 | 0 | internal init(_ waiter: Waiter) { |
108 | 0 | self._id = ObjectIdentifier(waiter) |
109 | 0 | } |
110 | | |
111 | | @usableFromInline |
112 | 0 | internal var description: String { |
113 | 0 | return String(describing: self._id) |
114 | 0 | } |
115 | | } |
116 | | } |
117 | | } |