memory

package
v1.9.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 3, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Store

type Store struct {
	// contains filtered or unexported fields
}

func New

func New() *Store

func (*Store) AdvanceSubscriptionPeriod

func (s *Store) AdvanceSubscriptionPeriod(_ context.Context, subID id.SubscriptionID, from, start, end, now time.Time) (bool, error)

func (*Store) Aggregate

func (s *Store) Aggregate(_ context.Context, tenantID, appID, featureKey string, period plan.Period) (int64, error)

func (*Store) AggregateMulti

func (s *Store) AggregateMulti(ctx context.Context, tenantID, appID string, featureKeys []string, period plan.Period) (map[string]int64, error)

func (*Store) ApplyCoupon

func (s *Store) ApplyCoupon(_ context.Context, subID id.SubscriptionID, couponID id.CouponID) error

ApplyCoupon is a low-level operation kept for callers and tests that need it separately. Engine code redeems through RedeemCoupon, which records the application and increments the redemption count as one unit.

func (*Store) ArchiveFeature

func (s *Store) ArchiveFeature(_ context.Context, featureID id.FeatureID) error

func (*Store) ArchivePlan

func (s *Store) ArchivePlan(_ context.Context, planID id.PlanID) error

func (*Store) CancelSubscription

func (s *Store) CancelSubscription(_ context.Context, subID id.SubscriptionID, immediately bool) (time.Time, error)

func (*Store) ChangeSubscriptionPlan

func (s *Store) ChangeSubscriptionPlan(_ context.Context, subID id.SubscriptionID, planID id.PlanID, quantity map[string]int64) (bool, error)

func (*Store) Close

func (s *Store) Close() error

func (*Store) CreateCoupon

func (s *Store) CreateCoupon(_ context.Context, c *coupon.Coupon) error

Coupon Store implementation

Every method below that crosses this store's boundary - in either direction - copies the coupon.Coupon value rather than sharing a pointer. CreateCoupon and UpdateCoupon copy the caller's coupon before storing it, and GetCoupon, GetCouponByID, ListCoupons and ListAppliedCoupons copy the stored coupon before handing it back. Once a *coupon.Coupon crosses in or out, this store never touches the fields of that specific object again - it only ever mutates its own internal copies, under s.mu. This is what makes it safe for a caller to read fields off a coupon obtained from Get without holding any lock, even while RedeemCoupon or IncrementCouponRedemptions is concurrently updating the same coupon on another goroutine: Ledger.ApplyCoupon's fast-path exhaustion check does exactly this, and a -race run over concurrent ApplyCoupon calls caught it as a real data race before these methods copied on every crossing.

func (*Store) CreateFeature

func (s *Store) CreateFeature(_ context.Context, f *feature.Feature) error

Feature catalog Store implementation

func (*Store) CreateInvoice

func (s *Store) CreateInvoice(_ context.Context, inv *invoice.Invoice) error

Invoice Store implementation

func (*Store) CreatePlan

func (s *Store) CreatePlan(_ context.Context, p *plan.Plan) error

Plan Store implementation

func (*Store) CreateSubscription

func (s *Store) CreateSubscription(_ context.Context, sub *subscription.Subscription) error

Subscription Store implementation

func (*Store) DeleteCoupon

func (s *Store) DeleteCoupon(_ context.Context, couponID id.CouponID) error

func (*Store) DeleteFeature

func (s *Store) DeleteFeature(_ context.Context, featureID id.FeatureID) error

func (*Store) DeletePlan

func (s *Store) DeletePlan(_ context.Context, planID id.PlanID) error

func (*Store) EnactSubscriptionCancel

func (s *Store) EnactSubscriptionCancel(_ context.Context, subID id.SubscriptionID, now time.Time) (bool, error)

func (*Store) EndSubscriptionTrial

func (s *Store) EndSubscriptionTrial(_ context.Context, subID id.SubscriptionID, now time.Time) (bool, error)

func (*Store) GetActiveSubscription

func (s *Store) GetActiveSubscription(_ context.Context, tenantID, appID string) (*subscription.Subscription, error)

