Skip to content

feat(payment): clickhouse and dual querying - #35

Merged
SteakFisher merged 2 commits into
mainfrom
feat/payment_clickhouse
May 13, 2026
Merged

feat(payment): clickhouse and dual querying#35
SteakFisher merged 2 commits into
mainfrom
feat/payment_clickhouse

Conversation

@SteakFisher

@SteakFisher SteakFisher commented May 13, 2026

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • New Features

    • Full PAYMENT event support: capture, store, query, aggregate, and price PAYMENT events.
    • Added creditAmount as a queryable field for filtering, aggregation, and reporting.
    • PAYMENT events now appear in analytics and multi-table query paths.
  • Bug Fixes

    • Consolidated PAYMENT pricing logic into a shared implementation and updated storage routing to use the ClickHouse path for PAYMENT.
  • Chores

    • Updated proto submodule pointer.

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 13, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Adds PAYMENT event support: ClickHouse payment_events schema and migration, ClickHouse insertion handler and query mappings, Postgres query mapping updates, adapter routing to ClickHouse, and shared PAYMENT pricing logic that sums SDK and AI prices.

Changes

PAYMENT Event Type Storage

Layer / File(s) Summary
Proto submodule update
proto
Submodule pointer updated to a new commit.
Storage interface and adapter routing
src/interface/storage/Storage.ts, src/factory/EventStorageAdapterFactory.ts
QUERY_FIELD_NAMES adds creditAmount; getEventStorageAdapter now routes PAYMENT to ClickHouseAdapter and removes Postgres adapter import.
ClickHouse schema and migrations
src/storage/adapter/clickhouse/schema.ts
Adds payment_events table definition and ensures it is created during migrations.
ClickHouse payment insertion
src/storage/adapter/clickhouse/handlers/addPayment.ts, src/storage/adapter/clickhouse/handlers/index.ts
Adds handleAddPayment: validates creditAmount and timestamps, generates UUID, inserts into payment_events, wraps errors with StorageError, and is re-exported.
ClickHouse adapter payment handling
src/storage/adapter/clickhouse/ClickHouseAdapter.ts, src/storage/adapter/clickhouse/handlers/priceRequestPayment.ts
Imports new handlers; add() routes PAYMENT to handleAddPayment; price() routes PAYMENT to handlePriceRequestPayment; priceRequestPayment re-exported from common implementation.
ClickHouse payment event querying
src/storage/adapter/clickhouse/handlers/queryEvents.ts
Adds creditAmount to sdk_call_events map, defines payment_events field map including creditAmount, extends CH_PARAM_TYPE with Int64, includes payment_events in table routing/default set, and maps aggregation groupBy=eventType to emit PAYMENT.
Postgres payment event querying
src/storage/adapter/postgres/handlers/queryEvents.ts
Imports paymentEventsTable; adds PAYMENT to internal EventTypeName; defines PAYMENT field mapping with creditAmount; adds SDK_CALL creditAmount mapping to NULL; updates getEventTypes and getSubtypeTable to recognize PAYMENT.
Shared PAYMENT pricing
src/storage/adapter/common/priceRequestPayment.ts, src/storage/adapter/postgres/handlers/priceRequestPayment.ts
Adds handlePriceRequestPayment(userId, beforeTimestamp) that queries SDK and AI prices, validates numeric results, sums them, and normalizes errors; Postgres/ClickHouse adapter files re-export this shared implementation.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 Hopping through schemas, a payment takes flight,
ClickHouse holds numbers by moonlit night,
Handlers and queries now dance in a line,
Credit amounts stored, summed neat and fine —
A rabbit's small cheer for code done right.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(payment): clickhouse and dual querying' directly and clearly describes the main changes: adding PAYMENT event support to ClickHouse storage adapter and enabling dual-storage querying across both adapters.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ 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 feat/payment_clickhouse

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/storage/adapter/clickhouse/handlers/queryEvents.ts (1)

290-290: ⚡ Quick win

Prefer explicit table-to-eventType mapping over chained ternaries.

The nested ternary assumes exactly three tables and will default to PAYMENT for any unrecognized table name. Consider using a lookup object or switch statement for clearer intent and safer future maintenance.

♻️ Proposed refactor using a lookup map

Define a constant at the top of the file:

+const TABLE_TO_EVENT_TYPE: Record<string, string> = {
+  sdk_call_events: "SDK_CALL",
+  ai_token_usage_events: "AI_TOKEN_USAGE",
+  payment_events: "PAYMENT",
+};

Then replace the ternary:

