credit

package
v1.0.0-beta.72 Latest Latest
Warning

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

Go to latest
Published: May 7, 2024 License: Apache-2.0 Imports: 7 Imported by: 0

README

[Experimental] OpenMeter Credits

OpenMeter can handle complex scenarios related to credit management, usage, and rate limits. You can grant credits via API for specific subjects with priorities, effective dates, and expiration dates. OpenMeter then burns down credits in order based on these parameters and the ingested usage, ensuring optimal performance.

OpenMeter Credits can help to implement:

  • Monthly usage-limit enforcement
  • Implementing prepaid credits
  • Combining recurring credits with top-ups
  • Rolling over remaining credits between billing periods

Quickstart

Run docker compose with --profile postgres and enable entitlements in config.yaml via

entitlements:
    enabled: true

Test

Credit tests require a Postgres database. The recommended way to run tests is to use make test, which runs the necessary dependencies via Dagger. If you need to iterate on credit tests quickly, you can run your own Postgres instance (or use the one run by docker-compose) and run tests manually as: POSTGRES_HOST=localhost go test ./internal/credit/...

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Balance

type Balance struct {
	LedgerID        ulid.ULID         `json:"id"`
	Metadata        map[string]string `json:"metadata,omitempty"`
	Subject         string            `json:"subject"`
	FeatureBalances []FeatureBalance  `json:"featureBalances"`
	GrantBalances   []GrantBalance    `json:"grantBalances"`
}

Balance of a subject in a credit.

func (Balance) Render

func (c Balance) Render(w http.ResponseWriter, r *http.Request) error

Render implements the chi renderer interface.

type Connector

type Connector interface {
	// Ledger
	CreateLedger(ctx context.Context, namespace string, ledger Ledger) (Ledger, error)
	ListLedgers(ctx context.Context, namespace string, params ListLedgersParams) ([]Ledger, error)

	// Grant
	CreateGrant(ctx context.Context, namespace string, grant Grant) (Grant, error)
	VoidGrant(ctx context.Context, namespace string, grant Grant) (Grant, error)
	ListGrants(ctx context.Context, namespace string, params ListGrantsParams) ([]Grant, error)
	GetGrant(ctx context.Context, namespace string, id ulid.ULID) (Grant, error)

	// Credit
	GetBalance(ctx context.Context, namespace string, ledgerID ulid.ULID, cutline time.Time) (Balance, error)
	GetHistory(ctx context.Context, namespace string, ledgerID ulid.ULID, from time.Time, to time.Time, limit int) (LedgerEntryList, error)
	GetHighWatermark(ctx context.Context, namespace string, ledgerID ulid.ULID) (HighWatermark, error)
	Reset(ctx context.Context, namespace string, reset Reset) (Reset, []Grant, error)

	// Feature
	CreateFeature(ctx context.Context, namespace string, feature Feature) (Feature, error)
	DeleteFeature(ctx context.Context, namespace string, ledgerID ulid.ULID) error
	ListFeatures(ctx context.Context, namespace string, params ListFeaturesParams) ([]Feature, error)
	GetFeature(ctx context.Context, namespace string, ledgerID ulid.ULID) (Feature, error)
}

type EntryType

type EntryType string
const (
	EntryTypeGrant     EntryType = "GRANT"
	EntryTypeVoidGrant EntryType = "VOID_GRANT"
	EntryTypeReset     EntryType = "RESET"
)

Defines values for EntryType.

func (EntryType) Values

func (EntryType) Values() (kinds []string)

type ExpirationPeriod

type ExpirationPeriod struct {
	// Count The expiration period count like 12 months.
	Count uint8 `json:"count,omitempty"`

	// Duration The expiration period duration like month.
	Duration ExpirationPeriodDuration `json:"duration,omitempty"`
}

ExpirationPeriod of a credit grant.

func (ExpirationPeriod) GetExpiration

func (c ExpirationPeriod) GetExpiration(t time.Time) time.Time

type ExpirationPeriodDuration

type ExpirationPeriodDuration string
const (
	ExpirationPeriodDurationHour  ExpirationPeriodDuration = "HOUR"
	ExpirationPeriodDurationDay   ExpirationPeriodDuration = "DAY"
	ExpirationPeriodDurationWeek  ExpirationPeriodDuration = "WEEK"
	ExpirationPeriodDurationMonth ExpirationPeriodDuration = "MONTH"
	ExpirationPeriodDurationYear  ExpirationPeriodDuration = "YEAR"
)

Defines values for ExpirationPeriodDuration.

func (ExpirationPeriodDuration) Values

func (ExpirationPeriodDuration) Values() (kinds []string)

type Feature

