Skip to content

refactor: update Antenna API client for POST /tasks and wrapped /result#134

Merged
mihow merged 6 commits intomainfrom
refactor/antenna-tasks-post-api
Apr 4, 2026
Merged

refactor: update Antenna API client for POST /tasks and wrapped /result#134
mihow merged 6 commits intomainfrom
refactor/antenna-tasks-post-api

Conversation

@mihow
Copy link
Copy Markdown
Collaborator

@mihow mihow commented Apr 3, 2026

Summary

Adapts the Antenna API client to the breaking changes in RolnickLab/antenna#1197. Must be deployed simultaneously with that PR.

  • /jobs/{id}/tasks/ — GET with ?batch=N query param → POST with {"batch_size": N} body
  • /jobs/{id}/result/ — bare list[PipelineTaskResult]{"results": [...]} wrapper
  • Trailing slash added to POST URLs (Django APPEND_SLASH cannot redirect POSTs)
  • processing_service_name query param removed from both endpoints

Also adds typed Pydantic schemas for the new request/response shapes and updates the mock test server to use them as FastAPI body parameters.

Changes

File What
trapdata/antenna/datasets.py GET → POST, AntennaTasksRequest schema for body, trailing slash
trapdata/antenna/client.py Wrap results in AntennaTaskResults, validate response with AntennaResultPostResponse
trapdata/antenna/schemas.py Add AntennaTasksRequest, AntennaResultPostResponse, QueuedTaskAcknowledgment
trapdata/antenna/tests/antenna_api_server.py Mock server uses typed Pydantic request/response models

Test plan

  • All 12 unit tests pass (pytest trapdata/antenna/tests/test_worker.py)
  • E2E integration test against local Antenna stack with PR branch: 10/10 images processed, 0 errors, 100% result post success (verified across 3 runs)

Deployment

Deploy simultaneously with RolnickLab/antenna#1197. The API contract changes are breaking in both directions.

Summary by CodeRabbit

  • Refactor
    • Task fetching switched to POST with a configurable batch size.
    • Result posting now sends structured payloads; responses are validated and logged with queued counts per job.
  • Tests
    • Test HTTP client redirect behavior adjusted and server test endpoints updated to reflect POST semantics.
  • Documentation
    • API docs updated to reflect the new POST /tasks and structured result interactions.

Adapt to breaking API changes in RolnickLab/antenna#1197:

- /jobs/{id}/tasks/ changed from GET with ?batch=N to POST with
  {"batch_size": N} in the request body
- /jobs/{id}/result/ now expects {"results": [...]} wrapper instead of
  a bare list
- Trailing slash is required on POST URLs (Django APPEND_SLASH cannot
  redirect POSTs)
- processing_service_name query param removed from both endpoints

Also adds typed Pydantic schemas for the new request/response shapes
(AntennaTasksRequest, AntennaResultPostResponse) and updates the mock
test server to use them as FastAPI body parameters.

Co-Authored-By: Claude <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 3, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 045fb88f-998a-4540-afa2-75749d20f874

📥 Commits

Reviewing files that changed from the base of the PR and between 588c186 and 4b80022.

📒 Files selected for processing (7)
  • trapdata/antenna/benchmark.py
  • trapdata/antenna/client.py
  • trapdata/antenna/result_posting.py
  • trapdata/antenna/tests/antenna_api_server.py
  • trapdata/antenna/tests/test_memory_leak.py
  • trapdata/antenna/tests/test_worker.py
  • trapdata/antenna/worker.py
💤 Files with no reviewable changes (2)
  • trapdata/antenna/worker.py
  • trapdata/antenna/benchmark.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • trapdata/antenna/tests/test_memory_leak.py

📝 Walkthrough

Walkthrough

The PR switches task polling from GET query requests to POST with a JSON body, removes the propagated processing_service_name argument across client/dataset/worker/result-posting code, adds new Pydantic request/response models for tasks and result posting, and validates POST responses before logging queued counts.

Changes

