feat: carbon-aware codecarbon wait (forecast + greenest-window selection) - #1363
Open
davidberenstein1957 wants to merge 3 commits into
Open
feat: carbon-aware codecarbon wait (forecast + greenest-window selection)#1363davidberenstein1957 wants to merge 3 commits into
codecarbon wait (forecast + greenest-window selection)#1363davidberenstein1957 wants to merge 3 commits into
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## feat/intensity-providers #1363 +/- ##
============================================================
+ Coverage 91.60% 91.74% +0.14%
============================================================
Files 49 51 +2
Lines 5109 5245 +136
============================================================
+ Hits 4680 4812 +132
- Misses 429 433 +4 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Fetch an Electricity Maps carbon intensity forecast, pick the window with the lowest mean intensity that still meets the deadline, and either report it (--dry-run) or sleep until it and delegate to run_and_monitor. Advisory/blocking only: no EmissionsData schema change, no decorator, and no static fallback profile. Without a token, get_forecast returns None and the job runs immediately -- a job is never blocked on a missing credential. get_forecast should become a method on the provider protocol once pluggable intensity providers land. Refs #1356 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Add a CLI reference section for `codecarbon wait` covering every flag and its default, the forecast requirements, and the run-now degradation when no forecast is available, plus one cross-link from the CLI tutorial. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`codecarbon wait` had its own HTTP path to Electricity Maps. It now goes through `electricitymaps_api.request`, so the token lookup, the request plumbing and the exponential failure cooldown are shared with the current-intensity path: a failing API is backed off once, process-wide. The forecast response is deliberately not put in the intensity cache. That cache exists for a value refetched on every measurement tick with a 300 s TTL; a forecast is fetched once per `wait` invocation and has a completely different useful lifetime. `get_forecast` still never raises: a cooldown is just one more reason to return None and run the job now. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
davidberenstein1957
force-pushed
the
feat/carbon-aware-scheduling
branch
from
August 13, 2026 05:28
a71bcb1 to
e7022e6
Compare
davidberenstein1957
changed the base branch from
master
to
feat/intensity-providers
August 13, 2026 05:28
davidberenstein1957
marked this pull request as ready for review
August 13, 2026 05:31
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Draft. A first, deliberately narrow slice of carbon-aware scheduling (#1356).
What is in it
codecarbon/core/intensity_forecast.py—IntensityPoint/Forecastdataclasses,get_forecast()against the Electricity Maps/carbon-intensity/forecastendpoint (reusing the existingelectricitymaps_api_tokenconfig key, the same location-parameter construction and the same timeout constant asget_emissions), andbest_window(), a pure sliding-mean window search with no I/O.codecarbon/cli/wait.py+ awaitcommand incodecarbon/cli/main.py:The blocking form delegates to the existing
run_and_monitor, so measurement, CSV output and exit-code propagation are unchanged. The tracker only starts after the sleep, so a waiting process holds no lock. Ctrl-C during the wait starts the job immediately rather than aborting.get_forecastnever raises: no token, a non-200, a malformed payload or an empty forecast all returnNone, and every caller degrades to running now. A job is never blocked on a missing credential.What is deliberately not in it
@carbon_awaredecorator /wait_for_green_windowcontext manager. The CLI is the smaller surface and validates whether anyone wants the sleeping behaviour before we own a second one.deferred_seconds/avoided_emissionsonEmissionsData. Worth having, but they should ship with a proven blocking path — two always-zero CSV columns are a schema change for no reader.What is blocked on the intensity-provider work
Electricity Maps is currently the only source that can serve a forecast, and only for users holding a paid token. That caps how much of the audience this feature can reach, and it is the main reason this PR is a narrow slice rather than the full design in #1356.
get_forecastis written to be absorbed: once pluggable intensity providers land it should become an optionalforecast()method on the provider protocol rather than a second HTTP client, and the HTTP is kept in one place here so that move is mechanical. Reviewers may reasonably prefer to hold this until the provider layer exists — hence draft.Tests
tests/test_intensity_forecast.py(14) andtests/cli/test_wait.py(16), all passing, no network — HTTP is stubbed withresponsesas intests/test_electricitymaps_api.py, and geolocation, config andtime.sleepare monkeypatched in the CLI tests. Coverage includes payload parsing, lat/lon vscountryCodeselection, naive-vs-aware timestamps, horizon truncation, every failure mode returningNone, the window search (trough, flat, monotonic, deadline shorter than duration, duration longer than horizon), the duration parser and its rejections, threshold short-circuit, and delegation torun_and_monitorwith the residual command.Docs are not written yet; they should land with this before it leaves draft.
Refs #1356
🤖 Generated with Claude Code