Add new structured listen API#619
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #619 +/- ##
==========================================
+ Coverage 76.40% 76.53% +0.12%
==========================================
Files 134 134
Lines 10161 10170 +9
==========================================
+ Hits 7764 7784 +20
+ Misses 2397 2386 -11
🚀 New features to boost your workflow:
|
| let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1) | ||
| defer { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) } | ||
| let eventLoop = eventLoopGroup.next() |
There was a problem hiding this comment.
use singleton eventloop instead.
There was a problem hiding this comment.
Is this correct?
let eventLoopGroup = MultiThreadedEventLoopGroup.singleton
let eventLoop = eventLoopGroup.next()
fabianfett
left a comment
There was a problem hiding this comment.
This already looks really good. A few small issues, but this will be a major improvement over the status quo.
fabianfett
left a comment
There was a problem hiding this comment.
just had a look at the statemachine: I'm afraid this code might break us:
mutating func cancelListening(id: Int) -> CancelAction {
switch self.state {
case .initialized:
fatalError("Invalid state: \(self.state)")
can we add an integration test case:
@Test func leavingTheScopeSecondsAfterCancellationDoesNotCrash() async throws {
withThrowingTaskGroup { taskGroup in
taskGroup.addTask {
try await client.listen("Foo") {
do {
for try await not in $0 {
}
} catch {
try await Task {
try? await Task.sleep(.seconds(1))
}.result
}
// scope is left long after task is cancelled
}
}
// wait until listen has started by using an AsyncStream.
taskGroup.cancelAll()
}
}|
@fabianfett I added the test, it passes without throwing any |
|
@fpseverino I hear you that it doesn't crash in your test, however I remain sceptical that something else is wrong here: Especially given this code it SHOULD crash. This resets it to |
Using the new
|
|
The magic is here: mutating func stopListeningSucceeded(channel: String) -> StopListeningSuccessAction {
switch self.channels[channel]!.stopListeningSucceeded() {
case .none:
self.channels.removeValue(forKey: channel)
return .none
case .startListening:
return .startListening
}
} |
fabianfett
left a comment
There was a problem hiding this comment.
Thanks for pushing this through. Really great API change.
listen, inspired byvalkey-swift, passing theAsyncSequenceto a closure and sending theUNLISTENtask to the channel handler once the closure finishes executingUNLISTENquery directly, but given the current implementation of the channel handler andPostgresNotificationSequence, that ended up sending twoUNLISTENeach time (which is not a protocol error, but undesirable)listenmethod