Currently, it seems impossible to reliably schedule multiple Farm Events at the same time and expect all of them to execute. This seems counter to the vision of FarmBot, which is primarily making growing your own food using automation accessible to everyone.
Regimens are designed to specify how the FarmBot cares for a particular plant type. Regimens don’t care if it’s winter or summer, they care about what “Day 1” and “Day 12” etc. look like for a given plant type.
Imagine you are preparing your FarmBot to handle many different types of plants, some of which you’ll plant during winter, some you’ll plant in spring, and some in summer. Some plants you might grow all year 'round, or repeatedly every season.
You’d make a Regimen for that plant type and specify day-to-day how to grow that plant from a seed to harvest. And you’d do this for (say for the sake of this example) 25 plant types, 25 Regimens.
In the current Farm Event scheduling mechanism, you’d have to manually ensure that the start times of your sequences inside each Regimen do not conflict with the start times of sequences inside other Regimens. That is, in my opinion, an unreasonable expectation. I would like to propose a conceptual solution that I believe would be possible with FarmBot, although potentially requiring some significant refactoring of the existing scheduling logic.
The Queue
The Queue is a list of tasks that is kept separately of all other current scheduling mechanisms. It becomes the primary source for FarmBot to periodically check if it needs to perform a task. Tasks are added by Farm Events and by the user requesting to run sequences ad hoc. The Queue does NOT have a concept of time, it simply exists to hold tasks and its goal is to be empty.
Benefits
- Currently, when FarmBot is executing a task, it’s not possible to instruct it to run a sequence without interrupting the current task. With the Queue, clicking Run on a sequence would essentially queue the sequence as the immediate next task, regardless of how many tasks are currently already in the Queue. This allows you to inject ad-hoc tasks into a big list of tasks without having to cancel and restart all those other tasks.
- Currently, scheduling Regimens with Farm Events that have sequences begin at the same start time means that only the first couple of operations will succeed. All other remaining tasks from that start time will simply disappear without being executed. With a Queue, all Farm Events will simply add all their tasks to the Queue when the Farm Event fires. The Queue then takes care of the sequential processing of these tasks, even if it takes 4 hours to reach the last added task.
Some constraints
- The Queue must work on a First In First Out principle. The only way to “jump the queue” is when a user clicks Run on a sequence. This will insert the sequence directly after the currently executing sequence, if there is one.
- Farm Events firing at the same time must add their list of tasks contiguously, meaning that tasks from one Farm Event may not blend into the sequential list of tasks from another Farm Event; each Farm Event is contiguous. The reason for this is because some sequences rely on other sequences to have executed, like mounting a watering nozzle before watering.
- FarmBot is a machine and does not care how long it takes to perform its tasks. But to manage user expectations, a periodic health check must be performed. This health check is simply verifying that the Queue was empty at least once in the last 24 hours. If it was NOT empty in the last 24 hours, it means FarmBot has too many tasks scheduled that cannot be completed in a full day. The health check could be performed as often as every minute, at the same time it checks if there are tasks in the Queue that should be picked up.