Skip to content

outpost: send reducer bucket totals over the WebSocket - #15411

Merged
maximevast merged 13 commits into
mainfrom
maxime/outpost-reducer-bucket-event
Oct 14, 2026
Merged

maximevast merged 13 commits into
mainfrom
maxime/outpost-reducer-bucket-event

Conversation

@maximevast

@maximevast maximevast commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Related Issue: #

What

Why

How

Checklist

  • This PR addresses a single concern (one bug fix, one feature, one refactor)
  • The diff is reasonably sized and easy to review
  • New functionality is covered by tests
  • Linting and type checking pass (uv run task lint && uv run task lint_types)
  • No unrelated changes or drive-by fixes are included

View guided diff Turn on auto-fix

@vercel

vercel Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
orbit Ready Ready Preview Oct 14, 2026 8:30am UTC
polar-test Ready Ready Preview Oct 14, 2026 8:30am UTC

Request Review

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

1 issue found across 9 files

Confidence score: 3/5

  • In server/polar/outpost/service.py, get_intervals passes UUID strings from Redis to UUID columns, which asyncpg cannot encode and can make the query fail. Parse the UUID fields before querying.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="server/polar/outpost/service.py">

<violation number="1" location="server/polar/outpost/service.py:145">
P1: The Redis event contains UUIDs as strings, but `get_intervals` binds `reducer_id` and `customer_id` against UUID columns; asyncpg cannot encode those strings as UUID parameters. Parse the UUID fields before querying so reducer-bucket events can be delivered.</violation>
</file>

Reply with feedback, questions, or to request a fix.

View guided diff | Turn on auto-fix | Re-trigger cubic

Comment thread server/polar/outpost/service.py Outdated
repository = ReducerBucketRepository.from_session(session)
intervals = await repository.get_intervals(
organization.id,
event["reducer_id"],

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1: The Redis event contains UUIDs as strings, but get_intervals binds reducer_id and customer_id against UUID columns; asyncpg cannot encode those strings as UUID parameters. Parse the UUID fields before querying so reducer-bucket events can be delivered.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At server/polar/outpost/service.py, line 145:

<comment>The Redis event contains UUIDs as strings, but `get_intervals` binds `reducer_id` and `customer_id` against UUID columns; asyncpg cannot encode those strings as UUID parameters. Parse the UUID fields before querying so reducer-bucket events can be delivered.</comment>

<file context>
@@ -120,5 +131,37 @@ async def _send_customer_meter(
+        repository = ReducerBucketRepository.from_session(session)
+        intervals = await repository.get_intervals(
+            organization.id,
+            event["reducer_id"],
+            bucket_start,
+            bucket_start + REDUCER_BUCKET_SIZE,
</file context>

Comment thread server/polar/reducer_bucket/service.py Outdated

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

0 issues found across 6 files (changes from recent commits).

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Requires human review: Auto-approval blocked by 1 unresolved issue from previous reviews.

View guided diff | Turn on auto-fix | Re-trigger cubic

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

1 issue found across 11 files (changes from recent commits).

Confidence score: 3/5

  • get_unsealed_totals in server/polar/outpost/service.py can omit current Redis-only buckets from WebSocket updates until reducer_bucket.sync runs. Include those pending buckets when calculating totals.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="server/polar/outpost/service.py">

<violation number="1" location="server/polar/outpost/service.py:178">
P2: `get_unsealed_totals` reads only PostgreSQL, while current buckets remain only in Redis until the delayed `reducer_bucket.sync` runs. Customer-meter updates publish this event during that window, so WebSocket messages omit active-bucket usage; include those Redis values before sending.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

View guided diff | Turn on auto-fix | Re-trigger cubic


count, total, minimum, maximum = await ReducerBucketRepository.from_session(
session
).get_unsealed_totals(organization.id, reducer.id, identities)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2: get_unsealed_totals reads only PostgreSQL, while current buckets remain only in Redis until the delayed reducer_bucket.sync runs. Customer-meter updates publish this event during that window, so WebSocket messages omit active-bucket usage; include those Redis values before sending.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At server/polar/outpost/service.py, line 178:

<comment>`get_unsealed_totals` reads only PostgreSQL, while current buckets remain only in Redis until the delayed `reducer_bucket.sync` runs. Customer-meter updates publish this event during that window, so WebSocket messages omit active-bucket usage; include those Redis values before sending.</comment>

<file context>
@@ -152,30 +128,84 @@ async def _send_reducer_bucket(
+
+        count, total, minimum, maximum = await ReducerBucketRepository.from_session(
+            session
+        ).get_unsealed_totals(organization.id, reducer.id, identities)
+        # Temporary: credits come from customer meters until credits are reducers.
+        # Credits reset on renewal before the billed usage gets sealed, so balances
</file context>

…r-bucket-event

# Conflicts:
#	server/tests/reducer_bucket/test_service.py
@maximevast
maximevast added this pull request to the merge queue Oct 14, 2026
Merged via the queue into main with commit cdba1da Oct 14, 2026
31 of 32 checks passed
@maximevast
maximevast deleted the maxime/outpost-reducer-bucket-event branch October 14, 2026 08:38

This branch was successfully deployed

2 active deployments
Preview – polar-test — f645109e Deployed Oct 14, 2026 by vercel[bot]
Preview – orbit — f645109e Deployed Oct 14, 2026 by vercel[bot]
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.

2 participants