memory

package
v0.0.1 Latest Latest
Warning

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

Go to latest
Published: Mar 26, 2026 License: MIT Imports: 5 Imported by: 0

Documentation

Overview

Package memory provides a thread-safe in-memory implementation of the store.PlanStore, store.SubscriptionStore, and store.UsageStore interfaces. It is intended for testing, local development, and quick-start prototyping. Do NOT use it in production — data is lost when the process restarts.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type PlanStore

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

PlanStore is an in-memory PlanStore.

func NewPlanStore

func NewPlanStore() *PlanStore

NewPlanStore returns an empty PlanStore.

func (*PlanStore) DeletePlan

func (s *PlanStore) DeletePlan(_ context.Context, id string) error

func (*PlanStore) GetPlan

func (s *PlanStore) GetPlan(_ context.Context, id string) (*store.Plan, error)

func (*PlanStore) ListPlans

func (s *PlanStore) ListPlans(_ context.Context, filter store.PlanFilter) ([]*store.Plan, error)

func (*PlanStore) SavePlan

func (s *PlanStore) SavePlan(_ context.Context, plan *store.Plan) error

type ShardedSubscriptionStore

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

ShardedSubscriptionStore is the high-throughput replacement for SubscriptionStore. Use NewShardedSubscriptionStore() to create one.

func NewShardedSubscriptionStore

func NewShardedSubscriptionStore() *ShardedSubscriptionStore

NewShardedSubscriptionStore returns an initialised ShardedSubscriptionStore.

func (*ShardedSubscriptionStore) CreateSubscriptionIfNotActive

func (s *ShardedSubscriptionStore) CreateSubscriptionIfNotActive(_ context.Context, sub *store.Subscription) error

CreateSubscriptionIfNotActive is the atomic check+insert used by Manager.Subscribe. It holds the activeBySubscriber write lock for the entire check+insert so no concurrent goroutine can slip in between.

func (*ShardedSubscriptionStore) DeleteSubscription

func (s *ShardedSubscriptionStore) DeleteSubscription(_ context.Context, id string) error

DeleteSubscription removes the subscription and evicts both global indexes.

func (*ShardedSubscriptionStore) GetActiveSubscription

func (s *ShardedSubscriptionStore) GetActiveSubscription(_ context.Context, subscriberID string) (*store.Subscription, error)

GetActiveSubscription is O(1) via the global activeBySubscriber index.

func (*ShardedSubscriptionStore) GetSubscription

func (s *ShardedSubscriptionStore) GetSubscription(_ context.Context, id string) (*store.Subscription, error)

func (*ShardedSubscriptionStore) GetSubscriptionByProviderID

func (s *ShardedSubscriptionStore) GetSubscriptionByProviderID(_ context.Context, providerID string) (*store.Subscription, error)

GetSubscriptionByProviderID is O(1) via the global byProviderID index.

func (*ShardedSubscriptionStore) ListSubscriptions

ListSubscriptions scans all shards. Acquires each shard's read lock in turn.

func (*ShardedSubscriptionStore) SaveSubscription

func (s *ShardedSubscriptionStore) SaveSubscription(_ context.Context, sub *store.Subscription) error

SaveSubscription upserts a subscription and keeps both global indexes consistent.

type SubscriptionStore

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

SubscriptionStore is an in-memory SubscriptionStore with two secondary indexes for O(1) lookups by provider ID and active subscriber.

Index invariants (maintained by SaveSubscription and DeleteSubscription):

  • byProviderID[pid] == id iff subs[id].ProviderID == pid (pid != "")
  • activeBySubscriber[sid] == id iff subs[id].SubscriberID == sid AND isActiveStatus(subs[id].Status)

func NewSubscriptionStore

func NewSubscriptionStore() *SubscriptionStore

NewSubscriptionStore returns an empty SubscriptionStore.

func (*SubscriptionStore) CreateSubscriptionIfNotActive

func (s *SubscriptionStore) CreateSubscriptionIfNotActive(_ context.Context, sub *store.Subscription) error

CreateSubscriptionIfNotActive atomically checks whether the subscriber already has an active or trialing subscription and, if not, inserts sub. Returns *store.ErrAlreadyExists when a conflict is detected. The entire check+insert runs under a single write lock — no TOCTOU window.

func (*SubscriptionStore) DeleteSubscription

func (s *SubscriptionStore) DeleteSubscription(_ context.Context, id string) error

DeleteSubscription removes the subscription and cleans up both secondary indexes.

func (*SubscriptionStore) GetActiveSubscription

func (s *SubscriptionStore) GetActiveSubscription(_ context.Context, subscriberID string) (*store.Subscription, error)

GetActiveSubscription is O(1) via the activeBySubscriber index.

func (*SubscriptionStore) GetSubscription

func (s *SubscriptionStore) GetSubscription(_ context.Context, id string) (*store.Subscription, error)

func (*SubscriptionStore) GetSubscriptionByProviderID

func (s *SubscriptionStore) GetSubscriptionByProviderID(_ context.Context, providerID string) (*store.Subscription, error)

GetSubscriptionByProviderID is O(1) via the byProviderID index.

func (*SubscriptionStore) ListSubscriptions

func (s *SubscriptionStore) ListSubscriptions(_ context.Context, filter store.SubscriptionFilter) ([]*store.Subscription, error)

func (*SubscriptionStore) SaveSubscription

func (s *SubscriptionStore) SaveSubscription(_ context.Context, sub *store.Subscription) error

SaveSubscription creates or updates a subscription and keeps both secondary indexes consistent with the primary map. All three map writes happen under a single write lock so no read can observe a partially-updated state.

type UsageStore

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

UsageStore is an in-memory UsageStore backed by a nested index.

The index has the shape:

index[subscriptionID][metric] → []*store.UsageRecord (ordered by insertion)

This reduces SumUsage and ListUsageRecords from O(N_total) to O(k) where k is the number of records for the specific subscription+metric — typically orders of magnitude smaller than the total record count.

Production adapters MUST create a composite index on (subscription_id, metric, recorded_at) to achieve equivalent performance.

func NewUsageStore

func NewUsageStore() *UsageStore

NewUsageStore returns an empty UsageStore.

func (*UsageStore) ListUnreportedUsage

func (s *UsageStore) ListUnreportedUsage(_ context.Context, limit int) ([]*store.UsageRecord, error)

ListUnreportedUsage returns up to limit records whose ProviderReportedAt is nil. Implements store.ReportableUsageStore.

func (*UsageStore) ListUsageRecords

func (s *UsageStore) ListUsageRecords(_ context.Context, subscriptionID string, from, to time.Time) ([]*store.UsageRecord, error)

ListUsageRecords scans only the records belonging to subscriptionID — O(m) where m is the total records for that subscription across all metrics.

func (*UsageStore) MarkUsageReported

func (s *UsageStore) MarkUsageReported(_ context.Context, id string, reportedAt time.Time) error

MarkUsageReported sets ProviderReportedAt on the record with the given ID. Implements store.ReportableUsageStore.

func (*UsageStore) SaveUsageRecord

func (s *UsageStore) SaveUsageRecord(_ context.Context, record *store.UsageRecord) error

func (*UsageStore) SumUsage

func (s *UsageStore) SumUsage(_ context.Context, subscriptionID, metric string, from, to time.Time) (int64, error)

SumUsage scans only the bucket for (subscriptionID, metric) — O(k) where k is the number of records for that pair, not O(N_total).

Jump to

Keyboard shortcuts

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