Add ClickHouse-backed metered credit cap enforcement (#19586)
## Summary Implements a ClickHouse-backed polling system to enforce metered-credit caps for workflow executions, replacing reliance on Stripe billing alerts. The system re-evaluates tier caps against live pricing on every poll cycle, allowing price/tier changes to propagate immediately without recreating Stripe alert objects. ## Key Changes - **BillingUsageCapService**: New service that queries ClickHouse for current-period credit usage and evaluates whether a subscription has reached its metered-credit allowance (tier cap + credit balance) - `isClickHouseEnabled()`: Checks if ClickHouse is configured - `getCurrentPeriodCreditsUsed()`: Sums creditsUsedMicro from usageEvent table for a workspace within a billing period - `evaluateCap()`: Determines if usage has reached the allowance by reading live pricing from the subscription - **EnforceUsageCapJob**: Cron job that polls all active subscriptions and updates `hasReachedCurrentPeriodCap` on metered items - Runs every 2 minutes to keep cap enforcement in sync with live usage - Supports shadow mode (log-only) via `BILLING_USAGE_CAP_CLICKHOUSE_ENABLED` flag for safe rollout - Continues processing after per-subscription errors with detailed logging - **EnforceUsageCapCronCommand**: CLI command to register the enforcement cron job - **MeteredCreditService**: Extracted `extractMeteredPricingInfoFromSubscription()` as a pure function for callers that already hold the subscription with pricing loaded, avoiding redundant DB queries - **Configuration**: Added `BILLING_USAGE_CAP_CLICKHOUSE_ENABLED` flag to control enforcement mode (active vs. shadow) - **Constants**: Added `METERED_OPERATION_TYPES` to define which operation types count toward the metered product's credit cap ## Implementation Details - The service queries ClickHouse for the sum of `creditsUsedMicro` in the current billing period, matching Stripe meter semantics - Pricing is re-read on every evaluation, so tier changes propagate within one poll cycle without Stripe alert recreation - The cron job only updates the database when the cap state actually changes (no-op if already in the correct state) - Shadow mode allows safe validation before enabling enforcement; transitions are logged but not persisted - Comprehensive test coverage for both the service and cron job, including error handling and state transitions https://claude.ai/code/session_01VksTSrYLXJVCPVBQhQdBTe --------- Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
+2
@@ -7,6 +7,7 @@ import { AddPermissionFlagRoleIdIndexFastInstanceCommand } from 'src/database/co
|
||||
import { AddWorkspaceIdToIndirectEntitiesFastInstanceCommand } from 'src/database/commands/upgrade-version-command/1-22/1-22-instance-command-fast-1775758621017-add-workspace-id-to-indirect-entities';
|
||||
import { AddWorkspaceIdIndexesAndFksFastInstanceCommand } from 'src/database/commands/upgrade-version-command/1-22/1-22-instance-command-fast-1775761294897-add-workspace-id-indexes-and-fks-to-indirect-entities';
|
||||
import { DropObjectMetadataDataSourceFkFastInstanceCommand } from 'src/database/commands/upgrade-version-command/1-22/1-22-instance-command-fast-1775804361516-drop-object-metadata-data-source-fk';
|
||||
import { AddCreditBalanceToBillingCustomerFastInstanceCommand } from 'src/database/commands/upgrade-version-command/1-22/1-22-instance-command-fast-1776078919203-add-credit-balance-to-billing-customer';
|
||||
import { BackfillWorkspaceIdOnIndirectEntitiesSlowInstanceCommand } from 'src/database/commands/upgrade-version-command/1-22/1-22-instance-command-slow-1775758621018-backfill-workspace-id-on-indirect-entities';
|
||||
import { DropWorkspaceVersionColumnFastInstanceCommand } from 'src/database/commands/upgrade-version-command/1-23/1-23-instance-command-fast-1785000000000-drop-workspace-version-column';
|
||||
|
||||
@@ -19,5 +20,6 @@ export const INSTANCE_COMMANDS = [
|
||||
BackfillWorkspaceIdOnIndirectEntitiesSlowInstanceCommand,
|
||||
AddWorkspaceIdIndexesAndFksFastInstanceCommand,
|
||||
DropObjectMetadataDataSourceFkFastInstanceCommand,
|
||||
AddCreditBalanceToBillingCustomerFastInstanceCommand,
|
||||
DropWorkspaceVersionColumnFastInstanceCommand,
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user