Conversation
…pdate_item_custom_metadata Adds optional optimistic concurrency control to run and item custom metadata updates. When `custom_metadata_checksum` is provided the server rejects the write with HTTP 412 if the metadata was modified since the checksum was read; pass `None` (default) to skip the check. Changes: - platform/resources/runs.py: add keyword-only `custom_metadata_checksum` param to `Run.update_custom_metadata` and `Run.update_item_custom_metadata`, forwarded to `CustomMetadataUpdateRequest` - application/_service.py: propagate `custom_metadata_checksum` through `ApplicationService.application_run_update_custom_metadata`, `application_run_update_item_custom_metadata`, and both static wrappers; handle HTTP 412 explicitly as `ValueError` with a clear concurrency-conflict message instead of the generic `RuntimeError` fallback - tests: add unit tests for checksum forwarding (None and non-None) at the `Run` resource layer; add service-layer tests for checksum propagation and 412→ValueError mapping; fix stale assertions to include `custom_metadata_checksum=None`
There was a problem hiding this comment.
Pull request overview
This PR adds optimistic concurrency control support for run/item custom metadata updates by introducing an optional checksum parameter and surfacing a dedicated conflict error for HTTP 412 responses.
Changes:
- Added keyword-only
custom_metadata_checksumplumbing from CLI → application service → platformRun.update_*_custom_metadata()calls. - Added
ConcurrencyConflictError(ValueError)and mapped HTTP 412 (precondition failed) to this error in the application service layer. - Updated and extended unit tests to validate checksum forwarding and 412→
ConcurrencyConflictErrorbehavior.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/aignostics/application/service_test.py | Updates assertions for the new checksum argument and adds tests for checksum forwarding + HTTP 412 mapping. |
| src/aignostics/system/_exceptions.py | Introduces ConcurrencyConflictError for optimistic concurrency conflicts. |
| src/aignostics/platform/resources/runs.py | Adds custom_metadata_checksum kw-only parameter and forwards it into the OpenAPI request model. |
| src/aignostics/application/_service.py | Accepts checksum in service APIs and converts HTTP 412 ApiException into ConcurrencyConflictError. |
| src/aignostics/application/_cli.py | Adds --checksum option to metadata update commands and handles ConcurrencyConflictError. |
❌ 1 Tests Failed:
View the top 1 failed test(s) by shortest run time
To view more test analytics, go to the Test Analytics Dashboard |
- Re-export ConcurrencyConflictError from aignostics.system public API - Update imports in _service.py and _cli.py to use public path - Add unit tests for CLI --checksum success path and ConcurrencyConflictError handler on both update-metadata and update-item-metadata commands
Extract repeated string literals into named constants:
- APPLICATION_CLI_SERVICE_PATCH_TARGET for the service patch path (5 uses)
- _TEST_METADATA_JSON for the metadata stub (4 uses)
- cast("dict[str, Any]") → cast(dict[str, Any]) in runs.py (4 uses)
| from aignostics.platform import NotFoundException, RunData, RunOutput | ||
| from aignostics.platform.resources.runs import ApiException | ||
| from aignostics.system._exceptions import ConcurrencyConflictError |
Replace internal module imports with public API paths: - aignostics.platform.resources.runs.ApiException → aignostics.platform - aignostics.system._exceptions.ConcurrencyConflictError → aignostics.system
PR #632 Code Review CompleteComprehensive review of optimistic concurrency control implementation. Executive SummaryThis PR successfully implements optimistic concurrency control via an optional Overall Assessment: High-quality implementation with one minor fix required Critical Findings (BLOCKING)
|
…exit code 3, GUI handler
- Move ConcurrencyConflictError from system/_exceptions to platform/_exceptions
and re-export from aignostics.platform — eliminates application→system
bidirectional dependency
- Revert cast() string-form regression in runs.py (restore TC006-compliant
cast("dict[str, Any]", ...) in all four call sites)
- CLI conflict handlers now exit 3 (distinct from exit 2 for not-found)
- Add specific ConcurrencyConflictError handler in GUI metadata editor
with "reload and retry" guidance instead of generic error message
- Update all imports and test assertions accordingly
|



🛡️ Implements PYSDK-130 following CC-SOP-01 Change Control, part of our ISO 13485-certified QMS | Ketryx Project
Summary
custom_metadata_checksumkeyword-only parameter toRun.update_custom_metadata(),Run.update_item_custom_metadata()(platform layer), all four service-layer methods, and both CLI commands (run update-metadata --checksum,run update-item-metadata --checksum). Defaults toNone— fully backward compatible.ConcurrencyConflictError(ValueError)insystem/_exceptions.py; HTTP 412 from the server now raises this instead of a genericValueError, letting callers distinguish concurrency conflicts from invalid-ID errors.ConcurrencyConflictErrormapping, and fixes previously brokenassert_called_once_withassertions. Removes deadPublicApiimport fromruns_test.py.Test plan
make lintpasses (mypy, pyright, ruff)uv run pytest tests/aignostics/application/service_test.py -m unit -v— all 21 tests green, including the 4 new checksum/412 testsuv run aignostics application run update-metadata --helpshows--checksumoptionuv run aignostics application run update-item-metadata --helpshows--checksumoptionPosted by Claude claude-sonnet-4-6 via Claude Code, applying skills cc-sop-01 on behalf of Andreas Kunft (andreas@aignostics.com)