-
Notifications
You must be signed in to change notification settings - Fork 17
libsimlin: add JSON APIs for model variable retrieval #219
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
Conversation
Add three new functions to libsimlin for directly retrieving variable details as JSON arrays: simlin_model_get_stocks_json, simlin_model_get_flows_json, and simlin_model_get_auxs_json. These functions allow callers to get stocks, flows, or auxiliaries without serializing the entire project. The new APIs follow the existing libsimlin memory ownership pattern - the returned buffer is owned by the caller and must be freed with simlin_free(). This provides a significant simplification for engine2 and pysimlin, which previously had to serialize the entire project to JSON just to access variable information. Changes include: - libsimlin: Three new FFI functions with proper documentation and tests - engine2: WASM bindings and Model class simplification using direct APIs - pysimlin: FFI bindings and Model class simplification using direct APIs The simplification is particularly beneficial for large projects where serializing the entire project is expensive when only variable info is needed. https://claude.ai/code/session_01PujQhTADskFsjJVY3GLuUQ
|
@codex review |
Pull Request Review: libsimlin JSON APIs for Variable RetrievalThis PR introduces targeted JSON APIs for retrieving stocks, flows, and auxiliaries from models without requiring full project serialization. Overall, this is a well-designed performance optimization with good test coverage. Here are my findings: ✅ Strengths
🔍 Code Quality ObservationsRust Implementation (libsimlin/src/lib.rs)Potential Issue - Lock Handling: let project_locked = (*model_ref.project).project.lock().unwrap();The code uses
Minor: Code Duplication fn get_variables_json<T, F>(
model: *mut SimlinModel,
out_buffer: *mut *mut u8,
out_len: *mut usize,
out_error: *mut *mut SimlinError,
filter_map: F,
error_context: &str,
) where
F: Fn(&engine::datamodel::Variable) -> Option<T>,
T: serde::Serialize,However, given there are only 3 variable types and they're unlikely to expand, the current explicit approach is reasonable. Memory Safety - Excellent:
TypeScript Implementation (engine2)Good Use of RAII Pattern: try {
fn(model, outBufPtr, outLenPtr, outErrPtr);
// ... error handling and result processing ...
return data;
} finally {
free(outBufPtr);
free(outLenPtr);
free(outErrPtr);
}Proper Memory Management:
Minor - Repeated Code:
Python Implementation (pysimlin)Correct CFFI Usage: output_ptr = ffi.new("uint8_t **")
output_len_ptr = ffi.new("uintptr_t *")
# ...
try:
return bytes(ffi.buffer(output_ptr[0], output_len_ptr[0]))
finally:
lib.simlin_free(output_ptr[0])Properly uses CFFI's buffer protocol and ensures cleanup in finally block. Good Error Handling: 🎯 Model Class SimplificationThe changes successfully simplify the Model classes in both engine2 and pysimlin: Before: model = self._get_model_json() # Serializes entire project
self._cached_stocks = ... for s in model.stocks ...After: json_bytes = get_stocks_json(self._ptr) # Direct variable access
stocks_json = json.loads(json_bytes.decode("utf-8"))This is cleaner and more efficient, especially for workflows that only query variable information. 🔒 SecurityNo Security Concerns Identified:
⚡ PerformanceExpected Benefits:
Potential Concern:
For extremely high-frequency calls, a more direct structured API might be faster, but for typical usage patterns this should be fine. 📝 TestingTest Quality: Excellent The tests verify:
Missing Test Coverage:
🎨 Style & ConventionsCommit Message: The commit follows the repository style perfectly:
Code Style: All code follows established patterns in the codebase. No style issues. 🤔 Questions/Suggestions
✅ VerdictLGTM with minor suggestions This PR is well-implemented, properly tested, and provides a clear performance benefit. The code quality is high, follows repository conventions, and introduces no security concerns. The only substantive question is about mutex lock handling in FFI functions - the current behavior (panic on poisoned lock) may be acceptable, but worth confirming. Recommended before merge:
Nice work! 🚀 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a4bdac1488
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| // Extract stocks from the datamodel and convert to JSON types | ||
| let stocks: Vec<engine::json::Stock> = datamodel_model | ||
| .variables | ||
| .iter() | ||
| .filter_map(|var| match var { | ||
| engine::datamodel::Variable::Stock(stock) => { | ||
| Some(engine::json::Stock::from(stock.clone())) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Preserve deterministic variable ordering
The new JSON APIs emit variables in the datamodel’s insertion order, but the existing JSON serialization path sorts stocks/flows/auxiliaries by canonical identifier for determinism (json::Model does sort_by_key(canonicalize) in src/simlin-engine/src/json.rs). Since the JS/Python Model.* accessors previously used project serialization, callers implicitly got a stable, canonical order. With this change, the same model can return a different order depending on import/edit history, which can break deterministic outputs and UI/tests that assume sorted lists. Consider sorting the collected vectors before serializing so these APIs match the prior behavior.
Useful? React with 👍 / 👎.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #219 +/- ##
==========================================
- Coverage 76.82% 76.79% -0.03%
==========================================
Files 69 69
Lines 20523 20624 +101
==========================================
+ Hits 15766 15839 +73
- Misses 4757 4785 +28 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Add three new functions to libsimlin for directly retrieving variable
details as JSON arrays: simlin_model_get_stocks_json,
simlin_model_get_flows_json, and simlin_model_get_auxs_json. These
functions allow callers to get stocks, flows, or auxiliaries without
serializing the entire project.
The new APIs follow the existing libsimlin memory ownership pattern -
the returned buffer is owned by the caller and must be freed with
simlin_free(). This provides a significant simplification for engine2
and pysimlin, which previously had to serialize the entire project to
JSON just to access variable information.
Changes include:
The simplification is particularly beneficial for large projects where
serializing the entire project is expensive when only variable info is
needed.
https://claude.ai/code/session_01PujQhTADskFsjJVY3GLuUQ