| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
fix(billing): stop dropping charges when prices change mid-month (#7470) ## Context `fromOrbPeriodCosts` reads one series of Orb cost buckets and throws the rest away, so a month whose prices changed part-way through is costed from only part of itself. No customer has lost a visible charge over this yet. It would take an immediate change between two paid plans on the same pricing, with usage on both sides of it — the mid-month upgrade path. The prod accounts that do split, like 25153, separate their usage prices from the growth add-on, and the page renders no fixed prices, so the figure on screen is unaffected. Both series also end at the same instant there, so which one the old code keeps is down to Orb's response order. ## Changes - Take the last bucket of every series, not one bucket overall. Each bucket in a series is a running total, so the last one covers that whole stretch. The stretches don't overlap, so adding them up gives the month. - Skip a series whose end date can't be read instead of losing the whole month to it, and report the skip so it isn't silent. Fixes [NAN-6972](https://linear.app/nango/issue/NAN-6972) ## Testing Backend only, so nothing to click in the preview. Ran the patched adapter against 25153's real prod payload: both series land, and the $270 add-on is counted instead of discarded. Tests cover a plan change splitting the month, one metric priced on both sides of it, a fixed price added later, keeping each series' last bucket, and an unreadable end date. | 7 天前 | |
feat(webapp): show existing customers what they'd pay on the new pricing (#7458) ## Context We're moving about 600 accounts to Pay-as-you-go. The email tells them what they'll pay and links here, but the page couldn't show that number. **This screen is live until the end of the month. After that most of this code goes, along with the projection endpoint.** So it reuses the existing usage table rather than adding new parts. ## Changes - The table shows two columns for the month you pick: what the current plan charges per metric, and what Pay-as-you-go would charge. - The old metrics move to a second table behind a toggle, still showing the current plan's charges. - The new figures come from ClickHouse, not Orb, which has no data for the new metrics yet. That way any month works, not just this one. - Connections use the month's running average — what Orb bills on, and what the email uses. - Rates live in `@nangohq/billing`, not on the plan. `planToApi` copies the whole plan row into its response, so a rate there would reach every browser. - You see it if you're on a retired plan with a move scheduled in Orb. Fixes [NAN-6744](https://linear.app/nango/issue/NAN-6744) ## Testing Checked against a real Orb test account for August and September: connections `$60.00` on Starter against `$23.20` on Pay-as-you-go, with the old metrics showing their own Starter charges. Tests cover each retired plan, Enterprise and the startup deal staying out, the add-on only applying to Growth, and a normal user refused the staff preview. Collapsed legacy metrics <img width="1282" height="303" alt="image" src="https://github.com/user-attachments/assets/eb8c97f4-44d8-428d-b713-783223bca9a1" /> Expanded legacy metrics <img width="1272" height="668" alt="image" src="https://github.com/user-attachments/assets/f3ef011f-607b-4826-8ba9-ec0fde952cb4" /> | 12 天前 | |
feat(billing): show per-metric charges for past months on the billing page (#7457) ## Problem Past months showed no per-metric charges even though Orb can return costs for a requested period. ## Solution - Add paired `from` and `to` dates to the period-cost endpoint and request the selected month from the billing page. - Accept closed periods only for explicit date ranges, preserving the current-period guard for ended subscriptions. - Report fixed prices separately so totals include base fees without assigning them to usage metrics. Fixes [NAN-6935](https://linear.app/nango/issue/NAN-6935) ## Testing Tested on the local stack against Orb test mode: selecting a past month showed a charge for each usage metric. Tests cover paired and invalid date ranges, closed periods, and subscriptions with only fixed prices. <img width="1264" height="473" alt="image" src="https://github.com/user-attachments/assets/cb213810-2a22-46c7-aa8a-4a44c2a5e34a" /> | 13 天前 | |
feat: billing with Lago (#3927) ## Changes - Send usage events to Lago I kept the original implementation from Thomas that allows multiple clients, which can be handy if we ever want to do some integration tests. - Only send metrics for paying accounts Lago does not reject the events, but we just we to start small ## 🧪 Tests - Go to Lago - Create a customer and assign a plan with the external id = account_id - Modify .env ``` LAGO_API_KEY=SHH FLAG_USAGE_ENABLED=true ``` - Trigger an action - ?? - Profit --------- Co-authored-by: Samuel Bodin <1637651+bodinsamuel@users.noreply.github.com> | 1 年前 | |
feat(webapp): show existing customers what they'd pay on the new pricing (#7458) ## Context We're moving about 600 accounts to Pay-as-you-go. The email tells them what they'll pay and links here, but the page couldn't show that number. **This screen is live until the end of the month. After that most of this code goes, along with the projection endpoint.** So it reuses the existing usage table rather than adding new parts. ## Changes - The table shows two columns for the month you pick: what the current plan charges per metric, and what Pay-as-you-go would charge. - The old metrics move to a second table behind a toggle, still showing the current plan's charges. - The new figures come from ClickHouse, not Orb, which has no data for the new metrics yet. That way any month works, not just this one. - Connections use the month's running average — what Orb bills on, and what the email uses. - Rates live in `@nangohq/billing`, not on the plan. `planToApi` copies the whole plan row into its response, so a rate there would reach every browser. - You see it if you're on a retired plan with a move scheduled in Orb. Fixes [NAN-6744](https://linear.app/nango/issue/NAN-6744) ## Testing Checked against a real Orb test account for August and September: connections `$60.00` on Starter against `$23.20` on Pay-as-you-go, with the old metrics showing their own Starter charges. Tests cover each retired plan, Enterprise and the startup deal staying out, the add-on only applying to Growth, and a normal user refused the staff preview. Collapsed legacy metrics <img width="1282" height="303" alt="image" src="https://github.com/user-attachments/assets/eb8c97f4-44d8-428d-b713-783223bca9a1" /> Expanded legacy metrics <img width="1272" height="668" alt="image" src="https://github.com/user-attachments/assets/f3ef011f-607b-4826-8ba9-ec0fde952cb4" /> | 12 天前 | |
chore: batch billing events (#4086) The batching happens in memory and events are sent on an interval (or when maxBatchSize is reached) in order to avoid sending too many individual events Tested in staging <!-- Summary by @propel-code-bot --> --- **Batch Billing Events for Efficient Ingestion and Shutdown Safety** This PR introduces batching for billing events, adding an in-memory batching layer (Batcher) to the billing subsystem. Rather than sending events individually, events are now accumulated and dispatched in batches either when a max batch size is reached or at a periodic interval. The implementation covers batch retry logic, queue limits, error handling, graceful shutdown to ensure no events are lost, integration into the main server and persist app shutdown, updated environment/configuration, and test coverage for the new batch logic. **Key Changes:** • Introduces a generic Batcher class to queue, batch, flush, and retry event processing. • Integrates the Batcher into the Billing class (replacing immediate `sendAll`/send methods with add/`addAll` and batch processing). • Configures batching parameters (batch size, flush interval, queue length, retry count) via environment variables. • Ensures clean shutdown of the batcher in both server and persist processes, draining any queued events. • Converts all billing event calls from immediate sending to use the new batching model throughout the codebase (persist, server, crons). • Adds comprehensive unit tests for the Batcher logic and updates `devDependencies`. • Adds a simple logger utility for the billing package. **Affected Areas:** • packages/billing/lib/batcher.ts (new batching implementation) • packages/billing/lib/billing.ts (Batcher integration) • packages/billing/lib/batcher.unit.test.ts (unit tests) • packages/billing/lib/logger.ts (new file) • packages/billing/package.json (test deps) • packages/utils/lib/environment/parse.ts (new env vars) • packages/persist/lib/app.ts (shutdown handling) • packages/persist/lib/records.ts (billing method usage update) • packages/server/lib/server.ts (shutdown handling) • packages/server/lib/crons/usage.ts (billing usage export update) • packages/server/lib/controllers/sync.controller.ts (billing method usage update) **Potential Impact:** **Functionality**: Improves system efficiency by reducing API calls for billing, introduces event queueing with retry/discard safeguards, and provides consistent, loss-tolerant shutdown. **Performance**: Should decrease network/API overhead due to fewer, larger batch sends. Some latency introduced in billing event submission (now asynchronous/batched). **Security**: No direct impact, though batching must avoid data loss/corruption (tests provided for edge cases). **Scalability**: System should better withstand bursty or high-volume billing traffic; tunable limits guard against runaway memory usage. **Review Focus:** • Concurrency and data loss: Ensure no race conditions in batched flush, shutdown, or queue mutation. • Queue and memory limits: Guard rails are correct and errors for discards are handled. • Integration: Ensure all historic send/`sendAll` sites now use the new add/`addAll` path. • Test completeness: All major Batcher behaviors (failure, retry, timeout, shutdown, interval) are well-covered. <details> <summary><strong>Testing Needed</strong></summary> • Verify correct configuration of batching parameters through env vars. • End-to-end test: generate high billing event volume, stop/start servers, and verify all events are counted (no loss on shutdown). • Simulate process failure during batching to ensure retries/discards behave as expected. • Run existing billing-related flows (persist, server) to confirm no regression. </details> <details> <summary><strong>Code Quality Assessment</strong></summary> **packages/billing/lib/batcher.ts**: Well-structured, generic design with robust queue/retry/flush logic; clear error and race condition handling. **packages/billing/lib/batcher.unit.test.ts**: Comprehensive test coverage for all batching edge cases. **packages/billing/lib/billing.ts**: Clean refactor to async batching, well-logged failure handling. **other files**: Minimal and systematic updates for API/usage change; safe modifications. </details> <details> <summary><strong>Best Practices</strong></summary> **Concurrency**: • Clean timer/interval management • Safe flush and shutdown sequencing **Test Coverage**: • Extensive unit tests for all Batcher paths **Configuration**: • Env-based tuning for batch parameters **Logging**: • Clear logs on batch send, error, and shutdown </details> <details> <summary><strong>Possible Issues</strong></summary> • Potential for out-of-order dispatch or missed flush in highly concurrent or rapid shutdown scenarios. • If the process dies abruptly (not clean shutdown), queued events may be lost. • Care must be taken to monitor memory usage if event rate exceeds ingest capacity (limits help). </details> --- *This summary was automatically generated by @propel-code-bot* | 1 年前 | |
fix(billing): sync data with orb and stripe (#4517) ## Changes fixes https://linear.app/nango/issue/NAN-3655/stripe-to-orb-data-syncing - Sync data with orb and stripe When changing team name, and correctly replicate billing address <!-- Summary by @propel-code-bot --> --- **Synchronize Team Data Changes with Stripe and Orb, Add Parallel Billing Updates and Event-Driven Processing** This PR introduces a robust, event-driven workflow to synchronize team data (specifically, team name changes and billing address) between Stripe and Orb billing providers. It adds a new event type ('team.updated'), a processor to handle these updates asynchronously, and expands the billing client abstraction with an 'updateCustomer' method implemented for Orb. The Stripe and Orb updates now occur in parallel via a pubsub event queue, with improved error handling and clearer separation of which fields are synchronized during webhook and manual updates. Several interfaces, controllers, and workflow steps are updated to ensure consistency, observability and resilience of billing data syncing. <details> <summary><strong>Key Changes</strong></summary> • Introduced a pubsub-based event (`team.updated`) and Team event processor for handling updates originating from team name change actions. • Expanded `BillingClient` interface to include `updateCustomer`; implemented `updateCustomer` for the Orb billing provider. • Modified `putTeam` controller to emit team.updated events after local account updates; triggers the new Team processor to sync updates to Stripe and Orb in parallel. • Added robust error handling and logging around third-party billing provider update failures to avoid failing the core operation. • Refactored Stripe payment and webhook flows: Stripe customers are now created with the team name property; webhook synchronization for payment methods now only updates the billing address (not name), reducing accidental overwrites. • Centralized Stripe ``SDK`` import/export to the billing package, simplifying shared usage across server code. • Type definitions and all dependent controller code updated to match new billing client capabilities. • Removed direct billing provider updates from controllers in favor of event-driven, retry-friendly pattern. </details> <details> <summary><strong>Affected Areas</strong></summary> • Team update controller and related ``API`` endpoints (`putTeam`.ts) • Billing client abstraction and Orb implementation (`BillingClient`, orb.ts, billing.ts) • Stripe payment collection and webhook processing (`postCollectPayment`.ts, `postWebhooks`.ts) • Pubsub/event system (event.ts, new team processor) • Billing-related types and type declarations • Application composition/startup (metering/app.ts) • Package dependencies and exports (billing package.json, index.ts, stripe.ts) </details> --- *This summary was automatically generated by @propel-code-bot* | 1 年前 |