Documentation
¶
Overview ¶
Package store defines the persistence interfaces used by the Manager. Implement these interfaces against your database of choice (Postgres, MongoDB, DynamoDB, etc.) or use the bundled store/memory package for testing and quick-start prototyping.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type AtomicSubscriptionStore ¶
type AtomicSubscriptionStore interface {
SubscriptionStore
// CreateSubscriptionIfNotActive inserts sub only when no active or trialing
// subscription already exists for sub.SubscriberID. Returns *ErrAlreadyExists
// on conflict. The check and insert MUST be atomic.
CreateSubscriptionIfNotActive(ctx context.Context, sub *Subscription) error
}
AtomicSubscriptionStore is an optional extension of SubscriptionStore that provides an atomic check-and-insert for the subscribe guard. Implementations that embed a real database SHOULD implement this interface using a transaction or conditional write (Postgres: INSERT … WHERE NOT EXISTS; DynamoDB: conditional PutItem) to eliminate the TOCTOU race between the duplicate-subscriber check and the insert.
The Manager detects this interface at construction time via type assertion. Store adapters that do not implement it fall back to a two-step check+save, which is safe for single-instance deployments but racy in multi-instance ones.
type ErrAlreadyExists ¶
type ErrAlreadyExists struct{ Entity string }
ErrAlreadyExists is returned by atomic store operations (e.g. CreateSubscriptionIfNotActive) when the record already exists.
func (*ErrAlreadyExists) Error ¶
func (e *ErrAlreadyExists) Error() string
type ErrNotFound ¶
type ErrNotFound struct{ Entity string }
ErrNotFound is returned by store implementations when a record does not exist. Callers compare with errors.Is.
func (*ErrNotFound) Error ¶
func (e *ErrNotFound) Error() string
type Plan ¶
type Plan struct {
ID string
ProviderID string
Name string
Description string
Amount int64
Currency string
Interval string
IntervalCount int
TrialDays int
Features []string
Limits map[string]int64
Metadata map[string]string
Active bool
CreatedAt time.Time
UpdatedAt time.Time
}
Plan is the stored representation of a subscription plan.
type PlanFilter ¶
type PlanFilter struct {
ActiveOnly bool
}
PlanFilter narrows the set of plans returned by ListPlans.
type PlanStore ¶
type PlanStore interface {
// SavePlan creates or updates a plan (upsert on ID).
SavePlan(ctx context.Context, plan *Plan) error
// GetPlan returns the plan with the given ID or ErrNotFound.
GetPlan(ctx context.Context, id string) (*Plan, error)
// ListPlans returns plans matching the filter.
ListPlans(ctx context.Context, filter PlanFilter) ([]*Plan, error)
// DeletePlan removes the plan permanently.
DeletePlan(ctx context.Context, id string) error
}
PlanStore persists subscription plans.
type ReportableUsageStore ¶
type ReportableUsageStore interface {
UsageStore
// ListUnreportedUsage returns up to limit records that have not yet been
// reported to the provider (ProviderReportedAt is nil/zero).
ListUnreportedUsage(ctx context.Context, limit int) ([]*UsageRecord, error)
// MarkUsageReported sets ProviderReportedAt = reportedAt for the given record ID.
MarkUsageReported(ctx context.Context, id string, reportedAt time.Time) error
}
ReportableUsageStore is an optional extension of UsageStore for the persist-then-report pattern. Implementations that want crash-safe provider reporting should implement this interface.
The Manager detects it at construction time via type assertion. When absent the usage reporter falls back to fire-and-forget (same as before).
type Subscription ¶
type Subscription struct {
ID string
ProviderID string
SubscriberID string
PlanID string
Status string
CurrentPeriodStart time.Time
CurrentPeriodEnd time.Time
TrialStart *time.Time
TrialEnd *time.Time
CanceledAt *time.Time
PausedAt *time.Time
Metadata map[string]string
CreatedAt time.Time
UpdatedAt time.Time
}
Subscription is the stored representation of a subscription.
type SubscriptionFilter ¶
type SubscriptionFilter struct {
SubscriberID string
PlanID string
Status string // empty = all statuses
}
SubscriptionFilter narrows the set of subscriptions returned by ListSubscriptions.
type SubscriptionStore ¶
type SubscriptionStore interface {
// SaveSubscription creates or updates a subscription (upsert on ID).
SaveSubscription(ctx context.Context, sub *Subscription) error
// GetSubscription returns the subscription with the given ID or ErrNotFound.
GetSubscription(ctx context.Context, id string) (*Subscription, error)
// GetSubscriptionByProviderID looks up a subscription by the provider's ID.
GetSubscriptionByProviderID(ctx context.Context, providerID string) (*Subscription, error)
// GetActiveSubscription returns the active/trialing subscription for a
// subscriber, or ErrNotFound if none exists.
GetActiveSubscription(ctx context.Context, subscriberID string) (*Subscription, error)
// ListSubscriptions returns subscriptions matching the filter.
ListSubscriptions(ctx context.Context, filter SubscriptionFilter) ([]*Subscription, error)
// DeleteSubscription hard-deletes a subscription record.
DeleteSubscription(ctx context.Context, id string) error
}
SubscriptionStore persists subscriptions.
type UsageRecord ¶
type UsageRecord struct {
ID string
SubscriptionID string
Metric string
Quantity int64
RecordedAt time.Time
Metadata map[string]string
// ProviderReportedAt is set (non-zero) once the record has been
// successfully reported to the payment provider. A zero value means the
// record is pending reporting. Used by the persist-then-report sweeper.
ProviderReportedAt *time.Time
}
UsageRecord is a single metered usage event.
type UsageStore ¶
type UsageStore interface {
// SaveUsageRecord appends a new usage record.
SaveUsageRecord(ctx context.Context, record *UsageRecord) error
// SumUsage returns the total quantity for a metric within [from, to).
SumUsage(ctx context.Context, subscriptionID, metric string, from, to time.Time) (int64, error)
// ListUsageRecords returns all records for a subscription within [from, to).
ListUsageRecords(ctx context.Context, subscriptionID string, from, to time.Time) ([]*UsageRecord, error)
}
UsageStore persists metered usage records.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package memory provides a thread-safe in-memory implementation of the store.PlanStore, store.SubscriptionStore, and store.UsageStore interfaces.
|
Package memory provides a thread-safe in-memory implementation of the store.PlanStore, store.SubscriptionStore, and store.UsageStore interfaces. |