Browse Source

ConnectionPool Waiter should store its timeout task

Motivation:

Connection pool waiters have a scheduled tasks for to timeout waiting.
This is cancelled and set to `nil` when the waiter is succeeded or
failed. Hoever, when scheduling a task the task was never stored! This
would lead to the potentially firing when the deadline expired although
the effect of this would be a no-op.

Modifications:

- Capture the waiters scheduled task
- Add a test

Result:

Cancelled tasks are actually cancelled.
George Barnett 3 years ago
parent
commit
742e8ec389

+ 1 - 1
Sources/GRPC/ConnectionPool/ConnectionPool+Waiter.swift

@@ -71,7 +71,7 @@ extension ConnectionPool {
       execute body: @escaping () -> Void
       execute body: @escaping () -> Void
     ) {
     ) {
       assert(self._scheduledTimeout == nil)
       assert(self._scheduledTimeout == nil)
-      eventLoop.scheduleTask(deadline: self._deadline, body)
+      self._scheduledTimeout = eventLoop.scheduleTask(deadline: self._deadline, body)
     }
     }
 
 
     /// Returns a boolean value indicating whether the deadline for this waiter occurs after the
     /// Returns a boolean value indicating whether the deadline for this waiter occurs after the

+ 19 - 0
Tests/GRPCTests/ConnectionPool/ConnectionPoolTests.swift

@@ -846,6 +846,25 @@ final class ConnectionPoolTests: GRPCTestCase {
       }
       }
     }
     }
   }
   }
+
+  func testWaiterStoresItsScheduledTask() throws {
+    let deadline = NIODeadline.uptimeNanoseconds(42)
+    let promise = self.eventLoop.makePromise(of: Channel.self)
+    let waiter = ConnectionPool.Waiter(deadline: deadline, promise: promise) {
+      return $0.eventLoop.makeSucceededVoidFuture()
+    }
+
+    XCTAssertNil(waiter._scheduledTimeout)
+
+    waiter.scheduleTimeout(on: self.eventLoop) {
+      waiter.fail(ConnectionPoolError.deadlineExceeded(connectionError: nil))
+    }
+
+    XCTAssertNotNil(waiter._scheduledTimeout)
+    self.eventLoop.advanceTime(to: deadline)
+    XCTAssertThrowsError(try promise.futureResult.wait())
+    XCTAssertNil(waiter._scheduledTimeout)
+  }
 }
 }
 
 
 extension ConnectionPool {
 extension ConnectionPool {