-          `'${t === "sdk_call_events" ? "SDK_CALL" : t === "ai_token_usage_events" ? "AI_TOKEN_USAGE" : "PAYMENT"}' as group_value`
+          `'${TABLE_TO_EVENT_TYPE[t] ?? "UNKNOWN"}' as group_value`
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/storage/adapter/clickhouse/handlers/queryEvents.ts` at line 290, Replace
the nested ternary that produces group_value (the expression using t ===
"sdk_call_events" ? "SDK_CALL" : ...) with a clear lookup map (e.g.,
TABLE_TO_EVENT_TYPE) defined at the top of the module and use
TABLE_TO_EVENT_TYPE[t] (with a safe default or explicit error) to produce the
group_value; update any references in queryEvents.ts that use the variable t to
use the lookup result so adding new tables is simple and avoids silently
defaulting to "PAYMENT".
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/storage/adapter/clickhouse/ClickHouseAdapter.ts`:
- Line 16: Remove the cross-adapter import of handlePriceRequestPayment from the
Postgres handlers and instead create a ClickHouse-specific handler module under
src/storage/adapter/clickhouse/handlers/ (e.g., priceRequestPayment.ts) that
implements the same interface/behavior used by ClickHouseAdapter; then update
ClickHouseAdapter to import handlePriceRequestPayment from the new clickhouse
handlers module, keeping the existing call sites and factory usage unchanged
(reference symbols: handlePriceRequestPayment, ClickHouseAdapter).

---

Nitpick comments:
In `@src/storage/adapter/clickhouse/handlers/queryEvents.ts`:
- Line 290: Replace the nested ternary that produces group_value (the expression
using t === "sdk_call_events" ? "SDK_CALL" : ...) with a clear lookup map (e.g.,
TABLE_TO_EVENT_TYPE) defined at the top of the module and use
TABLE_TO_EVENT_TYPE[t] (with a safe default or explicit error) to produce the
group_value; update any references in queryEvents.ts that use the variable t to
use the lookup result so adding new tables is simple and avoids silently
defaulting to "PAYMENT".
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: fe1cca8c-497f-43b7-833f-f138820fc30a

📥 Commits

Reviewing files that changed from the base of the PR and between 146b104 and 6ecef3d.

📒 Files selected for processing (9)
  • proto
  • src/factory/EventStorageAdapterFactory.ts
  • src/interface/storage/Storage.ts
  • src/storage/adapter/clickhouse/ClickHouseAdapter.ts
  • src/storage/adapter/clickhouse/handlers/addPayment.ts
  • src/storage/adapter/clickhouse/handlers/index.ts
  • src/storage/adapter/clickhouse/handlers/queryEvents.ts
  • src/storage/adapter/clickhouse/schema.ts
  • src/storage/adapter/postgres/handlers/queryEvents.ts

Comment thread src/storage/adapter/clickhouse/ClickHouseAdapter.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/storage/adapter/common/priceRequestPayment.ts (1)

6-62: ⚡ Quick win

Add operation logging for payment price calculation flow.

Please log success/failure with operation name and context for this handler path.

As per coding guidelines, Use logger from errors/logger with logOperationInfo and logOperationError; include operation name and context.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/storage/adapter/common/priceRequestPayment.ts` around lines 6 - 62, The
handler handlePriceRequestPayment is missing operation logging: import
logOperationInfo and logOperationError from errors/logger, then add
logOperationInfo at the start (operation: "handlePriceRequestPayment", context:
{ userId, beforeTimestamp }) and another logOperationInfo on successful
completion before returning totalPrice with context { userId, beforeTimestamp,
sdkPrice, aiPrice, totalPrice }; in the catch block call logOperationError with
the same operation name and include the error and context (userId,
beforeTimestamp) before rethrowing (preserve existing StorageError throws and
still wrap non-StorageError errors via StorageError.priceCalculationFailed).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/storage/adapter/common/priceRequestPayment.ts`:
- Around line 23-24: The current validation uses typeof + isNaN (e.g., if
(typeof sdkPrice !== "number" || isNaN(sdkPrice))) which accepts
Infinity/-Infinity; replace those checks with Number.isFinite(sdkPrice) (i.e.,
if (!Number.isFinite(sdkPrice)) throw StorageError.priceCalculationFailed(...))
and do the same replacement for the other price validation site in the same
module so both sdkPrice and the other price variable use Number.isFinite().
- Around line 48-53: Create a typed user-defined type guard to replace the `(e
as any)` cast in the catch logic: add a function like `isStorageError(e:
unknown): e is StorageError` that checks `e !== null`, `typeof e === "object"`,
`'type' in e`, and `'name' in e && typeof (e as { name?: unknown }).name ===
"string" && (e as { name: string }).name === "StorageError"`, then use `if
(isStorageError(e)) { ... }` in the catch block instead of the current `(e as
any)` pattern so the error narrowing is strict and no `any` is used.

---

Nitpick comments:
In `@src/storage/adapter/common/priceRequestPayment.ts`:
- Around line 6-62: The handler handlePriceRequestPayment is missing operation
logging: import logOperationInfo and logOperationError from errors/logger, then
add logOperationInfo at the start (operation: "handlePriceRequestPayment",
context: { userId, beforeTimestamp }) and another logOperationInfo on successful
completion before returning totalPrice with context { userId, beforeTimestamp,
sdkPrice, aiPrice, totalPrice }; in the catch block call logOperationError with
the same operation name and include the error and context (userId,
beforeTimestamp) before rethrowing (preserve existing StorageError throws and
still wrap non-StorageError errors via StorageError.priceCalculationFailed).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 54666d90-704e-4009-8d58-3b5b604609ef

