-
-
Notifications
You must be signed in to change notification settings - Fork 82
Add support for receiving and dispatching NotificationResponse messages #60
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we could achieve this using PostgresRequestHandler
without changing the pipeline at all. The key would be to not use simpleQuery
since that is designed for a request / response pattern.
Instead, we could have separate PostgresConnection.listen
/ notify
methods.
conn.listen(channel: "foo") { message, context in
print(message) // the notify message
print(context) // context for the current listen
context.stop() // context can be used to stop listening
}
conn.notify(channel: "foo", message: "bar")
These could be handled by a custom PostgresRequest
conformer.
Re: failing CI, see #60 for fix. You may need to merge this into your fork.
That does look like a nicer API. If it turns into a |
Hmm... that's a good point. Maybe LISTEN / NOTIFY could bypass |
For example, this is how |
Thanks for the feedback. I've rebased onto the fixed master branch for the CI fixes from #62, switched to a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that generating SQL seems out of scope for this project, that's a good point. Though if this method isn't actually going to generate the LISTEN
query maybe something like conn.addListener
would be a better name.
Besides that, I just have some small nits and ideas for simplification. Overall, really nice work on this, thank you!
let listenContext = PostgresListenContext() | ||
let channelHandler = PostgresNotificationHandler(channel: channel, notificationHandler: notificationHandler, listenContext: listenContext) | ||
let pipeline = self.channel.pipeline | ||
_ = pipeline.addHandler(channelHandler, name: nil, position: .before(requestHandler)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since PostgresRequestHandler
is ignoring .notificationResponse
now, I think you should be able to simply append the PostgresNotificationHandler
. That would make thing simpler not needing to pass around requestHandler
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Please use self.
whenever you access a property (pretend you're in an escaping closure all the time).
typealias InboundOut = PostgresMessage | ||
|
||
let channel: String | ||
let notificationHandler: (PostgresMessage.NotificationResponse, PostgresListenContext) -> Void |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NIO methods tend to pass context
first. It might be nice to follow that pattern here.
notificationHandler(notification, listenContext) | ||
} | ||
} catch let error { | ||
errorCaught(context: context, error: error) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
errorCaught
will put the error on the pipeline and eventually close the connection. I'm not sure that's what we want here. It might be better to just log the error to the connection's logger.
@@ -0,0 +1,56 @@ | |||
import NIO | |||
|
|||
public final class PostgresListenContext { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Anything public
should have docblocks.
Thanks for the additional feedback. I believe I've addressed all your comments. Please take another look. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great, thank you!
Are there any code examples of using this ? |
It has been a very long time since I have touched this code, but the added tests do show how this can be used. These tests remain present in the current version of the code: postgres-nio/Tests/IntegrationTests/PostgresNIOTests.swift Lines 111 to 230 in 9f84290
Hopefully this helps. I am not likely to be of much further use due to the length of time it has been since I worked on this, and I no longer work on anything that uses this. |
This is an initial stab at trying to fix #28. PostgresNIO already has sufficient support for sending
LISTEN
andNOTIFY
commands, through e.g.simpleQuery
, but lacks support for handling theNotificationResponse
messages that result when a notification comes through. This PR adds support for handlingNotificationResponse
messages by adding an additional channel handler beforePostgresRequestHandler
, that filters outNotificationResponse
messages (sincePostgresRequest
s are usually ill-prepared to handle them) and diverts them to handlers registered by channel in aPostgresNotificationHandlerMap
that can be accessed onPostgresConnection
. I'm not tied to the current API exposed here; I could imagine a couple different alternatives, but this seemed like the simplest thing that could possibly work and looks reasonably ergonomic to use.