func (*Store) GetCached

func (s *Store) GetCached(_ context.Context, tenantID, appID, featureKey string) (*entitlement.Result, error)

Entitlement Store implementation

func (*Store) GetCoupon

func (s *Store) GetCoupon(_ context.Context, code, appID string) (*coupon.Coupon, error)

func (*Store) GetCouponByID

func (s *Store) GetCouponByID(_ context.Context, couponID id.CouponID) (*coupon.Coupon, error)

func (*Store) GetFeature

func (s *Store) GetFeature(_ context.Context, featureID id.FeatureID) (*feature.Feature, error)

func (*Store) GetFeatureByKey

func (s *Store) GetFeatureByKey(_ context.Context, key, appID string) (*feature.Feature, error)

func (*Store) GetInvoice

func (s *Store) GetInvoice(_ context.Context, invID id.InvoiceID) (*invoice.Invoice, error)

func (*Store) GetInvoiceByPeriod

func (s *Store) GetInvoiceByPeriod(_ context.Context, tenantID, appID string, periodStart, periodEnd time.Time) (*invoice.Invoice, error)

func (*Store) GetPlan

func (s *Store) GetPlan(_ context.Context, planID id.PlanID) (*plan.Plan, error)

func (*Store) GetPlanBySlug

func (s *Store) GetPlanBySlug(_ context.Context, slug, appID string) (*plan.Plan, error)

func (*Store) GetSubscription

func (s *Store) GetSubscription(_ context.Context, subID id.SubscriptionID) (*subscription.Subscription, error)

func (*Store) IncrementCouponRedemptions

func (s *Store) IncrementCouponRedemptions(_ context.Context, couponID id.CouponID) error

IncrementCouponRedemptions is a low-level operation kept for callers and tests that need it separately. Engine code redeems through RedeemCoupon, which increments the count and records the application as one unit.

This replaces the map's entry with an updated copy rather than mutating the existing *coupon.Coupon in place, consistent with every other coupon method on this store copying on every crossing (see the comment above CreateCoupon). Mutating the stored object's fields in place, even under s.mu, would still be visible through any *coupon.Coupon a caller obtained from an earlier Get and is holding without a lock - and Get already handed that caller its own copy, so there is nothing of this store's for that mutation to reach.

func (*Store) IngestBatch

func (s *Store) IngestBatch(_ context.Context, events []*meter.UsageEvent) error

Meter Store implementation

func (*Store) Invalidate

func (s *Store) Invalidate(_ context.Context, tenantID, appID string) error

func (*Store) InvalidateFeature

func (s *Store) InvalidateFeature(_ context.Context, tenantID, appID, featureKey string) error

func (*Store) ListAppliedCoupons

func (s *Store) ListAppliedCoupons(_ context.Context, subID id.SubscriptionID) ([]*coupon.Coupon, error)

func (*Store) ListCoupons

func (s *Store) ListCoupons(_ context.Context, appID string, opts coupon.ListOpts) ([]*coupon.Coupon, error)

func (*Store) ListDueSubscriptions

func (s *Store) ListDueSubscriptions(_ context.Context, opts subscription.DueOpts) ([]*subscription.Subscription, error)

func (*Store) ListFeatures

func (s *Store) ListFeatures(_ context.Context, appID string, opts feature.ListOpts) ([]*feature.Feature, error)

func (*Store) ListGlobalFeatures

func (s *Store) ListGlobalFeatures(_ context.Context, opts feature.ListOpts) ([]*feature.Feature, error)

func (*Store) ListInvoices

func (s *Store) ListInvoices(_ context.Context, tenantID, appID string, opts invoice.ListOpts) ([]*invoice.Invoice, error)

func (*Store) ListOverdueInvoices

func (s *Store) ListOverdueInvoices(_ context.Context, opts invoice.OverdueOpts) ([]*invoice.Invoice, error)

func (*Store) ListPendingInvoices

func (s *Store) ListPendingInvoices(_ context.Context, appID string) ([]*invoice.Invoice, error)

func (*Store) ListPlans