Cohort / File(s) Summary
Schemas
trapdata/antenna/schemas.py
Added AntennaTasksRequest(batch_size: int), QueuedTaskAcknowledgment, AntennaResultPostResponse(status, job_id, results_queued, tasks); updated docs to reflect POST semantics.
Client
trapdata/antenna/client.py
Removed processing_service_name from get_jobs/post_batch_results signatures; post_batch_results sends AntennaTaskResults payload and validates response via AntennaResultPostResponse, logging results_queued.
Datasets / REST fetch
trapdata/antenna/datasets.py
RESTDataset._fetch_tasks() changed from authenticated GET /jobs/{id}/tasks (query) to POST /jobs/{id}/tasks/ with AntennaTasksRequest; removed processing_service_name from constructor and get_rest_dataloader.
Server tests / fixtures
trapdata/antenna/tests/antenna_api_server.py
Test server: /jobs/{id}/tasks/ endpoint changed to POST accepting AntennaTasksRequest; /jobs/{id}/result/ now accepts AntennaTaskResults and returns AntennaResultPostResponse with results_queued; removed get_last_get_jobs_service_name.
Result posting / worker / benchmark / tests
trapdata/antenna/result_posting.py, trapdata/antenna/worker.py, trapdata/antenna/benchmark.py, trapdata/antenna/tests/*
Removed processing_service_name from public/internal signatures and call sites; updated callers (worker, benchmark, result poster, tests) to use new client/dataloader/result-post APIs without that parameter; test HTTP clients set follow_redirects=False.

Sequence Diagram(s)

sequenceDiagram
    participant Worker as Worker
    participant Dataset as RESTDataset
    participant API as AntennaAPI
    participant Client as AntennaClient

    Worker->>Dataset: request next batch (POST /api/v2/jobs/{id}/tasks {batch_size})
    Dataset->>API: POST /api/v2/jobs/{id}/tasks/ (AntennaTasksRequest)
    API-->>Dataset: 200 OK (tasks list)
    Dataset-->>Worker: return tasks

    Worker->>Worker: process tasks -> results list
    Worker->>Client: post_batch_results(base_url, token, job_id, results)
    Client->>API: POST /api/v2/jobs/{id}/result/ (AntennaTaskResults)
    API-->>Client: 202 Accepted (AntennaResultPostResponse {results_queued})
    Client-->>Worker: confirm queued (results_queued)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

Possibly related PRs

Poem

🐰 I hopped through code where GETs once played,
Now POSTed batches prance in tidy JSON made,
Schemas guard the doors and responses are queued,
No service-name to trail the magnitude.
Hooray — the rabbit logs how many were queued! 🎉

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 64.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main changes: updating the Antenna API client to support POST /tasks endpoint and wrapped /result response format, which aligns with the core refactoring objectives across multiple files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/antenna-tasks-post-api

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
trapdata/antenna/client.py (1)

77-83: ⚠️ Potential issue | 🟠 Major

Remove unused processing_service_name parameter from function signature and call site.

The processing_service_name parameter is accepted and documented in the function signature but is never referenced in the implementation (it was removed from the API as noted in PR objectives). Remove it from the function definition at trapdata/antenna/client.py:77-83 and update the corresponding call site at trapdata/antenna/result_posting.py:177.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@trapdata/antenna/client.py` around lines 77 - 83, Remove the unused parameter
processing_service_name from the post_batch_results function signature in
trapdata/antenna/client.py by editing the post_batch_results definition to
accept only (base_url: str, auth_token: str, job_id: int, results:
list[AntennaTaskResult]) and update its type hints and docstring if present;
then update the call site in trapdata/antenna/result_posting.py (the invocation
of post_batch_results around line ~177) to stop passing processing_service_name
(pass the existing four args only). Ensure imports and any tests referring to
post_batch_results are updated accordingly.
🧹 Nitpick comments (2)
trapdata/antenna/schemas.py (1)

37-41: Consider adding validation for batch_size.

The batch_size field accepts any integer, including zero or negative values. If the API expects a positive integer, consider adding a constraint.

♻️ Optional: Add validation constraint
 class AntennaTasksRequest(pydantic.BaseModel):
     """Request body for POST /api/v2/jobs/{job_id}/tasks/."""

-    batch_size: int
+    batch_size: int = pydantic.Field(gt=0)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@trapdata/antenna/schemas.py` around lines 37 - 41, AntennaTasksRequest
currently allows any integer for batch_size; enforce that it is a positive
integer by updating the AntennaTasksRequest model: change the batch_size field
to use a constrained type or Field with gt=0 (e.g., pydantic.conint(gt=0) or
Field(..., gt=0)) or add a `@validator` on batch_size to raise a ValueError for
non-positive values so requests with zero/negative batch_size are rejected;
modify the AntennaTasksRequest class accordingly.
trapdata/antenna/datasets.py (1)

113-113: Remove unused processing_service_name parameter from RESTDataset.__init__.

The parameter is accepted and stored at line 132 but never referenced in any class method, including _fetch_tasks(). Per the PR objectives removing this from endpoints, the parameter should be removed from the class to avoid confusion. Also update the call site in get_rest_dataloader() (line 437).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@trapdata/antenna/datasets.py` at line 113, Remove the unused
processing_service_name parameter from RESTDataset.__init__ and its stored
attribute: delete the parameter from the signature and any assignment in
__init__, and ensure no methods (e.g., _fetch_tasks) reference it; then update
the call site in get_rest_dataloader() to stop passing processing_service_name.
Verify RESTDataset.__init__, _fetch_tasks, and get_rest_dataloader are
consistent after removing the parameter.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@trapdata/antenna/client.py`:
- Around line 77-83: Remove the unused parameter processing_service_name from
the post_batch_results function signature in trapdata/antenna/client.py by
editing the post_batch_results definition to accept only (base_url: str,
auth_token: str, job_id: int, results: list[AntennaTaskResult]) and update its
type hints and docstring if present; then update the call site in
trapdata/antenna/result_posting.py (the invocation of post_batch_results around
line ~177) to stop passing processing_service_name (pass the existing four args
only). Ensure imports and any tests referring to post_batch_results are updated
accordingly.

---

Nitpick comments:
In `@trapdata/antenna/datasets.py`:
- Line 113: Remove the unused processing_service_name parameter from
RESTDataset.__init__ and its stored attribute: delete the parameter from the
signature and any assignment in __init__, and ensure no methods (e.g.,
_fetch_tasks) reference it; then update the call site in get_rest_dataloader()
to stop passing processing_service_name. Verify RESTDataset.__init__,
_fetch_tasks, and get_rest_dataloader are consistent after removing the
parameter.

In `@trapdata/antenna/schemas.py`:
- Around line 37-41: AntennaTasksRequest currently allows any integer for
batch_size; enforce that it is a positive integer by updating the
AntennaTasksRequest model: change the batch_size field to use a constrained type
or Field with gt=0 (e.g., pydantic.conint(gt=0) or Field(..., gt=0)) or add a
`@validator` on batch_size to raise a ValueError for non-positive values so
requests with zero/negative batch_size are rejected; modify the
AntennaTasksRequest class accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6dc7c977-e8ad-4132-9851-6fb0310f3fca

📥 Commits

Reviewing files that changed from the base of the PR and between c0bbae5 and cd6377a.

📒 Files selected for processing (4)
  • trapdata/antenna/client.py
  • trapdata/antenna/datasets.py
  • trapdata/antenna/schemas.py
  • trapdata/antenna/tests/antenna_api_server.py

…nd dataset APIs

The processing_service_name parameter was threaded through post_batch_results,
ResultPoster.post_async, RESTDataset, get_rest_dataloader, and _process_job but
was never sent to the Antenna API in any of these code paths. Removes the dead
parameter from all affected signatures and call sites.

Also adds gt=0 validation to AntennaTasksRequest.batch_size.

Co-Authored-By: Claude <noreply@anthropic.com>
@mihow
Copy link
Copy Markdown
Collaborator Author

mihow commented Apr 4, 2026

Addressed all review comments in 588c186:

  • Removed unused processing_service_name from post_batch_results(), ResultPoster.post_async(), RESTDataset.__init__(), get_rest_dataloader(), _process_job(), and all call sites (worker, benchmark, tests). The parameter was threaded through these layers but never sent to the API.
  • Added gt=0 validation to AntennaTasksRequest.batch_size.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
trapdata/antenna/result_posting.py (2)

17-18: ⚠️ Potential issue | 🟡 Minor

Stale docstring example shows removed service_name parameter.

The usage example still references service_name which was removed from the post_async signature.

📝 Proposed fix
-    poster = ResultPoster(max_pending=5)
-    poster.post_async(base_url, auth_token, job_id, results, service_name)
+    poster = ResultPoster(max_pending=5)
+    poster.post_async(base_url, auth_token, job_id, results)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@trapdata/antenna/result_posting.py` around lines 17 - 18, The
docstring/example still shows calling poster.post_async with a removed parameter
service_name; update the example to call poster.post_async(base_url, auth_token,
job_id, results) (and leave poster.get_metrics() as-is) so it matches the
current post_async signature; search for poster.post_async occurrences in the
module (and any examples or tests) and remove the obsolete service_name argument
from those calls.

62-65: ⚠️ Potential issue | 🟡 Minor

Stale docstring example in class docstring.

Same issue as the module docstring - the example still includes service_name.

📝 Proposed fix
     Example:
         poster = ResultPoster(max_pending=10)
-        poster.post_async(base_url, auth_token, job_id, results, service_name)
+        poster.post_async(base_url, auth_token, job_id, results)
         metrics = poster.get_metrics()
         poster.shutdown()
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@trapdata/antenna/result_posting.py` around lines 62 - 65, Update the stale
example in the ResultPoster class docstring (and any similar module docstring)
to match the current ResultPoster API: remove the obsolete service_name argument
from the post_async call and show the correct call sequence using
ResultPoster(max_pending=10), poster.post_async(base_url, auth_token, job_id,
results), poster.get_metrics(), and poster.shutdown(). Ensure the docstring
example references the ResultPoster class and its post_async, get_metrics, and
shutdown methods so it stays accurate.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@trapdata/antenna/result_posting.py`:
- Around line 17-18: The docstring/example still shows calling poster.post_async
with a removed parameter service_name; update the example to call
poster.post_async(base_url, auth_token, job_id, results) (and leave
poster.get_metrics() as-is) so it matches the current post_async signature;
search for poster.post_async occurrences in the module (and any examples or
tests) and remove the obsolete service_name argument from those calls.
- Around line 62-65: Update the stale example in the ResultPoster class
docstring (and any similar module docstring) to match the current ResultPoster
API: remove the obsolete service_name argument from the post_async call and show
the correct call sequence using ResultPoster(max_pending=10),
poster.post_async(base_url, auth_token, job_id, results), poster.get_metrics(),
and poster.shutdown(). Ensure the docstring example references the ResultPoster
class and its post_async, get_metrics, and shutdown methods so it stays
accurate.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ec38284c-0a5c-4350-b474-56574263c24b

📥 Commits

Reviewing files that changed from the base of the PR and between cd6377a and 588c186.

📒 Files selected for processing (7)
  • trapdata/antenna/benchmark.py
  • trapdata/antenna/client.py
  • trapdata/antenna/datasets.py
  • trapdata/antenna/result_posting.py
  • trapdata/antenna/schemas.py
  • trapdata/antenna/tests/test_memory_leak.py
  • trapdata/antenna/worker.py
💤 Files with no reviewable changes (3)
  • trapdata/antenna/tests/test_memory_leak.py
  • trapdata/antenna/benchmark.py
  • trapdata/antenna/worker.py

…b calls

The previous commit removed processing_service_name from _process_job but
missed updating the test call sites, causing "got multiple values for
argument 'device'" errors.

Co-Authored-By: Claude <noreply@anthropic.com>
@mihow
Copy link
Copy Markdown
Collaborator Author

mihow commented Apr 4, 2026

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

mihow and others added 3 commits April 4, 2026 00:17
The upstream Antenna API (RolnickLab/antenna#1197) no longer accepts
processing_service_name on GET /jobs. Remove the parameter from the
client, worker call site, mock server, and test assertions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add trailing slash to POST /tasks/ route (matches client and /result/)
- Set redirect_slashes=False on mock FastAPI app so slash mismatches
  cause 404 instead of silent redirects
- Set follow_redirects=False on all TestClient instances so redirects
  surface as test failures

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove service_name from result_posting.py docstring examples (param
  was removed in 588c186 but examples not updated)
- Remove vestigial service_name param from benchmark run_benchmark()
  and CLI arg (no longer passed to any API call)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@mihow mihow merged commit 0987099 into main Apr 4, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant