Postgres ebuilds currently ship a systemd service file that is installed versioned, meaning postgresql 9.5 installs postgresql-9.5.service.
This makes it hard for other services to properly depend on running postgres when the version doesn't matter.
I would for example like to depend on postgresql.service without needing to update other services on each postgres upgrade.
After short discussion in the #gentoo.de (german channel) it seems that the best solution would be to provide a postgresql.target, that is reached wenn any postgresql-X.Y.service is started, so other units can depend on that target.
Other solutions don't come to mind right now, but I'd be happy with any one that doesn't require me to mess with service files on postgres upgrades.
I'd be happy to provide patches if this solution is acceptable, and I hope I didn't miss any obvious existing solution.
I'm not yet sure what the best way to provide the target would be, maybe a systemd-generator could create it dynamically, since shipping a postgresql.target in multiple ebuilds won't work.
I don't find systemd intriguing enough to use and have zero experience with it. I do know this issue is not experienced with the standard initscripts.
I do welcome any contributions and encourage you to help me improve the experience with systemd.
As long as it doesn't depend on postgresql.eselect selecting the active service slot, I'm willing to consider it.
I agree it would be convenient.
The proposed use of a target is creative. I thought normally the target pulls up the service units? This target would be stopped if the service stopped?
It appears that the systemd way is a symlink
But that conflicts with the philosophy of eselect (bug 571390, comment 1).
Still you can do:
ln -sf /usr/lib64/systemd/system/postgresql-9.5.service /etc/systemd/system/postgresql.service
Which is hardly a lot of work. The downside being that because it is created manually it seems unlikely any ebuilds in the Portage tree are going to support it, leaving it for custom ebuilds or drop-ins.
Yes, that is exactly the issue.
I don't mind creating a symlink when I upgrade, my issue is really the dependency-problem, which is error-prone and invites missing things which then only might hit you on a reboot of the machine and thus can be disrupting.
If of course understand the desire not to have this in the eselect applet, especially since this couldn't cleanly fix the dependency issue.
I'm still not sure what the best way to solve this is, I'll continue to think about it and try to find a working and minimally invasive method.
It is true, that usually targets are used the other way around, but in this case it would be viable to only have the postgres service in the target, so other services can just depend on the target, which is a clean and reasonable way imho.
I've experimented a bit with it and I'm not yet 100% happy with the outcome, I'll provide patches to test when I've solved the issues.
Created attachment 427164 [details, diff]
add target requirement to service file
Created attachment 427166 [details]
Ok, here we go.
I played around with a number of solutions, but this one seamed to be the most reasonable and least problematic, if not quite perfect.
The idea is to provide a postgresql.target, which is reached as soon as all enabled postgresql servers are started.
Conversely the postgresql target will stop as soon as the first enabled postgresql server instance is stopped, which will also cause all other server instances (for example, 9.1, 9.2 and 9.3) to be stopped.
This is a side-effect that cannot reasonably be avoided, since it depends on user actions.
The simple solution for the dilemma is to just disable a 2nd postgresql service before stopping it, in which case it will not cause any issues.
If only one server is running, it works fine in all situations. If another server is started without being enabled, it also works, but will not stop the target in any case.
Long story short, with this solution any ebuild can depend on postgresql.target, either by hard dependency via Requires=postgresql.target, or soft dependency via Wants=postgresql.target.
Finally, for this to work, a postgresql.target file must be provided, which I attached. It will need to be installed in the systemd path in either lib/ or /etc and can only exist once.
The file is basically empty and does not contain any logic or dependencies, they are implied only via the service files themselves.
So to solve this issue I propose 3 possibilities:
1) Provide the target file via eselect-postgresql which is the cleanest solution without adding another ebuild.
2) Provide the target via postgresql ebuilds in pkg_post... with guards so it can't be removed when another postgresql version is still installed. Works, but not that pretty.
3) Ship a trivial systemd-generator script which creates the file when systemd starts, but will never remove it even if postgresql is uninstalled completely.
Let me know if this works for you, and feel free to contact me in case anything is still unclear.
Thanks to tamiko and Whissi in #gentoo.de and ohsix in #systemd.
Created attachment 427174 [details, diff]
add target requirement to service file
Sorry for the noise. Tamiko informed me, that the problem I mentioned can be avoided by using the Before= directive, instead of Requires=.
I tested this as well and it is indeed less problematic, even though the target will still go offline if any postgres instance does.
However, this will end all other running postgres services, so it is the better solution.
Although this is useful, I don't see how I can cleanly implement this in an automated way that would also make sense to users.
It would be better noted on the wiki at: