-
Notifications
You must be signed in to change notification settings - Fork 56
Automations - first roundtrip for forecasts #2290
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
Merged
Merged
Changes from all commits
Commits
Show all changes
79 commits
Select commit
Hold shift + click to select a range
f97c2f0
feat: add Automation data model
Flix6x f410437
feat: CLI commands to manage and run automations
Flix6x 6f6591c
feat: record on forecasting jobs how they were created
Flix6x fb74bfc
feat: API endpoints to list an asset's automations
Flix6x ab62b9f
feat: UI page listing an asset's automations
Flix6x db8f288
test: cover automations CLI, API and UI
Flix6x 9cb4f63
docs: document automations
Flix6x e0575c7
docs: changelog entry for automations
Flix6x b1f56bf
fix: render cron descriptions in 24-hour format regardless of locale
Flix6x de6fb71
fix: address code review findings for automations
Flix6x bf2cc60
fix: address code review findings for automations (remaining files)
Flix6x 7493c13
test: assert on the cron validation failure without pinning click's m…
Flix6x 7bc3056
merge: synchronize automations with current main
BelhsanHmida 15c9937
data/schemas: restrict automations to five-field cron
BelhsanHmida 3090cf5
data/schemas/tests: cover automation cron field count
BelhsanHmida 8cc3920
cli/jobs: retain automation guard after queueing failure
BelhsanHmida 29c46b3
cli/tests: cover partial automation queue failure
BelhsanHmida 8666c31
cli: normalize YAML forecasting option files
BelhsanHmida 3433020
cli/tests: cover automation YAML option files
BelhsanHmida 430dcef
data/services: redact inaccessible automation provenance
BelhsanHmida 6c4bbc6
api/v3_0/tests: cover automation provenance authorization
BelhsanHmida 337ad3b
ui/assets: distinguish automation load failures
BelhsanHmida 119fc9d
ui/tests: cover automation load error state
BelhsanHmida 04daae4
utils/docs: preserve standalone asterisks in RST conversion
BelhsanHmida 22addda
utils/tests: cover RST cron wildcard conversion
BelhsanHmida edf77a5
docs/forecasting: clarify automation execution contract
BelhsanHmida a6cee99
changelog: record automation API and runner contract
BelhsanHmida 194f8cc
api/docs: show job creation provenance
BelhsanHmida a3d7ebe
test: keep forecast CLI stub compatible with job provenance
BelhsanHmida de76798
Merge main into forecast automations
BelhsanHmida 646f9fd
fix: require valid automation generators
BelhsanHmida 4664afe
test: cover automation generator retention
BelhsanHmida b801d74
fix: constrain forecast automation outputs
BelhsanHmida 006f85c
test: cover forecast automation output scope
BelhsanHmida dba4edc
docs: explain forecast automation ownership rules
BelhsanHmida efdda5a
fix: merge automation and main migration heads
BelhsanHmida c783e8f
data/models: let data generators report their input and output sensors
Flix6x 8b2cc73
data/models/forecasting: only announce a pipeline run when actually r…
Flix6x b37256f
cli: default the automation recurrence to daily, and reject options t…
Flix6x aa64afb
api/v3_0: report an automation's input and output sensors
Flix6x b438e8f
api/v3_0: add an endpoint for one data source
Flix6x 17f432b
api/v3_0: regenerate the OpenAPI specs
Flix6x 1ea8f78
ui: link an automation's details to its sensors, and make the listing…
Flix6x 2b87d5e
ui: show a sensor's data source record and the automations feeding it
Flix6x 1869247
tests: cover the automation and data source review follow-ups
Flix6x 03626b4
docs: describe the automation and data source follow-ups
Flix6x 0f8fe58
Merge the current automations branch into the review follow-ups
Flix6x 1dccf9f
api/v3_0: regenerate the OpenAPI specs after merging
Flix6x 9f1d075
cli: only reject configuration options that were actually given with …
Flix6x b397907
data/services: only consider automations that could feed a sensor
Flix6x 318cd91
tests: follow the merged automation behaviour
Flix6x 1eb3a50
cli: keep mypy happy about click 8 attributes
BelhsanHmida 9653e10
cli: keep the automation help focused on the automation
BelhsanHmida 87e07f6
data/models: count a source-filtered regressor as an input sensor
BelhsanHmida 8860bd0
data/services: do not report no sensors when an automation's sensors …
BelhsanHmida 2b961cc
Feat automation timezones catchup (#2396)
BelhsanHmida f75bb6d
Merge branch 'main' into feat/2288-automations-for-forecasts
BelhsanHmida a98b4fc
Merge origin/main into automation fixes
BelhsanHmida 8eac59f
fix(data/schemas): reject cron expressions without dates
BelhsanHmida 249642f
fix(data/services): isolate invalid recurrences and stale claims
BelhsanHmida bf23428
fix(api/v3_0): protect automation sensor details
BelhsanHmida af5957b
test(cli): cover impossible recurrence input
BelhsanHmida c18f7de
test(data/services): cover resilient automation claims
BelhsanHmida 23ea45a
test(api/v3_0): cover private automation dependencies
BelhsanHmida 63fee6b
Merge branch 'main' into feat/2288-automations-for-forecasts
BelhsanHmida dd5fae6
data/models: name an automation's cursor after what it points at
Flix6x b3845d8
tests: follow the automation cursor rename
Flix6x dbf0bae
docs: explain the automation cursor, and say "run" instead of "occurr…
Flix6x 7e1bab2
docs/changelog: give the automation API changes their own version sec…
Flix6x d1cd0a2
docs/changelog: restore the v3.0-32 underline to full length
Flix6x 6474eec
data/services: address review findings on the automations service
Flix6x 1bda4b5
data/models: index the automation asset foreign key
Flix6x 8d8514d
api/v3_0: work out an automation's sensors once when they cannot be r…
Flix6x eca2520
cli: warn which automations a sensor deletion would break
Flix6x fc91bc4
tests: cover the sensor deletion warning, and stop depending on caplog
Flix6x 05e059e
docs/changelog: record the sensor deletion warning
Flix6x 6541676
Merge branch 'main' into feat/2288-automations-for-forecasts
Flix6x 4051dc2
docs: give automations their own page
Flix6x 06bf14b
data/migrations: index the automation asset FK without adding a revision
Flix6x File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| .. _automations: | ||
|
|
||
| Automations | ||
| ============ | ||
|
|
||
| An **automation** is a recurring task defined on an asset. | ||
| For now, an automation computes forecasts; automating schedules and reports is planned. | ||
|
|
||
| On each run, the automation queues jobs (so make sure a worker is processing the ``forecasting`` queue, see :ref:`redis-queue`). | ||
| The parameters of the task were stored when the automation was created, and validated with the same schema that the CLI and API use. | ||
| Timing parameters are resolved on each run — for instance, the forecast start defaults to the time the automation runs, so each run produces fresh forecasts. | ||
|
|
||
| Creating an automation | ||
| ---------------------- | ||
|
|
||
| Here is how you create an automation in the CLI, asking for daily (at 6 AM) forecasts of sensor 12: | ||
|
|
||
| .. code-block:: bash | ||
|
|
||
| flexmeasures add automation --asset 3 --name "Daily PV forecasts" --type forecasts \ | ||
| --cron "0 6 * * *" --timezone Europe/Amsterdam --sensor 12 | ||
|
|
||
| ``--type`` says what the automation computes, and defaults to ``forecasts``. | ||
| The remaining options are the ones the task itself needs: a forecast automation accepts everything `flexmeasures add forecast` accepts, such as ``--forecaster`` to pick the forecaster and ``--config`` to configure it (see :ref:`forecasting`). | ||
| The forecaster and its configuration are stored on a data source, so you can also pass ``--source`` to reuse the data source of an existing forecaster, in which case ``--forecaster`` and ``--config`` (and the individual configuration options) are not needed — the data source already determines them. | ||
| That data source is required while the automation exists, so it cannot be deleted until the automation is removed. | ||
|
|
||
| The recurrence is defined by a standard five-field cron string (minute, hour, day of month, month, and day of week), which defaults to ``"0 0 * * *"`` (daily at midnight). | ||
| It is interpreted in the automation's IANA timezone. | ||
| If ``--timezone`` is omitted, the current ``FLEXMEASURES_TIMEZONE`` value is copied to the automation. | ||
| Changing that configuration later does not change existing automations. | ||
| Cron aliases and optional seconds or year fields are not supported. | ||
|
|
||
| Automations are active by default (use ``--inactive`` to create them in deactivated state). | ||
| Use ``flexmeasures edit automation`` to rename, re-schedule (``--cron``), change the timezone, activate or deactivate an automation, and ``flexmeasures delete automation`` to remove one. | ||
| These changes are recorded in the asset's audit log. | ||
|
|
||
| For forecast automations, the sensor on which forecasts are saved (``sensor-to-save``, falling back to ``sensor``) must belong to the automation's asset or one of its descendants. | ||
| This relationship is checked both when the automation is created and immediately before each run. | ||
|
|
||
| Running automations | ||
| ------------------- | ||
|
|
||
| For automations to actually run, let a cron job execute the following command once per minute: | ||
|
|
||
| .. code-block:: bash | ||
|
|
||
| * * * * * flexmeasures jobs run-automations | ||
|
|
||
| Each due automation then queues its jobs. | ||
| If the runner misses runs, because it was down or overloaded, it catches up when it resumes: it queues only the latest missed run of each automation, rather than replaying stale ones. | ||
| Timing parameters that default to the run time are resolved when that catch-up run is queued, so it produces a current forecast. | ||
|
|
||
| Each scheduled run receives at most one automatic queueing attempt. | ||
| If the process crashes, or queueing fails after creating some jobs, that run is not retried automatically, because a retry could duplicate partial work. | ||
|
|
||
| The jobs record how they were created, which is shown on the asset's status page (UI), where recent jobs are listed. | ||
|
|
||
| Viewing automations | ||
| ------------------- | ||
|
|
||
| Automations defined on an asset can be viewed on the asset's *Automations* page in the UI, and listed with the API endpoint `[GET] /assets/(id)/automations <../api/v3_0.html#get--api-v3_0-assets-id-automations>`_. | ||
| An automation's details show the sensors it reads from and writes to, linking to each sensor's page. | ||
| Conversely, a sensor's page lists the automations that write data to it. | ||
|
|
||
| .. _automation_cursor: | ||
|
|
||
| Appendix: how the runner decides what is due | ||
| -------------------------------------------- | ||
|
|
||
| This section describes the bookkeeping behind the catch-up behaviour above. | ||
| You do not need it to use automations. | ||
|
|
||
| The runner is a stateless command, executed once a minute by cron, so it needs a durable record of how far each automation has got. | ||
| That record is one UTC timestamp per automation, its *cursor*: the scheduled time of the most recent run the automation has committed to. | ||
| Runs at or before the cursor are never queued again. | ||
| Before queueing any jobs, the runner advances the cursor to the run it is about to queue, and saves it. | ||
| The cursor therefore records that a run was claimed, not that queueing or the task itself succeeded. | ||
|
|
||
| Keeping a single moving timestamp, rather than a record per run, is what makes the behaviour above fall out: a runner that has been down catches up by moving the cursor straight to the latest due run, and two runners started in the same minute cannot queue the same run twice, because the cursor is advanced with a conditional update that only one of them can win. | ||
|
|
||
| A new automation starts from its creation minute and does not replay runs from before it existed. | ||
| Changing its cron expression or timezone, or reactivating it, restarts from the time of that change. | ||
| Deactivated automations do not accumulate catch-up work. | ||
| After upgrading an existing installation, runs scheduled before the upgrade are not replayed. | ||
|
|
||
| Daylight-saving-time transitions follow wall-clock semantics. | ||
| If the clock skips a scheduled local time in spring, that run happens once at the transition boundary. | ||
| If a scheduled local time occurs twice in autumn, the first instance is the canonical run and the repeated instance is not queued again. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.