fairagro-middleware-api-client 8.7.1.dev8__tar.gz → 8.7.1.dev11__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (17) hide show
  1. {fairagro_middleware_api_client-8.7.1.dev8 → fairagro_middleware_api_client-8.7.1.dev11}/PKG-INFO +1 -1
  2. {fairagro_middleware_api_client-8.7.1.dev8 → fairagro_middleware_api_client-8.7.1.dev11}/src/middleware/api_client/api_client.py +7 -5
  3. {fairagro_middleware_api_client-8.7.1.dev8 → fairagro_middleware_api_client-8.7.1.dev11}/tests/unit/test_client.py +16 -13
  4. {fairagro_middleware_api_client-8.7.1.dev8 → fairagro_middleware_api_client-8.7.1.dev11}/.gitignore +0 -0
  5. {fairagro_middleware_api_client-8.7.1.dev8 → fairagro_middleware_api_client-8.7.1.dev11}/README.md +0 -0
  6. {fairagro_middleware_api_client-8.7.1.dev8 → fairagro_middleware_api_client-8.7.1.dev11}/example_client_config.yaml +0 -0
  7. {fairagro_middleware_api_client-8.7.1.dev8 → fairagro_middleware_api_client-8.7.1.dev11}/pyproject.toml +0 -0
  8. {fairagro_middleware_api_client-8.7.1.dev8 → fairagro_middleware_api_client-8.7.1.dev11}/src/middleware/api_client/__init__.py +0 -0
  9. {fairagro_middleware_api_client-8.7.1.dev8 → fairagro_middleware_api_client-8.7.1.dev11}/src/middleware/api_client/config.py +0 -0
  10. {fairagro_middleware_api_client-8.7.1.dev8 → fairagro_middleware_api_client-8.7.1.dev11}/src/middleware/api_client/models.py +0 -0
  11. {fairagro_middleware_api_client-8.7.1.dev8 → fairagro_middleware_api_client-8.7.1.dev11}/src/middleware/api_client/py.typed +0 -0
  12. {fairagro_middleware_api_client-8.7.1.dev8 → fairagro_middleware_api_client-8.7.1.dev11}/tests/conftest.py +0 -0
  13. {fairagro_middleware_api_client-8.7.1.dev8 → fairagro_middleware_api_client-8.7.1.dev11}/tests/integration/conftest.py +0 -0
  14. {fairagro_middleware_api_client-8.7.1.dev8 → fairagro_middleware_api_client-8.7.1.dev11}/tests/integration/test_create_arcs.py +0 -0
  15. {fairagro_middleware_api_client-8.7.1.dev8 → fairagro_middleware_api_client-8.7.1.dev11}/tests/unit/test_api_client_config.py +0 -0
  16. {fairagro_middleware_api_client-8.7.1.dev8 → fairagro_middleware_api_client-8.7.1.dev11}/tests/unit/test_client_config.py +0 -0
  17. {fairagro_middleware_api_client-8.7.1.dev8 → fairagro_middleware_api_client-8.7.1.dev11}/tests/unit/test_retry_logic.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fairagro-middleware-api-client
3
- Version: 8.7.1.dev8
3
+ Version: 8.7.1.dev11
4
4
  Summary: The FAIRagro advanced middleware API client
5
5
  Requires-Python: >=3.12
6
6
  Requires-Dist: httpx>=0.28.1
@@ -280,12 +280,14 @@ class ApiClient:
280
280
  identifier = self._extract_identifier_from_rocrate(serialized)
281
281
  if identifier is not None:
282
282
  if identifier in seen_identifiers:
283
- await self._cancel_pending_arc_tasks(pending_tasks)
284
- raise ApiClientError(
285
- f"Duplicate ARC identifier '{identifier}' submitted more than once "
286
- f"in harvest {harvest_id}. This is likely a client-side data error "
287
- "(two different ARCs sharing the same identifier)."
283
+ logger.error(
284
+ "Skipping duplicate ARC identifier '%s' in harvest %s. "
285
+ "Two ARCs share the same identifier this is a client-side data error.",
286
+ identifier,
287
+ harvest_id,
288
288
  )
289
+ failed_submissions += 1
290
+ continue
289
291
  seen_identifiers.add(identifier)
290
292
 
291
293
  task = asyncio.create_task(submit_one(serialized))
@@ -714,11 +714,13 @@ async def test_harvest_arcs_cancels_on_catastrophic_error(client_config: Config)
714
714
 
715
715
  @pytest.mark.asyncio
716
716
  @respx.mock
717
- async def test_harvest_arcs_fails_on_duplicate_identifier(client_config: Config) -> None:
718
- """harvest_arcs marks harvest as failed when the same ARC identifier appears twice."""
719
- # Two ARC dicts that share the same RO-Crate identifier — simulates a
720
- # client-side data error where two distinct ARCs were accidentally given
721
- # the same identifier field.
717
+ async def test_harvest_arcs_skips_duplicate_identifier(client_config: Config) -> None:
718
+ """harvest_arcs skips a duplicate ARC and completes the harvest successfully.
719
+
720
+ When the same RO-Crate identifier appears twice in the input, the second
721
+ occurrence is counted as a failed submission and the harvest continues.
722
+ This prevents a single client-side data error from aborting the whole harvest.
723
+ """
722
724
  arc_a = {
723
725
  "@context": "https://w3id.org/ro/crate/1.1/context",
724
726
  "@graph": [{"@id": "./", "@type": "Dataset", "identifier": "duplicate-arc", "name": "ARC A"}],
@@ -727,23 +729,24 @@ async def test_harvest_arcs_fails_on_duplicate_identifier(client_config: Config)
727
729
  "@context": "https://w3id.org/ro/crate/1.1/context",
728
730
  "@graph": [{"@id": "./", "@type": "Dataset", "identifier": "duplicate-arc", "name": "ARC B"}],
729
731
  }
730
- failed_response = {**_HARVEST_RESPONSE, "status": "FAILED"}
732
+ completed_response = {**_HARVEST_RESPONSE, "status": "COMPLETED", "completed_at": "2024-01-01T01:00:00Z"}
731
733
  respx.post(f"{client_config.api_url}v3/harvests").mock(
732
734
  return_value=httpx.Response(http.HTTPStatus.OK, json=_HARVEST_RESPONSE)
733
735
  )
734
- # The first ARC is submitted successfully before the duplicate is detected.
735
- respx.post(f"{client_config.api_url}v3/harvests/harvest-456/arcs").mock(
736
+ # Only the first ARC is submitted; the duplicate is skipped client-side.
737
+ arc_route = respx.post(f"{client_config.api_url}v3/harvests/harvest-456/arcs").mock(
736
738
  return_value=httpx.Response(http.HTTPStatus.OK, json=_ARC_RESPONSE)
737
739
  )
738
- fail_route = respx.patch(f"{client_config.api_url}v3/harvests/harvest-456").mock(
739
- return_value=httpx.Response(http.HTTPStatus.OK, json=failed_response)
740
+ complete_route = respx.post(f"{client_config.api_url}v3/harvests/harvest-456/complete").mock(
741
+ return_value=httpx.Response(http.HTTPStatus.OK, json=completed_response)
740
742
  )
741
743
 
742
744
  async with ApiClient(client_config) as client:
743
- with pytest.raises(ApiClientError, match="Duplicate ARC identifier 'duplicate-arc'"):
744
- await client.harvest_arcs("test-rdi", _arc_gen(arc_a, arc_b))
745
+ result = await client.harvest_arcs("test-rdi", _arc_gen(arc_a, arc_b))
745
746
 
746
- assert fail_route.called
747
+ assert result.status == "COMPLETED"
748
+ assert arc_route.call_count == 1 # duplicate was skipped, not submitted
749
+ assert complete_route.called
747
750
 
748
751
 
749
752
  @pytest.mark.asyncio