type Feature struct {
	Namespace string     `json:"-"`
	ID        *ulid.ULID `json:"id,omitempty"`

	// Name The name of the feature.
	Name string `json:"name"`

	// MeterSlug The meter that the feature is associated with and decreases grants by usage.
	MeterSlug string `json:"meterSlug,omitempty"`

	// MeterGroupByFilters Optional meter group by filters. Useful if the meter scope is broader than what feature tracks.
	MeterGroupByFilters *map[string]string `json:"meterGroupByFilters,omitempty"`

	// Read-only fields
	Archived *bool `json:"archived,omitempty"`
}

Feature is a feature or service offered to a customer. For example: CPU-Hours, Tokens, API Calls, etc.

func (Feature) Render

func (c Feature) Render(w http.ResponseWriter, r *http.Request) error

Render implements the chi renderer interface.

type FeatureBalance

type FeatureBalance struct {
	Feature
	Balance float64 `json:"balance"`
}

func (FeatureBalance) Render

Render implements the chi renderer interface.

type FeatureNotFoundError

type FeatureNotFoundError struct {
	ID ulid.ULID
}

func (*FeatureNotFoundError) Error

func (e *FeatureNotFoundError) Error() string

type Grant

type Grant struct {
	// ID is the readonly identifies of a grant.
	ID *ulid.ULID `json:"id,omitempty"`

	// Parent ID is the readonly identifies of the grant's parent if any.
	ParentID *ulid.ULID `json:"parentID,omitempty"`

	// Subject The subject to grant the amount to.
	LedgerID ulid.ULID `json:"ledgerID"`

	// Type The grant type.
	Type GrantType `json:"type"`

	// FeatureID The feature ID.
	FeatureID *ulid.ULID `json:"featureID"`

	// Amount The amount to grant. Can be positive or negative number.
	Amount float64 `json:"amount"`

	// Priority is a positive decimal numbers. With lower numbers indicating higher importance;
	// for example, a priority of 1 is more urgent than a priority of 2.
	// When there are several credit grants available for a single invoice, the system selects the credit with the highest priority.
	// In cases where credit grants share the same priority level, the grant closest to its expiration will be used first.
	// In the case of two credits have identical priorities and expiration dates, the system will use the credit that was created first.
	Priority uint8 `json:"priority"`

	// EffectiveAt The effective date.
	EffectiveAt time.Time `json:"effectiveAt"`

	// Expiration The expiration configuration.
	Expiration ExpirationPeriod `json:"expiration"`
	// ExpiresAt contains the exact expiration date calculated from effectiveAt and Expiration for rendering
	ExpiresAt time.Time `json:"expiresAt"`

	Metadata map[string]string `json:"metadata,omitempty"`

	// Rollover Grant rollover configuration.
	Rollover *GrantRollover `json:"rollover,omitempty"`

	// Void The voided date.
	Void bool `json:"void"`
}

Grant is used to increase balance of specific subjects.

func (Grant) ExpirationDate

func (c Grant) ExpirationDate() time.Time

func (Grant) Render

func (c Grant) Render(w http.ResponseWriter, r *http.Request) error

Render implements the chi renderer interface.

type GrantBalance

type GrantBalance struct {
	Grant
	Balance float64 `json:"balance"`
}

func (GrantBalance) Render

Render implements the chi renderer interface.

type GrantNotFoundError

type GrantNotFoundError struct {
	GrantID ulid.ULID
}

func (*GrantNotFoundError) Error

func (e *GrantNotFoundError) Error() string

type GrantRollover

type GrantRollover struct {
	// MaxAmount Maximum amount to rollover.
	MaxAmount *float64 `json:"maxAmount,omitempty"`

	// Type The rollover type to use:
	Type GrantRolloverType `json:"type"`
}

GrantRollover configuration.

type GrantRolloverType

type GrantRolloverType string
const (
	GrantRolloverTypeOriginalAmount  GrantRolloverType = "ORIGINAL_AMOUNT"
	GrantRolloverTypeRemainingAmount GrantRolloverType = "REMAINING_AMOUNT"
)

Defines values for GrantRolloverType.

func (GrantRolloverType) Values

func (GrantRolloverType) Values() (kinds []string)

type GrantType

type GrantType string
const (
	GrantTypeUsage GrantType = "USAGE"
)

Defines values for GrantType.

func (GrantType) Values

func (GrantType) Values() (kinds []string)

type HighWatermarBeforeError

type HighWatermarBeforeError struct {
	Namespace     string
	LedgerID      ulid.ULID
	HighWatermark time.Time
}

HighWatermarBeforeError is returned when a lock cannot be obtained.

func (*HighWatermarBeforeError) Error

func (e *HighWatermarBeforeError) Error() string

type HighWatermark

type HighWatermark struct {
	LedgerID ulid.ULID `ch:"ledger_id"`
	Time     time.Time `ch:"time"`
}

type Ledger

type Ledger struct {
	// ID is the ID of the ledger instance
	ID ulid.ULID `json:"id,omitempty"`

	// Subject specifies which metering subject this ledger is referring to
	Subject string `json:"subject"`

	Metadata map[string]string `json:"metadata,omitempty"`
}

func (Ledger) Render

func (c Ledger) Render(w http.ResponseWriter, r *http.Request) error

Render implements the chi renderer interface.

type LedgerAlreadyExistsError

type LedgerAlreadyExistsError struct {
	Namespace string
	LedgerID  ulid.ULID
	Subject   string
}

func (*LedgerAlreadyExistsError) Error

func (e *LedgerAlreadyExistsError) Error() string

type LedgerEntry

type LedgerEntry struct {
	ID        *ulid.ULID      `json:"id,omitempty"`
	Type      LedgerEntryType `json:"type"`
	Time      time.Time       `json:"time"`
	FeatureID *ulid.ULID      `json:"featureId,omitempty"`
	Amount    *float64        `json:"amount,omitempty"`
	Period    *Period         `json:"period,omitempty"`
}

LedgerEntry is a credit ledger entry.

func (LedgerEntry) Render

func (c LedgerEntry) Render(w http.ResponseWriter, r *http.Request) error

Render implements the chi renderer interface.

type LedgerEntryList

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

func NewLedgerEntryList

func NewLedgerEntryList() LedgerEntryList

func (*LedgerEntryList) AddGrant

func (c *LedgerEntryList) AddGrant(grant Grant)

func (*LedgerEntryList) AddGrantUsage

func (c *LedgerEntryList) AddGrantUsage(grantBalance GrantBalance, from time.Time, to time.Time, amount float64)

func (*LedgerEntryList) AddReset

func (c *LedgerEntryList) AddReset(reset Reset)

func (*LedgerEntryList) AddVoidGrant

func (c *LedgerEntryList) AddVoidGrant(grant Grant)

func (*LedgerEntryList) Append

func (c *LedgerEntryList) Append(other LedgerEntryList)

func (LedgerEntryList) GetEntries

func (f LedgerEntryList) GetEntries() []LedgerEntry

func (LedgerEntryList) MarshalJSON

func (f LedgerEntryList) MarshalJSON() ([]byte, error)

func (LedgerEntryList) Render

type LedgerEntryType

type LedgerEntryType string
const (
	LedgerEntryTypeGrant      LedgerEntryType = "GRANT"
	LedgerEntryTypeVoid       LedgerEntryType = "VOID"
	LedgerEntryTypeReset      LedgerEntryType = "RESET"
	LedgerEntryTypeGrantUsage LedgerEntryType = "GRANT_USAGE"
)

Defines values for LedgerEntryType.

func (LedgerEntryType) Values

func (LedgerEntryType) Values() (kinds []string)

type LedgerNotFoundError

type LedgerNotFoundError struct {
	Namespace string
	LedgerID  ulid.ULID
}

func (*LedgerNotFoundError) Error

func (e *LedgerNotFoundError) Error() string

type ListFeaturesParams

type ListFeaturesParams struct {
	IncludeArchived bool
}

type ListGrantsParams

type ListGrantsParams struct {
	LedgerIDs         []ulid.ULID
	From              *time.Time
	To                *time.Time
	FromHighWatermark bool
	IncludeVoid       bool
	Limit             int
}

type ListLedgersParams

type ListLedgersParams struct {
	Subjects []string
	Offset   int
	Limit    int
}

type LockErrNotObtainedError

type LockErrNotObtainedError struct {
	Namespace string
	ID        ulid.ULID
}

LockErrNotObtainedError is returned when a lock cannot be obtained.

func (*LockErrNotObtainedError) Error

func (e *LockErrNotObtainedError) Error() string

type Period

type Period struct {
	From time.Time `json:"from"`
	To   time.Time `json:"to"`
}

type Reset

type Reset struct {
	// ID is the readonly identifies of a reset.
	ID *ulid.ULID `json:"id,omitempty"`

	// Subject The subject to grant the amount to.
	LedgerID ulid.ULID `json:"ledgerID"`

	// EffectiveAt The effective date, cannot be in the future.
	EffectiveAt time.Time `json:"effectiveAt"`
}

Reset is used to reset the balance of a specific subject.

func (Reset) Render

func (c Reset) Render(w http.ResponseWriter, r *http.Request) error

Render implements the chi renderer interface.

Jump to

Keyboard shortcuts

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