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

add backend-agnostic connection check #135

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

guillomovitch
Copy link

Summary

Each minion class backend uses a different attribute for its database connection object ('pg' for postgres backend, 'mysql' for mysql backend, etc). This makes low-level operations implementation-dependant.

Motivation

The change allows to send regular traffic to the backend, in order to avoid the database connection being closed for timeout, in a backend-agnostic way.

References

See discussion #2229.

This is useful for avoiding database connection getting idle.
@kraih
Copy link
Member

kraih commented Feb 1, 2025

I don't like that this requires changes in every single backend. Based on that fact i'm voting 👎 .

@jberger
Copy link
Member

jberger commented Feb 1, 2025

Could it also implement can_ping with a default implementation of return 0? Then backends can choose to implement or not. Or heck the default implementation of ping could just assume the worst case which is no different than now.

@kraih
Copy link
Member

kraih commented Feb 2, 2025

The whole idea of having a ping method in a job queue API seems wrong to me.

@kraih
Copy link
Member

kraih commented Feb 2, 2025

And it's not like ping is a huge sophisticated feature folks will get a lot of value out of. It's just a wrapper for a SELECT 1 query.

@guillomovitch
Copy link
Author

The default minion setup, at least when used with minion plugin, is to establish a single persistent network connection with the backend, as long a the application is running. Ensuring this connection stays functional is mandatory when intermediate network equipments automatically cut off idle connections. So, the actual need is just to make easier to implement a keepalive mechanism to match this strategy.

Actually, small differences between backends (each one use a different property to store its database object) require the application to handle each backend differently, ie:

Mojo::IOLoop->recurring($delay => sub ($loop) {
    my $backend = $app->minion->backend;
    my $class = ref($backend);
    if ($class eq 'Minion::Backend::mysql') {
        $backend->mysql->db->ping;
    } elseif ($class eq 'Minion::Backend::Pg') {
        $backend->pg->db->ping;
    } else {
        ....
    }
});

With this small abstraction layer added to minion, this would turn to:

Mojo::IOLoop->recurring($delay => sub ($loop) {
    $app->minion->backend->ping;
});

This keepalive mechanism would also be a useful addition to Minion::Backend, but still requires this first part.

@jberger I may indeed add a can_ping method, but wouldn't just removing the stub implementation in Minion::Backend achieve the same result, using Universal::can, ie:

use Universal::can;
if ($backend->can('ping')) {
  // has backend-agnostic way of sending keepalive packets
} else {
  // has backend-specific way of sending keepalive packets
}

@kraih
Copy link
Member

kraih commented Feb 2, 2025

I get what you want to ultimately achieve, but the implementation makes no sense in a job queue API. Just look at the method description Check backend connection.. Ok, so it checks the connection... but then what? Why would i ever want to check if the connection is active? What do i as a user do if it isn't? It just doesn't make sense there.

@guillomovitch
Copy link
Author

I just re-used the name and description of ping method in Mojo::Pg::Database. I can change the description to something as:
"send unspecified trafic to the backend, to avoid the connexion turning idle", but that would just be describing one usage, even if probably the only one.

Alternatives solutions:

  • instead of proving a shortcut to one specific method of the backend database object, provide a more generic db one, to expose this object for whatever usage
  • do not expose this ping method (just renaming it to _ping, and not documenting it, for instance), but implement a keepalive($delay) method in Minion::Backend class that would rely on this private method to achieve the intended result

The first solution is basically making desencapsulation easier, the second one seems a better idea, but I'm unconfortable with the idea of private methods implemented in a child class, and used from a parent class.

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

Successfully merging this pull request may close these issues.

3 participants