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 systemd service #23

Merged
merged 1 commit into from
Jul 19, 2024
Merged

Add systemd service #23

merged 1 commit into from
Jul 19, 2024

Conversation

wojnilowicz
Copy link
Contributor

No description provided.

@2e3s
Copy link
Owner

2e3s commented Jun 11, 2024

Thank you for your suggestion, doesn't ActivityWatch manage the modules and run the modules itself? I have added a similar functionality myself to the bundled version which works almost identically to the original distribution of ActivityWatch (particularly, Qt-based tray icon app).

Or is it about the delays? If some environment requires a timeout, I think it may be considered in the code to facilitate the usage for everyone, for example, I added delays and more attempts for #8 and #11

@wojnilowicz
Copy link
Contributor Author

You're welcome. Indeed, this is a suggestion. I use it.

ActivityWatch manages its modules, if you run them through aw-qt. It also has a systemd service at https://github.com/ActivityWatch/aw-server-rust/blob/82345cfc5371c673a9bc2b5284530ae8c180153d/aw-server.service that lets you start aw-server, but then its modules don't start.
This MR is for aw-awatcher to start just like aw-server. No need to start aw-qt.

The issue with delay is so that if aw-server doesn't initialize fully then aw-awatcher goes dead, but systemd doesn't know that. If you can fix that somehow (either by failing aw-awatcher or idling for aw-server) then it would be even a better solution.

BTW, I believe the issues you pointed doesn't help me. I don't use bundled version and I use you latest watcher and still have to be careful when to start your watcher.

@2e3s
Copy link
Owner

2e3s commented Jun 11, 2024

The issue with delay is so that if aw-server doesn't initialize fully then aw-awatcher goes dead, but systemd doesn't know that.

There are 3 reconnection attempts with 1 second interval, doesn't this work for you? Maybe, 3 attempts/2 seconds waiting is not enough?
It has After=aw-server.service, so I would expect it to work, especially after the delay.

either by failing aw-awatcher

Doesn't aw-awatcher fail the way which is recognized by systemd?

@wojnilowicz
Copy link
Contributor Author

wojnilowicz commented Jun 11, 2024

The issue with delay is so that if aw-server doesn't initialize fully then aw-awatcher goes dead, but systemd doesn't know that.

There are 3 reconnection attempts with 1 second interval, doesn't this work for you? Maybe, 3 attempts/2 seconds waiting is not enough?

Certainly not on my old machine. It's far too less. I also have a newer and quite fast machine, but I wouldn't bet that 3 times 1 s is enough for it 🙂

It has After=aw-server.service, so I would expect it to work, especially after the delay.

After=aw-server.service is not helpful here as it only marks that the aw-server executable has been launched. I believe your awatcher expects to communicate with it to not fail, and for this aw-server needs a bit more time, hence the delay of 100 seconds. My newer machine can go way below these 100 seconds, so this solution is not perfect, so you could come up with something more robust if you want to invest time in it.

either by failing aw-awatcher

Doesn't aw-awatcher fail the way which is recognized by systemd?

I'm not an expert on this but replacing the delay with

Restart=on-failure
RestartSec=30

under the service tag doesn't help, so I concluded that it doesn't actually report failing. Maybe the return code is still zero.

@2e3s 2e3s mentioned this pull request Jun 11, 2024
@2e3s
Copy link
Owner

2e3s commented Jun 12, 2024

under the service tag doesn't help, so I concluded that it doesn't actually report failing. Maybe the return code is still zero.

Just checked, the return code is ok if you have this error:

Error: Failed to create bucket aw-watcher-afk_demi-desktop-linux

Caused by:
    0: error sending request for url (http://127.0.0.1:5600//api/0/buckets/aw-watcher-afk_demi-desktop-linux): error trying to connect: tcp connect error: Connection refused (os error 111)
    1: error trying to connect: tcp connect error: Connection refused (os error 111)
    2: tcp connect error: Connection refused (os error 111)
    3: Connection refused (os error 111)
$ echo $?
1

@wojnilowicz
Copy link
Contributor Author

Yes, maybe I should experiment a bit more with this. Thanks for the error codes listing. I'm surprised that an error code could be 0. Shouldn't that be reserved for "everything's ok"?

@2e3s
Copy link
Owner

2e3s commented Jun 12, 2024

I'm surprised that an error code could be 0. Shouldn't that be reserved for "everything's ok"?

I'm not sure I understand, the error code for awatcher is 1 when the aforementioned exception happens as echo $? shows in the snippet. Otherwise, 0 is returned on a regular exit, I've just checked.

@wojnilowicz
Copy link
Contributor Author

Ok, I did no try it yet, so maybe I don't quite understand what "0: error sending request for url [...]" means.

@luisgerhorst
Copy link
Contributor

Here's what I'm using:

[Unit]
Requires=aw-server.service
After=aw-server.service

[Service]
Type=simple
# Verbosity level: -v for warnings, -vv for info, -vvv for debug, -vvvv for trace
ExecStart=/bin/bash -c 'aw-awatcher --version && aw-awatcher -vvvv'
Restart=always
RestartSec=60
Nice=18
IOSchedulingPriority=6
# Was not able to test this on a system where it has an effect:
# CPUQuota=10%

[Install]
WantedBy=default.target

and

[Unit]
After=network.target

[Service]
Type=simple
ExecStart=/bin/bash -c 'aw-server'
Restart=on-failure
RestartSec=60
Nice=18
IOSchedulingPriority=6
# Was not able to test this on a system where it has an effect:
# CPUQuota=10%

[Install]
WantedBy=default.target

Not sure, but maybe setting Nice would be something to consider?

@wojnilowicz
Copy link
Contributor Author

Thanks for sharing, but I'm not sure "nice" is a robust solution here.

Now I'm just leaning more toward that this should be fixed on ActivityWatch side through something called forking as seen at
https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html
which will assure that aw-server is initialized fully before aw-aw_watcher starts.

Then here the systemd service could be minimal.

@wojnilowicz
Copy link
Contributor Author

I used sd-notify in aw-server-rust to inform systemd exactly when the server is up and running and only then start awatcher, but that didn't help during boot, so it's not about non-existent communication with aw-server-rust.

What I found is that without ExecStartPre=/bin/sleep 100 awatcher starts and immediately exits successfully. I suspect that in my case it's because kwin_x11 is not yet initialized. ExecStartPre=/bin/sleep 100 adds enough time for it to start. That's not robust, because the time it has to wait depends on the machine it runs.

The new version of the service should be robust on every system. It sleeps for 5 seconds after aw-server.service or graphical-session.target (that's where kwin_x11 starts) starts. If it will not find KDE or GNOME, it'll exit successfully, but will try to restart itself after 5 s then after 10 s and then after every 15 s and will finally give up after 2 minutes.

Could you accept that PR?

@2e3s 2e3s merged commit 810707c into 2e3s:main Jul 19, 2024
4 checks passed
@2e3s
Copy link
Owner

2e3s commented Jul 19, 2024

Thank you for your updated config. It looks more robust and shareable, but it requires aw-server.service too. I've merged it anyway (to another folder, "watcher" is a local crate), and mentioned it in readme.

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