Skip to content
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

Support for the LISTEN / NOTIFY functionality? #231

Open
jonesmz opened this issue Feb 20, 2020 · 2 comments
Open

Support for the LISTEN / NOTIFY functionality? #231

jonesmz opened this issue Feb 20, 2020 · 2 comments
Assignees
Labels
feature feature request

Comments

@jonesmz
Copy link
Contributor

jonesmz commented Feb 20, 2020

E.g.: https://www.postgresql.org/docs/11/sql-listen.html

@thed636
Copy link
Contributor

thed636 commented Mar 2, 2020

Hi Michael!

Yep, what do you think about such an interface?

class notification {
public:
    /* notification channel name */
    std::string_view relname() const noexcept;
    /* process ID of notifying server process */
    int backend_pid() const noexcept;
    /* notification payload string */
    std::string_view extra() const noexcept;
    /* true if has notification */
    operator bool () const noexcept; 
    bool operator!() const noexcept;
private:
    std::shared_ptr<const ::PGnotify> v_; // to be easy copyable
};

template <typename Connection>
notification get_notification(Connection& conn);

template <typename Connection, typename CompletionToken>
auto wait_notification(Connection&& conn, CompletionToken continuation);

template <typename Connection, typename TimeConstraint, typename CompletionToken>
auto wait_notification(Connection&& conn, TimeConstraint t, CompletionToken continuation);

And usage like:

auto conn = ozo::request(..., yield);
// trying to get notification that may be received during the request operation
auto notification = ozo::get_notification(conn);

while(!notification) {
    // trying to wait for notification
    wait_notification(conn, yield);
    notification = ozo::get_notification(conn);
}

// handle notification
std::cout << notification.extra() << std::endl;

@thed636 thed636 self-assigned this Mar 2, 2020
@thed636 thed636 added the feature feature request label Mar 2, 2020
@jonesmz
Copy link
Contributor Author

jonesmz commented Mar 2, 2020

Comments or suggestions inline below.

class notification {
public:
    /* notification channel name */
    std::string_view channel_name() const noexcept;
    /* process ID of notifying server process */
    //// To be honest, it's not clear to me how this would be useful to the code consuming the notification.
    int backend_pid() const noexcept;
    /* notification payload string */
    //// What's the actual underlying storage for the channel_name and the payload
    //// For example, I have a reference counted string class that I use in most of my code
    //// and I'd probably want to provide some kind of binding that allows OZO to deserialize
    //// this data directly into my refcounted string type.
    std::string_view payload() const noexcept;

    /* true if has notification */
    //// I see why you add these, but personally, I'd rather use an interface that has an std::error_code to indicate whether the notification was successfully retrieved or not.
    //// But this doesn't hurt, obviously.
    operator bool () const noexcept; 
    bool operator!() const noexcept;
private:
    std::shared_ptr<const ::PGnotify> v_; // to be easy copyable
};

auto conn = ozo::request(..., yield);

// trying to get notification that may be received during the request operation
////////  My understanding of the notifications is that there does not need to be a request in flight
//////// for notifications to be sent. E.g. other connections to the database may cause notifications
//////// and as such, ozo would need a mechanism to keep a connection alive at all times to allow
//////// for an application to listen to notifications even when it is not sending requests on a regular
//////// basis.
//////// For example, my application queries the database for configuration information when a client
//////// device first connects, but then after that first connection, would only want to re-query for that
//////// device's configuration information if the database says that it changed. I don't want to be
//////// actively polling the database in order to determine if the config has changed, i just want to be
//////// notified that it has, and only then query for the changed data.
auto notification = ozo::get_notification(conn);

//////// Personally I'd rather have the wait_notification function return the notification (Based on the normal boost completion token patterns. With yield, as return value, with other types, as callback parameters.
//////// This would be similar to how ozo::request works, where the completion handler is called with
//////// the results of the request, and you don't need to call another function to get the actual results.
while(!notification) {
    // trying to wait for notification
    wait_notification(conn, yield);
    notification = ozo::get_notification(conn);
}

// handle notification
std::cout << notification.extra() << std::endl;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature feature request
Projects
None yet
Development

No branches or pull requests

2 participants