ClientTransport.swift 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. /*
  2. * Copyright 2023, 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. /// A type that provides a long-lived bidirectional communication channel to a server.
  17. ///
  18. /// The client transport is responsible for providing streams to a backend on top of which an
  19. /// RPC can be executed. A typical transport implementation will establish and maintain connections
  20. /// to a server (or servers) and manage these over time, potentially closing idle connections and
  21. /// creating new ones on demand. As such transports can be expensive to create and as such are
  22. /// intended to be used as long-lived objects which exist for the lifetime of your application.
  23. ///
  24. /// gRPC provides an in-process transport in the `GRPCInProcessTransport` module and HTTP/2
  25. /// transport built on top of SwiftNIO in the https://github.com/grpc/grpc-swift-nio-transport
  26. /// package.
  27. @available(gRPCSwift 2.0, *)
  28. public protocol ClientTransport<Bytes>: Sendable {
  29. /// The bag-of-bytes type used by the transport.
  30. associatedtype Bytes: GRPCContiguousBytes & Sendable
  31. typealias Inbound = RPCAsyncSequence<RPCResponsePart<Bytes>, any Error>
  32. typealias Outbound = RPCWriter<RPCRequestPart<Bytes>>.Closable
  33. /// Returns a throttle which gRPC uses to determine whether retries can be executed.
  34. ///
  35. /// Client transports don't need to implement the throttle or interact with it beyond its
  36. /// creation. gRPC will record the results of requests to determine whether retries can be
  37. /// performed.
  38. var retryThrottle: RetryThrottle? { get }
  39. /// Establish and maintain a connection to the remote destination.
  40. ///
  41. /// Maintains a long-lived connection, or set of connections, to a remote destination.
  42. /// Connections may be added or removed over time as required by the implementation and the
  43. /// demand for streams by the client.
  44. ///
  45. /// Implementations of this function will typically create a long-lived task group which
  46. /// maintains connections. The function exits when all open streams have been closed and new connections
  47. /// are no longer required by the caller who signals this by calling ``beginGracefulShutdown()``, or by cancelling the
  48. /// task this function runs in.
  49. func connect() async throws
  50. /// Signal to the transport that no new streams may be created.
  51. ///
  52. /// Existing streams may run to completion naturally but calling
  53. /// ``ClientTransport/withStream(descriptor:options:_:)`` should result in an ``RPCError`` with
  54. /// code ``RPCError/Code/failedPrecondition`` being thrown.
  55. ///
  56. /// If you want to forcefully cancel all active streams then cancel the task
  57. /// running ``connect()``.
  58. func beginGracefulShutdown()
  59. /// Opens a stream using the transport, and uses it as input into a user-provided closure alongisde the given context.
  60. ///
  61. /// - Important: The opened stream is closed after the closure is finished.
  62. ///
  63. /// Transport implementations should throw an ``RPCError`` with the following error codes:
  64. /// - ``RPCError/Code/failedPrecondition`` if the transport is closing or has been closed.
  65. /// - ``RPCError/Code/unavailable`` if it's temporarily not possible to create a stream and it
  66. /// may be possible after some backoff period.
  67. ///
  68. /// - Parameters:
  69. /// - descriptor: A description of the method to open a stream for.
  70. /// - options: Options specific to the stream.
  71. /// - closure: A closure that takes the opened stream and the client context as its parameters.
  72. /// - Returns: Whatever value was returned from `closure`.
  73. func withStream<T: Sendable>(
  74. descriptor: MethodDescriptor,
  75. options: CallOptions,
  76. _ closure: (_ stream: RPCStream<Inbound, Outbound>, _ context: ClientContext) async throws -> T
  77. ) async throws -> T
  78. /// Returns the configuration for a given method.
  79. ///
  80. /// - Parameter descriptor: The method to lookup configuration for.
  81. /// - Returns: Configuration for the method, if it exists.
  82. func config(forMethod descriptor: MethodDescriptor) -> MethodConfig?
  83. }