func (s *Store) ListPlans(_ context.Context, appID string, opts plan.ListOpts) ([]*plan.Plan, error)

func (*Store) ListSubscriptions

func (s *Store) ListSubscriptions(_ context.Context, tenantID, appID string, opts subscription.ListOpts) ([]*subscription.Subscription, error)

func (*Store) MarkInvoicePaid

func (s *Store) MarkInvoicePaid(_ context.Context, invID id.InvoiceID, paidAt time.Time, paymentRef string) error

func (*Store) MarkInvoicePastDue

func (s *Store) MarkInvoicePastDue(_ context.Context, invID id.InvoiceID, now time.Time) (bool, error)

MarkInvoicePastDue stores a changed copy in place of the invoice rather than writing to it. This store keeps invoices by the pointer it was handed and hands the same pointer back from GetInvoice and the older lists, so a write to it would race any caller still reading an invoice the clock is moving. The copy removes this method from that race, not the store: other writers still share the stored pointer, Ledger.MarkInvoicePaid among them, which sets Status, PaidAt and PaymentRef on the invoice GetInvoice returned, after the store call and outside this store's lock.

func (*Store) MarkInvoiceVoided

func (s *Store) MarkInvoiceVoided(_ context.Context, invID id.InvoiceID, reason string) error

func (*Store) Migrate

func (s *Store) Migrate(_ context.Context) error

Store management

func (*Store) PauseSubscription

func (s *Store) PauseSubscription(_ context.Context, subID id.SubscriptionID, at time.Time) (bool, error)

func (*Store) Ping

func (s *Store) Ping(_ context.Context) error

func (*Store) PurgeUsage

func (s *Store) PurgeUsage(_ context.Context, before time.Time) (int64, error)

func (*Store) QueryUsage

func (s *Store) QueryUsage(_ context.Context, tenantID, appID string, opts meter.QueryOpts) ([]*meter.UsageEvent, error)

func (*Store) RedeemCoupon

func (s *Store) RedeemCoupon(_ context.Context, subID id.SubscriptionID, couponID id.CouponID) error

RedeemCoupon records a coupon's application to a subscription and increments its redemption count under one lock, so a reader can never observe the count moved without the application row that explains it, or see a stale TimesRedeemed while deciding whether the coupon is exhausted. The cap (MaxRedemptions) is checked and the count incremented atomically with respect to every other call on this store: there is no window between reading TimesRedeemed and writing it where a concurrent call could also pass the cap check.

Like IncrementCouponRedemptions, this swaps in an updated copy of the coupon rather than mutating the stored pointer in place - see that method's comment for why, and CreateCoupon's for the copy-on-every- crossing rule this store follows throughout.

func (*Store) ResumeSubscription

func (s *Store) ResumeSubscription(_ context.Context, subID id.SubscriptionID, r subscription.Resume) (bool, error)

func (*Store) SetCached

func (s *Store) SetCached(_ context.Context, tenantID, appID, featureKey string, result *entitlement.Result, ttl time.Duration) error

func (*Store) SetInvoiceProvider

func (s *Store) SetInvoiceProvider(_ context.Context, invID id.InvoiceID, providerID, providerName string) error

SetInvoiceProvider stores a changed copy, for the reason MarkInvoicePastDue gives.

func (*Store) SetSubscriptionProvider

func (s *Store) SetSubscriptionProvider(_ context.Context, subID id.SubscriptionID, providerID, providerName string) error

func (*Store) UpdateCoupon

func (s *Store) UpdateCoupon(_ context.Context, c *coupon.Coupon) error

func (*Store) UpdateFeature

func (s *Store) UpdateFeature(_ context.Context, f *feature.Feature) error

func (*Store) UpdateInvoice

func (s *Store) UpdateInvoice(_ context.Context, inv *invoice.Invoice) error

func (*Store) UpdatePlan

func (s *Store) UpdatePlan(_ context.Context, p *plan.Plan) error

func (*Store) UpdateSubscription

func (s *Store) UpdateSubscription(_ context.Context, sub *subscription.Subscription) error

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL