subscription

package
v0.1.6 Latest Latest
Warning

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

Go to latest
Published: Jul 9, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

Documentation

Overview

Package subscription manages tenant plan subscriptions, renewals, expiration, grace periods, and billing hooks.

Index

Constants

View Source
const (
	// SQLDialectMySQL uses question-mark placeholders and is the default.
	SQLDialectMySQL = sqlutil.DialectMySQL

	// SQLDialectSQLite uses question-mark placeholders.
	SQLDialectSQLite = sqlutil.DialectSQLite

	// SQLDialectPostgres uses numbered placeholders.
	SQLDialectPostgres = sqlutil.DialectPostgres
)
View Source
const (
	// DefaultSQLTableName is the default subscription table name.
	DefaultSQLTableName = "saas_subscriptions"
)

Variables

View Source
var (
	// ErrSubscriptionNotFound reports that a subscription does not exist.
	ErrSubscriptionNotFound = errors.New("gotenancy/subscription: subscription not found")

	// ErrSubscriptionAlreadyExists reports that a tenant already has a subscription.
	ErrSubscriptionAlreadyExists = errors.New("gotenancy/subscription: subscription already exists")

	// ErrInvalidSubscription reports invalid subscription metadata.
	ErrInvalidSubscription = errors.New("gotenancy/subscription: invalid subscription")

	// ErrInvalidTransition reports an invalid subscription lifecycle transition.
	ErrInvalidTransition = errors.New("gotenancy/subscription: invalid transition")

	// ErrInvalidListFilter reports an invalid subscription list filter.
	ErrInvalidListFilter = errors.New("gotenancy/subscription: invalid list filter")

	// ErrNilDB reports that a SQL store was created with a nil database handle.
	ErrNilDB = errors.New("gotenancy/subscription: nil db")

	// ErrInvalidTableName reports an unsafe SQL table name.
	ErrInvalidTableName = errors.New("gotenancy/subscription: invalid table name")

	// ErrUnsupportedSQLDialect reports an unsupported SQLStore dialect.
	ErrUnsupportedSQLDialect = errors.New("gotenancy/subscription: unsupported sql dialect")
)

Functions

This section is empty.

Types

type BillingEvent

type BillingEvent struct {
	TenantID         types.TenantID
	Action           string
	FromPlan         string
	ToPlan           string
	Status           Status
	CurrentPeriodEnd *time.Time
}

BillingEvent describes a subscription change for external billing systems.

type BillingHook

type BillingHook func(context.Context, BillingEvent) error

BillingHook receives subscription lifecycle changes.

type LifecycleService added in v0.1.5

type LifecycleService interface {
	Service
	SubscribeWithPeriod(ctx context.Context, tenantID types.TenantID, planID string, currentPeriodEnd time.Time) (Subscription, error)
	Renew(ctx context.Context, tenantID types.TenantID, currentPeriodEnd time.Time) (Subscription, error)
	Expire(ctx context.Context, tenantID types.TenantID) (Subscription, error)
	ExpireDue(ctx context.Context) ([]Subscription, error)
}

LifecycleService extends Service with billing-period renewal and expiration operations.

type ListFilter added in v0.1.6

type ListFilter struct {
	TenantIDs []types.TenantID
	PlanIDs   []string
	Statuses  []Status
	Limit     int
	Offset    int
}

ListFilter restricts subscription list queries.

type MemoryService

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

MemoryService is a thread-safe in-memory subscription service.

func NewMemoryService

func NewMemoryService(opts ...Option) *MemoryService

NewMemoryService creates an empty subscription service.

func (*MemoryService) Create added in v0.1.6

func (service *MemoryService) Create(ctx context.Context, subscription Subscription) error

Create inserts a subscription.

func (*MemoryService) Delete added in v0.1.6

func (service *MemoryService) Delete(ctx context.Context, tenantID types.TenantID) error

Delete removes a subscription by tenant ID.

func (*MemoryService) Downgrade

func (service *MemoryService) Downgrade(ctx context.Context, tenantID types.TenantID, planID string) (Subscription, error)

Downgrade changes an active subscription to a lower plan.

func (*MemoryService) Expire added in v0.1.5

func (service *MemoryService) Expire(ctx context.Context, tenantID types.TenantID) (Subscription, error)

Expire marks an active subscription expired immediately.

func (*MemoryService) ExpireDue added in v0.1.5

func (service *MemoryService) ExpireDue(ctx context.Context) ([]Subscription, error)

ExpireDue marks active subscriptions expired after their current period and grace window end.

func (*MemoryService) Get

func (service *MemoryService) Get(ctx context.Context, tenantID types.TenantID) (Subscription, error)

Get returns a subscription by tenant ID.

func (*MemoryService) List added in v0.1.6

func (service *MemoryService) List(ctx context.Context, filter ListFilter) ([]Subscription, error)

List returns subscriptions matching filter.

func (*MemoryService) ListPage added in v0.1.6

func (service *MemoryService) ListPage(ctx context.Context, filter PageFilter) ([]Subscription, error)

ListPage returns subscriptions after the cursor while preserving List filtering semantics.

func (*MemoryService) Renew added in v0.1.5

func (service *MemoryService) Renew(ctx context.Context, tenantID types.TenantID, currentPeriodEnd time.Time) (Subscription, error)

Renew reactivates an active or expired subscription with a new current period end.

func (*MemoryService) Subscribe

func (service *MemoryService) Subscribe(ctx context.Context, tenantID types.TenantID, planID string) (Subscription, error)

Subscribe creates an active subscription for a tenant.

func (*MemoryService) SubscribeWithPeriod added in v0.1.5

