Skip to content

feat: 30.2 — unified api surface#4

Merged
vieiralucas merged 1 commit intomainfrom
feat/30.2-unified-api
Mar 25, 2026
Merged

feat: 30.2 — unified api surface#4
vieiralucas merged 1 commit intomainfrom
feat/30.2-unified-api

Conversation

@vieiralucas
Copy link
Copy Markdown
Member

@vieiralucas vieiralucas commented Mar 25, 2026

Summary

  • Update Python SDK for the unified proto API from Story 30.1
  • BatchEnqueue RPC removed; enqueue_many() replaces batch_enqueue()
  • EnqueueRequest now wraps repeated EnqueueMessage; EnqueueResponse returns repeated EnqueueResult with typed error codes
  • AckRequest/NackRequest now wrap repeated AckMessage/NackMessage with per-message results
  • ConsumeResponse only has repeated messages (singular message field removed)
  • BatchMode renamed to AccumulatorMode; BatchEnqueueResult to EnqueueResult; BatchEnqueueError to EnqueueError
  • Linger.batch_size renamed to Linger.max_messages
  • Per-message EnqueueErrorCode mapped to typed SDK exceptions (e.g. QUEUE_NOT_FOUND -> QueueNotFoundError)
  • Proto regenerated from unified service.proto; admin.proto synced

Test plan

  • 16 unit tests pass (batcher flush, accumulator modes, type constructors)
  • 15 integration tests pass against real fila-server (enqueue/consume/ack lifecycle, enqueue_many, accumulator modes, TLS, API key auth)
  • No "batch" prefix in public API

🤖 Generated with Claude Code


Summary by cubic

Aligns the Python SDK with the unified v1 gRPC API (Story 30.2): removes BatchEnqueue, adds enqueue_many(), and returns per‑message EnqueueResult with typed errors. Also simplifies consume responses and renames batching to accumulation.

  • New Features

    • Added enqueue_many(); replaces batch_enqueue() and returns list[EnqueueResult].
    • Per-message EnqueueErrorCode now maps to typed SDK exceptions (e.g., QUEUE_NOT_FOUND -> QueueNotFoundError).
    • ConsumeResponse only includes messages[] (singular message removed).
    • Ack/Nack protos now wrap repeated messages with per-message results.
    • Batching renamed to accumulation: AccumulatorMode replaces BatchMode; background AutoAccumulator/LingerAccumulator.
    • Linger.max_messages replaces Linger.batch_size.
    • Synced admin.proto; API key RPCs removed from generated stubs.
  • Migration

    • Replace batch_enqueue(...) with enqueue_many([...]) and handle list[EnqueueResult].
    • Update imports/types: BatchEnqueueResult -> EnqueueResult, BatchEnqueueError -> EnqueueError, BatchMode -> AccumulatorMode.
    • Update config: Linger.batch_size -> Linger.max_messages.
    • If you use raw protos, expect only messages[] in ConsumeResponse.

Written for commit 39a2e2e. Summary will update on new commits.

Update Python SDK for the unified proto API:
- Enqueue RPC now uses repeated EnqueueMessage/EnqueueResult
- BatchEnqueue RPC removed; enqueue_many() replaces batch_enqueue()
- Ack/Nack use repeated AckMessage/NackMessage with per-message results
- ConsumeResponse only has repeated messages field
- BatchMode renamed to AccumulatorMode, BatchEnqueueResult to EnqueueResult
- BatchEnqueueError renamed to EnqueueError
- Linger.batch_size renamed to Linger.max_messages
- Per-message error codes mapped to typed SDK exceptions
  (e.g. ENQUEUE_ERROR_CODE_QUEUE_NOT_FOUND -> QueueNotFoundError)
- All 31 tests pass (16 unit, 15 integration)
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

4 issues found across 16 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="fila/client.py">

<violation number="1" location="fila/client.py:11">
P2: Remove the unused `EnqueueError` import; with Ruff `F` rules enabled this triggers `F401` and can fail CI.</violation>
</file>

<file name="proto/fila/v1/service.proto">

<violation number="1" location="proto/fila/v1/service.proto:59">
P1: Proto field number reuse: `messages` moved from field 2 → 1, reusing the deleted `message` field's number. During a rolling deployment, an old server writing `repeated messages` on field 2 will be silently ignored by new clients reading field 1. Keep `messages` at field number 2 and reserve field 1 to maintain wire compatibility.</violation>
</file>

<file name="fila/errors.py">

<violation number="1" location="fila/errors.py:33">
P3: `EnqueueError`'s new docstring contradicts runtime behavior: per-message enqueue failures can raise `EnqueueError` via `_map_enqueue_result_error` fallback.</violation>
</file>

<file name="tests/test_batcher.py">

<violation number="1" location="tests/test_batcher.py:67">
P2: The single-flush success test became too weak by only asserting call count; it should assert the actual request content sent to `Enqueue`.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

message ConsumeResponse {
Message message = 1; // Single message (backward compatible, used when batch size is 1)
repeated Message messages = 2; // Batched messages (populated when server sends multiple at once)
repeated Message messages = 1;
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot Mar 25, 2026

Choose a reason for hiding this comment

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

P1: Proto field number reuse: messages moved from field 2 → 1, reusing the deleted message field's number. During a rolling deployment, an old server writing repeated messages on field 2 will be silently ignored by new clients reading field 1. Keep messages at field number 2 and reserve field 1 to maintain wire compatibility.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At proto/fila/v1/service.proto, line 59:

<comment>Proto field number reuse: `messages` moved from field 2 → 1, reusing the deleted `message` field's number. During a rolling deployment, an old server writing `repeated messages` on field 2 will be silently ignored by new clients reading field 1. Keep `messages` at field number 2 and reserve field 1 to maintain wire compatibility.</comment>

<file context>
@@ -6,57 +6,137 @@ import "fila/v1/messages.proto";
 message ConsumeResponse {
-  Message message = 1;           // Single message (backward compatible, used when batch size is 1)
-  repeated Message messages = 2; // Batched messages (populated when server sends multiple at once)
+  repeated Message messages = 1;
 }
 
</file context>
Suggested change
repeated Message messages = 1;
reserved 1;
repeated Message messages = 2;
Fix with Cubic

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Not applicable — the SDK proto must match the server proto, and the server already uses repeated Message messages = 1; (changed in story 30.1, commit 68e1617). Both server and SDK were updated together in the same epic. Using field 2 with reserved 1 here would create a wire mismatch with the server. Fila is pre-alpha with no rolling deployment guarantees.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Thanks for the feedback! I've saved this as a new learning to improve future reviews.

Comment thread fila/client.py
from fila.batcher import AutoBatcher, LingerBatcher
from fila.batcher import AutoAccumulator, LingerAccumulator
from fila.errors import (
EnqueueError,
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot Mar 25, 2026

Choose a reason for hiding this comment

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

P2: Remove the unused EnqueueError import; with Ruff F rules enabled this triggers F401 and can fail CI.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At fila/client.py, line 11:

<comment>Remove the unused `EnqueueError` import; with Ruff `F` rules enabled this triggers `F401` and can fail CI.</comment>

<file context>
@@ -6,15 +6,16 @@
-from fila.batcher import AutoBatcher, LingerBatcher
+from fila.batcher import AutoAccumulator, LingerAccumulator
 from fila.errors import (
+    EnqueueError,
     _map_ack_error,
-    _map_batch_enqueue_error,
</file context>
Fix with Cubic

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Fixed in aac8edc. Removed the unused EnqueueError import from client.py. Also moved MessageNotFoundError and RPCError to top-level imports (eliminating the inline imports that triggered I001).

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Thanks for the update—appreciate the cleanup!

Comment thread tests/test_batcher.py

assert fut.result(timeout=1.0) == "msg-001"
stub.Enqueue.assert_called_once_with(proto)
stub.Enqueue.assert_called_once()
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot Mar 25, 2026

Choose a reason for hiding this comment

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

P2: The single-flush success test became too weak by only asserting call count; it should assert the actual request content sent to Enqueue.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At tests/test_batcher.py, line 67:

<comment>The single-flush success test became too weak by only asserting call count; it should assert the actual request content sent to `Enqueue`.</comment>

<file context>
@@ -59,35 +53,33 @@ class TestFlushSingle:
 
         assert fut.result(timeout=1.0) == "msg-001"
-        stub.Enqueue.assert_called_once_with(proto)
+        stub.Enqueue.assert_called_once()
 
     def test_rpc_error(self) -> None:
</file context>
Suggested change
stub.Enqueue.assert_called_once()
stub.Enqueue.assert_called_once()
sent_req = stub.Enqueue.call_args.args[0]
assert len(sent_req.messages) == 1
assert sent_req.messages[0] == proto
Fix with Cubic

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Fixed in aac8edc. The test now asserts the actual request content — verifies len(sent_req.messages) == 1 and sent_req.messages[0] == proto.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Thanks for updating the test to assert the request content!

Comment thread fila/errors.py
Comment on lines +33 to 34
and do not raise this exception. This is raised only when the entire
RPC fails (e.g., network error, server unavailable).
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot Mar 25, 2026

Choose a reason for hiding this comment

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

P3: EnqueueError's new docstring contradicts runtime behavior: per-message enqueue failures can raise EnqueueError via _map_enqueue_result_error fallback.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At fila/errors.py, line 33:

<comment>`EnqueueError`'s new docstring contradicts runtime behavior: per-message enqueue failures can raise `EnqueueError` via `_map_enqueue_result_error` fallback.</comment>

<file context>
@@ -26,15 +26,31 @@ def __init__(self, code: grpc.StatusCode, message: str) -> None:
-    Individual per-message failures are reported via ``BatchEnqueueResult.error``
-    and do not raise this exception. This is raised only when the entire batch
+    Individual per-message failures are reported via ``EnqueueResult.error``
+    and do not raise this exception. This is raised only when the entire
     RPC fails (e.g., network error, server unavailable).
     """
</file context>
Suggested change
and do not raise this exception. This is raised only when the entire
RPC fails (e.g., network error, server unavailable).
and in ``enqueue_many()`` do not raise this exception. It is also used as a
fallback for per-message enqueue failures that do not map to a specific type.
Fix with Cubic

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Fixed in aac8edc. Updated the EnqueueError docstring to note that it is also used as a fallback for per-message enqueue failures that do not map to a more specific type (via _map_enqueue_result_error).

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Thanks for the feedback! I've saved this as a new learning to improve future reviews.

@vieiralucas vieiralucas merged commit 3451bb6 into main Mar 25, 2026
1 of 3 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