Send subscription.updated when the meter period advances

Merged
PI
16d ago
+30-0

Summary

Related Issue: none

cycle_meters moves current_meter_period_start / current_meter_period_end forward without emitting subscription.updated. As a result, webhook consumers keep a stale meter period.

What

  • cycle_meters now calls _after_subscription_updated once the meter clock has advanced. It does this on both paths:
    • Active: after settlement, the meter reset and the credit re-grant.
    • Frozen (inactive, e.g. past_due): after the clock advances, with nothing settled or reset.
  • Tests in TestCycleMeters now assert that subscription.updated is sent once on both paths. The active-path test also asserts that customer.state_changed is enqueued.

Why

The billing cycle already sends subscription.updated through SubscriptionUpdateContext, so the meter period was only stale when it advanced on its own (meter interval shorter than the billing interval).

How

The status doesn't change at a meter boundary. So _after_subscription_updated (called with the current status as the previous status) only sends the subscription.updated webhook and enqueues customer.state_changed. The second one is useful too, since meters were just reset.

Behaviour change: merchants whose meter interval is shorter than their billing interval now receive one extra subscription.updated per meter period.

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 (the new assertions fail without the fix)
  • Linting and type checking pass (ruff and mypy on the changed files; tests/subscription passes, 495 tests)
  • No unrelated changes or drive-by fixes are included

๐Ÿค– Generated with Claude Code

https://claude.ai/code/session_018HHcDPUBuyzYF2BrPiqMzM


Generated by Claude Code