Scheduling Times

Could you please consider adding an option to control the days and times when a folder will sync, or not sync? I would like to force certain folders to sync off hours. I’ve tried a very large rescan interval but that is not specific enough.

1 Like

It would be cool to have, but it’s probably not so easy to implement, as each folder would require separate controls for when to sync and when to stay paused.

For now you can use custom scripts paired with OS tools (e.g. Task Scheduler in Windows) to pause and unpause folders at specific times.

Possibly related: https://github.com/syncthing/syncthing/issues/6130.

I agree that such an option will probably not land in Syncthing itself. The API should be used to pause or unpause folders at specific times, which is not hard to do via Task Scheduler (Windows) or a cron job (Linux).

Or even Syncthing itself. To pause a folder:

syncthing cli config folders {the-folder-ID} paused set true
1 Like

I was just about to add that command line to my post :slight_smile:

2 Likes

I took some time to check what the API really offers, and in fact we have /rest/system/pause and /rest/system/resume, but they work only for devices, not folders. Any reason for that? Now with the granular config manipulation API it’s no longer of importance, but since we already have that endpoint, shouldn’t it support pausing folders as well?

Or be deprecated altogether? I think the main advantage it gives is easily (un)pausing all remote devices at once, which would be ambiguous for folders – should it pause all folders or all devices if none is specified?

You might enjoy the API discussion in the original PR.

2 Likes

Interesting read indeed. Somewhere in there you @calmh proposed to extend the API to folders instead of deprecating it, yet it didn’t happen in the end. Now with the granular config API in place, what’s your new stance on the old endpoints?

For my part, I think the API should expose things semantically. Whether a paused state is stored in the config does not matter, what the user wants is to manipulate the paused state. Something like /rest/folder/xxxx-yyyy/paused sounds like the way to go then, keeping the existing events in addition. I don’t think exposing the information in aggregated form somewhere else to bootstrap the GUI state is harmful in any way either.

If there’s an actual need, having endpoints for operations without having to know and modify the config makes sense. However I think we should then take a step back and think about how that api should look like, not just add new endpoints one-by-one ending up with a new bunch of endpoints without consistency. When it comes to already existing endpoints, making them work in a more sensible way on a case-by-case bases seems reasonable, as they already exist.

I agree that if we want to touch this, the end result should be thought about as a more complete picture, not just single items. A good starting point to decide whether an “action” endpoint is needed in addition to the generic config patching, could be whether a button in the GUI is appropriate / present.

Some thoughts about requirements for a consistent API experience here:

  1. Ideally one call should be able to manipulate several similar things for efficiency. But in this case I guess having all or only one is sufficient?
  2. We need to distinguish between (un)pausing folders and devices.
  3. We need to distinguish between pausing and unpausing / resuming.
  4. The endpoint naming should be concise and RESTful-ish.

The current solution /rest/system/pause[?device=...] and /rest/system/resume[?device=...] is sufficient on points 1 and 3. It fails on 2 (only devices) and 4 (IDs are not entities, /system/ is arbitrary). I don’t see a clear way to fix those, as an optional ?folder=... parameter would not address 4 and still cannot act on all folders.

To properly address points 2 and 4, the existing /rest/folder/... hierarchy could be used, extended by /rest/device/.... Bulk manipulation of all entities could be handled via sub-path, e.g.

/rest/folder/paused => `true` or `false`
/rest/folder/.../paused => `true` or `false`
/rest/device/paused => `true` or `false`
/rest/device/.../paused => `true` or `false`

Each would transfer a JSON value (boolean, not string) in both GET and POST requests. Which is better on point 4 (RESTfulness, “paused-state” being the “entity”), but a bit worse on point 3 (pause vs. resume). I’d prefer it for consistency though.

Is that a direction we’d want to move into for the API in general? If so, this would be a small first step, marking the old endpoints deprecated in exchange. Ideally we’ll already have the replacements available for some time at the eventual point of removing deprecated stuff.

1 Like

I wasn’t talking about a complete picture of pausing, I was talking about a higher lever “what should the API do (or not)”, and how should it be structured in general.

Why must/should there be a 1-to-1 relationship of API to UI elements?
There’s been some discussion on non-trivial information related to Syncthing state that is currently computed/tracked in the UI. Moving that into the API makes sense to me. However in my view UI elements are an entirely different concern from the API, and there should be less coupling not more. Currently a lot of API endpoints were created becaues of the web UI, as it’s the main user, but I view that as a downside.

1 Like

So was I, but I don’t think we are at a point in development where a complete API redesign is in order. Rather I’d like to sketch out a picture of what principles should be adhered to, then work toward that goal on every occasion where someone has trouble with the current inconsistencies.

I said “a good starting point”, not a definitive mapping. But if we think it’s worth for a GUI user to have a one-click action available to {pause | resume} {single | all} {folders | devices}, that is an indication that the same actions might make sense for other API users. In this specific case I think they do, as also indicated by the OP’s request. Another data point as to why the current state is undesirable: gui: Ignore own device when pausing/resuming all devices (ref #7359) by tomasz1986 · Pull Request #7366 · syncthing/syncthing · GitHub

1 Like

To me this feels like a typical case where the API would be better off taking something like a list of folder IDs to pause. That one method then becomes pause-one, pause-many or pause-all depending on what the caller does.

I considered that as well. But as far as I could tell it would not be very RESTy, but more along an RPC design pattern. And how would you encode “all” then?

I would send the list of all folders. I’m an API consumer, not a human, so I can build that list.

As an array? And then keep the pause and resume endpoints separate? That couldn’t well be mirrored to the GET side though, or do you mean:

{
  "paused": [ "aaa", "bbb", ... ],
  "active": [ "xxx", "yyy", ... ]
}

Look, I’m just trying to understand what guidelines for a future, less messy API could be. But I keep getting contradicting hints, or I’m misunderstanding the concept of well-designed REST paths / resource naming. Isn’t that the direction we’re trying to go?

Maybe? Maybe an rpc style would be better. I don’t know. I think if someone is doing a rethink it requires a larger proposal discussion, iterations, pros and cons, prior art, etc. It can get arbitrarily complicated.

There’s an established pattern of how thinks work currently. If we’re going to change that it should be a very considered decision.

There is an established pattern of inconsistently following different patterns as the API has grown into what it is. So much I could gather from trying to find ways and places to extend the API with new functions, and I think most of us agree on the inconsistency part.

My experience with REST in particular is too limited to propose a complete big picture. But calling it a REST API and prefixing with /rest/ creates some expectations as recently witnessed. So for any future additions or for making smaller fixes (like what would be in order for this topic), we should have some direction to follow. If the big picture redesign ever happens and it turns out REST won’t be that paradigm, there will be more rework to do, but it will be at a time when breaking changes are expected.

My main concern is really to fix usability issues with small changes, extensions and documentation. I have no strong opinion on which API style it shall be. But I want to follow something consistently.