📥 Commits

Reviewing files that changed from the base of the PR and between 6ecef3d and 29860ae.

📒 Files selected for processing (5)
  • src/storage/adapter/clickhouse/ClickHouseAdapter.ts
  • src/storage/adapter/clickhouse/handlers/index.ts
  • src/storage/adapter/clickhouse/handlers/priceRequestPayment.ts
  • src/storage/adapter/common/priceRequestPayment.ts
  • src/storage/adapter/postgres/handlers/priceRequestPayment.ts
✅ Files skipped from review due to trivial changes (1)
  • src/storage/adapter/clickhouse/handlers/priceRequestPayment.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/storage/adapter/clickhouse/handlers/index.ts
  • src/storage/adapter/clickhouse/ClickHouseAdapter.ts

Comment thread src/storage/adapter/common/priceRequestPayment.ts
Comment thread src/storage/adapter/common/priceRequestPayment.ts
@SteakFisher
SteakFisher force-pushed the feat/payment_clickhouse branch from b6d6984 to 29860ae Compare May 13, 2026 18:12
@SteakFisher
SteakFisher merged commit bcdd6f2 into main May 13, 2026
5 checks passed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/storage/adapter/common/priceRequestPayment.ts`:
- Around line 30-39: Remove the corrupted validation block that references
aiPrice before it's declared and contains orphaned lines for sdkPrice;
specifically delete the early Number.isFinite(aiPrice) check and the stray lines
that look like a partial throw StorageError.priceCalculationFailed(...) so only
the proper aiPrice validation (the existing check around aiPrice assigned later)
remains; ensure no leftover orphaned references to aiPrice or sdkPrice exist and
that only the correct StorageError.priceCalculationFailed(...) usages remain.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 68db90ae-3779-475a-a22e-d3f15779ade0

📥 Commits

Reviewing files that changed from the base of the PR and between 29860ae and b6d6984.

📒 Files selected for processing (1)
  • src/storage/adapter/common/priceRequestPayment.ts

Comment on lines +30 to +39
if (!Number.isFinite(aiPrice)) {
throw StorageError.priceCalculationFailed(
userId,
new Error(`Invalid AI price value returned: ${aiPrice}`)
);
}
userId,
new Error(`Invalid SDK price value returned: ${sdkPrice}`)
);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Critical: Corrupted code block breaks compilation and references undefined variable.

Lines 30-39 contain two problems causing CI failures:

  1. aiPrice is referenced on line 30 before it's declared on line 43
  2. Lines 36-39 are orphaned code fragments (missing the throw StorageError.priceCalculationFailed( prefix)

This entire block must be removed. The aiPrice validation already exists at lines 49-54 after aiPrice is properly assigned.

🐛 Proposed fix: Remove corrupted lines
     if (!Number.isFinite(sdkPrice)) {
       throw StorageError.priceCalculationFailed(
         userId,
         new Error(`Invalid SDK price value returned: ${sdkPrice}`)
       );
     }
-    
-    if (!Number.isFinite(aiPrice)) {
-      throw StorageError.priceCalculationFailed(
-        userId,
-        new Error(`Invalid AI price value returned: ${aiPrice}`)
-      );
-    }
-        userId,
-        new Error(`Invalid SDK price value returned: ${sdkPrice}`)
-      );
-    }

     const aiAdapter =
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (!Number.isFinite(aiPrice)) {
throw StorageError.priceCalculationFailed(
userId,
new Error(`Invalid AI price value returned: ${aiPrice}`)
);
}
userId,
new Error(`Invalid SDK price value returned: ${sdkPrice}`)
);
}
if (!Number.isFinite(sdkPrice)) {
throw StorageError.priceCalculationFailed(
userId,
new Error(`Invalid SDK price value returned: ${sdkPrice}`)
);
}
const aiAdapter =
🧰 Tools
🪛 Biome (2.4.15)

[error] 38-38: Expected a statement but instead found ')'.

(parse)

🪛 GitHub Actions: Run Tests / 0_Test.txt

[error] 38-38: TypeScript (TS1128): Declaration or statement expected.

🪛 GitHub Actions: Run Tests / Test

[error] 38-38: TypeScript error TS1128: Declaration or statement expected.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/storage/adapter/common/priceRequestPayment.ts` around lines 30 - 39,
Remove the corrupted validation block that references aiPrice before it's
declared and contains orphaned lines for sdkPrice; specifically delete the early
Number.isFinite(aiPrice) check and the stray lines that look like a partial
throw StorageError.priceCalculationFailed(...) so only the proper aiPrice
validation (the existing check around aiPrice assigned later) remains; ensure no
leftover orphaned references to aiPrice or sdkPrice exist and that only the
correct StorageError.priceCalculationFailed(...) usages remain.

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