Coverage Report

Created: 2026-02-14 07:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}