client-call-bidistreaming.swift 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. /// {{ method|methodDescriptorName }} (Bidirectional Streaming)
  2. {{ access }} protocol {{ .|call:file,service,method }} {
  3. /// Call this to wait for a result. Blocking.
  4. func receive() throws -> {{ method|output }}
  5. /// Call this to wait for a result. Nonblocking.
  6. func receive(completion:@escaping ({{ method|output }}?, {{ .|clienterror:file,service }}?)->()) throws
  7. /// Call this to send each message in the request stream.
  8. func send(_ message:{{ method|input }}, errorHandler:@escaping (Error)->()) throws
  9. /// Call this to close the sending connection. Blocking.
  10. func closeSend() throws
  11. /// Call this to close the sending connection. Nonblocking.
  12. func closeSend(completion: (()->())?) throws
  13. /// Cancel the call.
  14. func cancel()
  15. }
  16. {{ access }} extension {{ .|call:file,service,method }} {
  17. func receive() throws -> {{ method|output }} {
  18. var returnError : {{ .|clienterror:file,service }}?
  19. var returnMessage : {{ method|output }}!
  20. let sem = DispatchSemaphore(value: 0)
  21. do {
  22. try receive() {response, error in
  23. returnMessage = response
  24. returnError = error
  25. sem.signal()
  26. }
  27. _ = sem.wait(timeout: DispatchTime.distantFuture)
  28. }
  29. if let returnError = returnError {
  30. throw returnError
  31. }
  32. return returnMessage
  33. }
  34. func closeSend() throws {
  35. let sem = DispatchSemaphore(value: 0)
  36. try closeSend() {
  37. sem.signal()
  38. }
  39. _ = sem.wait(timeout: DispatchTime.distantFuture)
  40. }
  41. }
  42. fileprivate final class {{ .|call:file,service,method }}Impl: {{ .|call:file,service,method }} {
  43. private var call : Call
  44. /// Create a call.
  45. init(_ channel: Channel) {
  46. self.call = channel.makeCall("{{ .|path:file,service,method }}")
  47. }
  48. /// Call this to start a call. Nonblocking.
  49. func start(metadata:Metadata, completion: ((CallResult)->())?)
  50. throws -> {{ .|call:file,service,method }} {
  51. try self.call.start(.bidiStreaming, metadata:metadata, completion:completion)
  52. return self
  53. }
  54. func receive(completion:@escaping ({{ method|output }}?, {{ .|clienterror:file,service }}?)->()) throws {
  55. do {
  56. try call.receiveMessage() {(data) in
  57. if let data = data {
  58. if let returnMessage = try? {{ method|output }}(serializedData:data) {
  59. completion(returnMessage, nil)
  60. } else {
  61. completion(nil, {{ .|clienterror:file,service }}.invalidMessageReceived)
  62. }
  63. } else {
  64. completion(nil, {{ .|clienterror:file,service }}.endOfStream)
  65. }
  66. }
  67. }
  68. }
  69. func send(_ message:{{ method|input }}, errorHandler:@escaping (Error)->()) throws {
  70. let messageData = try message.serializedData()
  71. try call.sendMessage(data:messageData, errorHandler:errorHandler)
  72. }
  73. func closeSend(completion: (()->())?) throws {
  74. try call.close(completion: completion)
  75. }
  76. func cancel() {
  77. call.cancel()
  78. }
  79. }
  80. //-{% if generateTestStubs %}
  81. /// Simple fake implementation of {{ .|call:file,service,method }} that returns a previously-defined set of results
  82. /// and stores sent values for later verification.
  83. class {{ .|call:file,service,method }}TestStub: {{ .|call:file,service,method }} {
  84. var inputs: [{{ method|input }}] = []
  85. var outputs: [{{ method|output }}] = []
  86. func receive(completion:@escaping ({{ method|output }}?, {{ .|clienterror:file,service }}?)->()) throws {
  87. if let output = outputs.first {
  88. outputs.removeFirst()
  89. completion(output, nil)
  90. } else {
  91. completion(nil, {{ .|clienterror:file,service }}.endOfStream)
  92. }
  93. }
  94. func send(_ message:{{ method|input }}, errorHandler:@escaping (Error)->()) throws {
  95. inputs.append(message)
  96. }
  97. func closeSend(completion: (()->())?) throws { completion?() }
  98. func cancel() { }
  99. }
  100. //-{% endif %}