Catfriend1 / syncthing-android

Syncthing-Fork - A Syncthing Wrapper for Android.
Mozilla Public License 2.0
1.21k stars 40 forks source link

Run condition on folder change #876

Open mhofman opened 2 years ago

mhofman commented 2 years ago

Description of the issue

I understand that SyncthingNative is capable of doing a watch through inotify on shared folders, but that requires the engine to be running, which keeps the network connections going.

I've read the wiki's Info on battery optimization, and it seems the recommended path is to enable the"Sync every hour for 5 minutes" option.

What I'd like is for the Android wrapper to watch itself for changes to the folder shared (since it seems to keep a copy of that info outside the engine), start SyncthingNative after those changes have been detected (probably with a hysteresis similar to the engine), and shutdown after the sync has completed (engine idle for x minutes).

I'm usually interested to fully sync the changes, so the 5 minutes hard limit is kinda strange, like https://github.com/Catfriend1/syncthing-android/issues/419#issuecomment-501676574 mentions as well. We could keep a "run for max y minutes" option for people that want to enforce some limit, maybe coupled to a "only if on battery", or "only if on cellular" toggle?

Version Information

ds84182 commented 2 months ago

It's probably easier to add a feature & api to syncthing to suspend/resume network connections. Then keep syncthing running, and use LocalChangeDetected events to schedule/reschedule the job on file changes.

The app has to switch to using a job with requirements set based on run conditions. e.g. setRequiredNetworkType ensures the system brings up the required network interfaces, etc. And scheduled jobs are always run when their requirements are next met. e.g. You've set run conditions to sync camera photos when you arrive home; it'll sync on arrival instead of waiting an hour.

Hell, on API level 29 you can even add a requirement to run on a specific wifi network. It's perfect :)

And the job scheduling behavior would be rather straightforward: When there are no local changes, schedule it as a persistent periodic job. When a local change is detected, trigger it by rescheduling it without the periodic interval, if it isn't already rescheduled or currently running. When the job finishes it can reschedule as a periodic job.

The periodic job may not need an interval assigned to it. Android would run it when its most convenient. Like when the device is unlocked. The minimum latency could be optional or user-specified.

On API level 33 there are new job priorities, and API level 34 has immediately run/user initiated jobs. These would depend on the scheduling reason. A local change is user initiated, a periodic update can wait.

Honestly this might all be possible without adding a network disable feature to syncthing. Android should handle it correctly by bringing down the network when appropriate. But adding it may prevent unneeded background CPU usage from connection retries.

May tinker with this soon. It would pair nicely with Super Productivity.

ds84182 commented 1 month ago

Ok an update: Syncthing already does this if you turn off the 5 minute run condition, turn off port binding, and (possibly) turn off running on mobile data.

In my tests syncthing doesn't use ANY battery when my phone is connected to WiFi. Syncing is instant when I add or change files.

Port binding requests a wakelock/persistent network request from NetworkManager. I don't know if this is much of an issue on WiFi, but on mobile data the modem never turns off in your pocket leading to EXTREME battery drain.

Dunno if there should be a separate mobile data-only version of the "run for 5 minutes" option.