func (service *MemoryService) SubscribeWithPeriod(ctx context.Context, tenantID types.TenantID, planID string, currentPeriodEnd time.Time) (Subscription, error)

SubscribeWithPeriod creates an active subscription with a current billing period end.

func (*MemoryService) Unsubscribe

func (service *MemoryService) Unsubscribe(ctx context.Context, tenantID types.TenantID) (Subscription, error)

Unsubscribe cancels an active subscription.

func (*MemoryService) Update added in v0.1.6

func (service *MemoryService) Update(ctx context.Context, subscription Subscription) error

Update replaces a subscription.

func (*MemoryService) Upgrade

func (service *MemoryService) Upgrade(ctx context.Context, tenantID types.TenantID, planID string) (Subscription, error)

Upgrade changes an active subscription to a higher plan.

type MemoryStore added in v0.1.6

type MemoryStore = MemoryService

MemoryStore is kept as a Store-oriented name for MemoryService.

func NewMemoryStore added in v0.1.6

func NewMemoryStore(opts ...Option) *MemoryStore

NewMemoryStore creates an empty subscription store.

type Option

type Option func(*MemoryService)

Option configures MemoryService.

func WithBillingHook

func WithBillingHook(hook BillingHook) Option

WithBillingHook sets the billing hook.

func WithClock

func WithClock(clock func() time.Time) Option

WithClock sets the clock used for subscription dates.

func WithGracePeriod added in v0.1.5

func WithGracePeriod(period time.Duration) Option

WithGracePeriod sets the post-period grace window before ExpireDue marks a subscription expired.

type PageFilter added in v0.1.6

type PageFilter struct {
	TenantIDs []types.TenantID
	PlanIDs   []string
	Statuses  []Status
	Limit     int
	Offset    int
	// Cursor returns rows ordered after the tenant ID cursor.
	Cursor types.TenantID
}

PageFilter restricts cursor-based subscription list queries.

type PagedStore added in v0.1.6

type PagedStore interface {
	Store
	ListPage(ctx context.Context, filter PageFilter) ([]Subscription, error)
}

PagedStore extends Store with cursor-based subscription listing.

type SQLDialect added in v0.1.6

type SQLDialect = sqlutil.Dialect

SQLDialect controls SQL placeholder rendering for SQLStore.

type SQLStore added in v0.1.6

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

SQLStore persists tenant subscriptions through database/sql.

The table is expected to contain these columns: tenant_id, plan_id, status, start_date, end_date, current_period_end, grace_period_end.

func NewSQLStore added in v0.1.6

func NewSQLStore(db *sql.DB, opts ...SQLStoreOption) (*SQLStore, error)

NewSQLStore creates a SQL-backed subscription store.

func (*SQLStore) Create added in v0.1.6

func (store *SQLStore) Create(ctx context.Context, subscription Subscription) error

Create inserts a subscription.

func (*SQLStore) Delete added in v0.1.6

func (store *SQLStore) Delete(ctx context.Context, tenantID types.TenantID) error

Delete removes a subscription by tenant ID.

func (*SQLStore) Get added in v0.1.6

func (store *SQLStore) Get(ctx context.Context, tenantID types.TenantID) (Subscription, error)

Get returns a subscription by tenant ID.

func (*SQLStore) List added in v0.1.6

func (store *SQLStore) List(ctx context.Context, filter ListFilter) (subscriptions []Subscription, err error)

List returns subscriptions matching filter.

func (*SQLStore) ListPage added in v0.1.6

func (store *SQLStore) ListPage(ctx context.Context, filter PageFilter) (subscriptions []Subscription, err error)

ListPage returns subscriptions after the cursor while preserving List filtering semantics.

func (*SQLStore) Update added in v0.1.6

func (store *SQLStore) Update(ctx context.Context, subscription Subscription) error

Update replaces a subscription.

type SQLStoreOption added in v0.1.6

type SQLStoreOption func(*SQLStore) error

SQLStoreOption configures SQLStore.

func WithSQLDialect added in v0.1.6

func WithSQLDialect(dialect SQLDialect) SQLStoreOption

WithSQLDialect configures SQL placeholder rendering.

func WithTableName added in v0.1.6

func WithTableName(table string) SQLStoreOption

WithTableName overrides the default subscription table name.

type Service

type Service interface {
	Subscribe(ctx context.Context, tenantID types.TenantID, planID string) (Subscription, error)
	Unsubscribe(ctx context.Context, tenantID types.TenantID) (Subscription, error)
	Upgrade(ctx context.Context, tenantID types.TenantID, planID string) (Subscription, error)
	Downgrade(ctx context.Context, tenantID types.TenantID, planID string) (Subscription, error)
	Get(ctx context.Context, tenantID types.TenantID) (Subscription, error)
}

Service manages tenant subscriptions.

type Status

type Status string

Status describes subscription lifecycle state.

const (
	StatusActive    Status = "active"
	StatusExpired   Status = "expired"
	StatusCancelled Status = "cancelled"
)

type Store added in v0.1.6

type Store interface {
	Create(ctx context.Context, subscription Subscription) error
	Get(ctx context.Context, tenantID types.TenantID) (Subscription, error)
	List(ctx context.Context, filter ListFilter) ([]Subscription, error)
	Update(ctx context.Context, subscription Subscription) error
	Delete(ctx context.Context, tenantID types.TenantID) error
}

Store persists tenant subscriptions.

type Subscription

type Subscription struct {
	TenantID         types.TenantID
	PlanID           string
	Status           Status
	StartDate        time.Time
	EndDate          *time.Time
	CurrentPeriodEnd *time.Time
	GracePeriodEnd   *time.Time
}

Subscription binds a tenant to a plan.

Jump to

Keyboard shortcuts

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