Feature/prepare mars2grib for cache#190
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## develop #190 +/- ##
===========================================
- Coverage 62.33% 61.94% -0.39%
===========================================
Files 303 303
Lines 11601 11674 +73
Branches 1036 1046 +10
===========================================
Hits 7232 7232
- Misses 4369 4442 +73 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
Prepares mars2grib for an upcoming cache mechanism by introducing a transitional staged-encoding workflow (prepare/finalise) alongside the existing encode() hot path.
Changes:
- Added staged header encoding to
SpecializedEncoder(prepare()+finaliseEncoding()). - Added a transitional staged cache entry and staged workflow in
CoreOperations. - Exposed a temporary opaque staged cache API in
Mars2Grib(CacheEntry,prepare(),finaliseEncoding()).
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
src/metkit/mars2grib/frontend/header/SpecializedEncoder.h |
Adds staged encoder methods to split header encoding into preparation and runtime finalisation. |
src/metkit/mars2grib/api/Mars2Grib.h |
Exposes a temporary public staged cache API (opaque cache entry + prepare/finalise). |
src/metkit/mars2grib/api/Mars2Grib.cc |
Implements the opaque cache wrapper/deleter and forwards staged calls to CoreOperations. |
src/metkit/mars2grib/CoreOperations.h |
Introduces CoreOperations::CacheEntry plus staged prepare()/finaliseEncoding() pipeline functions. |
.github/copilot-instructions.md |
Adds repository-level Copilot instructions (doc sync checks for mars2grib-related changes). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| CacheEntryPtr prepare(const eckit::LocalConfiguration& mars, const eckit::LocalConfiguration& misc); | ||
|
|
There was a problem hiding this comment.
New public staged-encoding API (prepare() / finaliseEncoding()) is introduced without corresponding test coverage. There are existing mars2grib API tests (e.g. tests/mars2grib/api/test_cpp_api.cc) covering encode(), so please add at least one test that exercises prepare() + repeated finaliseEncoding() and verifies it produces a valid CodesHandle (and ideally matches encode() output for the same inputs).
There was a problem hiding this comment.
It is a temporary solution that will be removed soon
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // @todo eventually need to return another clone to commit modifications | ||
| return samplePtr; |
There was a problem hiding this comment.
finaliseEncoding() currently returns the handle after applying the stage callbacks without performing the final stage clone that encode() does (it clones after every stage). If the clone step is required to match encode() semantics (and the comment suggests it is), clone before returning and drop the @todo so staged output is consistent with the non-staged path.
| // @todo eventually need to return another clone to commit modifications | |
| return samplePtr; | |
| auto resultPtr = clone_or_throw<OutDict_t>(*samplePtr); | |
| return resultPtr; |
There was a problem hiding this comment.
Potentially heavy operation in the hot path. I'll add this only if strictly needed
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| try { | ||
| return CoreOperations::finaliseEncoding<double, eckit::LocalConfiguration, eckit::LocalConfiguration, Options, | ||
| metkit::codes::CodesHandle>( | ||
| *(cacheEntry->impl_), Span<const double>{values}, mars, misc, opts_, language_); | ||
| } | ||
| catch (...) { | ||
| throw eckit::Exception("Unable to finalise encoding", Here()); | ||
| } |
There was a problem hiding this comment.
The catch-all here rethrows a new eckit::Exception and discards the detailed nested exception chain produced by CoreOperations::finaliseEncoding(...). This makes debugging failures much harder and changes the observable error behavior compared to encode(). Prefer either letting the original exception propagate, or rethrowing while preserving the nested exception (e.g., std::throw_with_nested(eckit::Exception(...))).
| try { | |
| return CoreOperations::finaliseEncoding<double, eckit::LocalConfiguration, eckit::LocalConfiguration, Options, | |
| metkit::codes::CodesHandle>( | |
| *(cacheEntry->impl_), Span<const double>{values}, mars, misc, opts_, language_); | |
| } | |
| catch (...) { | |
| throw eckit::Exception("Unable to finalise encoding", Here()); | |
| } | |
| return CoreOperations::finaliseEncoding<double, eckit::LocalConfiguration, eckit::LocalConfiguration, Options, | |
| metkit::codes::CodesHandle>( | |
| *(cacheEntry->impl_), Span<const double>{values}, mars, misc, opts_, language_); |
| try { | ||
| return CoreOperations::finaliseEncoding<float, eckit::LocalConfiguration, eckit::LocalConfiguration, Options, | ||
| metkit::codes::CodesHandle>( | ||
| *(cacheEntry->impl_), Span<const float>{values}, mars, misc, opts_, language_); | ||
| } | ||
| catch (...) { | ||
| throw eckit::Exception("Unable to finalise encoding", Here()); | ||
| } |
There was a problem hiding this comment.
Same issue as the double overload: catching everything and throwing a fresh eckit::Exception drops the underlying nested exception context from CoreOperations::finaliseEncoding(...). Consider removing this try/catch or preserving the nested exception chain when wrapping.
| try { | |
| return CoreOperations::finaliseEncoding<float, eckit::LocalConfiguration, eckit::LocalConfiguration, Options, | |
| metkit::codes::CodesHandle>( | |
| *(cacheEntry->impl_), Span<const float>{values}, mars, misc, opts_, language_); | |
| } | |
| catch (...) { | |
| throw eckit::Exception("Unable to finalise encoding", Here()); | |
| } | |
| return CoreOperations::finaliseEncoding<float, eckit::LocalConfiguration, eckit::LocalConfiguration, Options, | |
| metkit::codes::CodesHandle>( | |
| *(cacheEntry->impl_), Span<const float>{values}, mars, misc, opts_, language_); |
Description
Summary
This draft PR introduces a first staged-encoding path for
mars2grib, together with the minimal API exposure needed to exercise it from the current public interface.The main goal is not to finalize the cache design yet, but to prepare the codebase for the cache mechanism that will be implemented shortly and, in the meantime, enable comparison against the existing well-tested cache-based workflow.
What is included
SpecializedEncoderAdded two new staged methods:
prepare(...)finaliseEncoding(...)These split the current hot-path header generation into:
The existing
encode(...)path remains unchanged.CoreOperationsAdded a first staged workflow on top of the encoder:
CoreOperations::CacheEntryCoreOperations::prepare(...)CoreOperations::finaliseEncoding(...)This path mirrors the existing normalization / layout resolution / header encoding / value injection flow, but exposes the intermediate prepared cache object explicitly.
This is intended as a transitional step toward a future implementation where cache lifecycle and reuse will be fully internalized inside the core layer.
Mars2GribAPIAdded temporary public exposure of the staged path:
CacheEntryprepare(...)finaliseEncoding(...)The public API remains specialized on:
eckit::LocalConfigurationOptionsmetkit::codes::CodesHandleThe public cache object is only a thin opaque wrapper around the current core cache entry.
Important note
This PR does not claim that the staged cache API is final.
The newly exposed staged functions are temporary and are only here to:
So the intention of this PR is mainly:
Non-goals
This PR does not aim to:
Expected next step
A follow-up step should replace this temporary staged exposure with a cleaner internal cache design managed entirely in
CoreOperations, while preserving or simplifying the public API accordingly.Remarks
A few naming inconsistencies remain in the code (
par/misc) because this terminology has changed multiple times during the design discussions and is already spread across the existing codebase. I preferred not to do a large naming cleanup in this PR in order to keep the change focused on the staged/cache preparation itself.Contributor Declaration
By opening this pull request, I affirm the following: