Documentation
¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrDuplicateApproval = errors.New("checker has already acted on this request at this stage")
ErrDuplicateApproval is returned by ApprovalStore.Create when a unique constraint violation occurs (same checker + request + stage). This maps to the service-level ErrAlreadyActioned for proper HTTP 409 responses.
var ErrDuplicateRequest = errors.New("a pending request with the same identity already exists")
ErrDuplicateRequest is returned by RequestStore.Create when a unique constraint violation occurs on the pending fingerprint index. This catches race conditions where two identical requests are created concurrently.
var ErrNotFound = errors.New("record not found")
ErrNotFound is returned by Delete operations when the target row does not exist (or was already deleted between a service-layer existence check and the actual DELETE statement).
var ErrStatusConflict = errors.New("request status has already changed")
ErrStatusConflict is returned by UpdateStatus / UpdateStageAndStatus when the request is no longer in 'pending' status. This acts as a compare-and-set guard, preventing double terminal transitions from concurrent approvers.
Functions ¶
This section is empty.
Types ¶
type ApprovalStore ¶
type ApprovalStore interface {
Create(ctx context.Context, approval *model.Approval) error
ListByRequestID(ctx context.Context, requestID uuid.UUID) ([]model.Approval, error)
CountByDecisionAndStage(ctx context.Context, requestID uuid.UUID, decision model.Decision, stageIndex int) (int, error)
ExistsByCheckerAndStage(ctx context.Context, requestID uuid.UUID, checkerID string, stageIndex int) (bool, error)
}
type AuditStore ¶
type OperatorFilter ¶
type OperatorStore ¶
type OperatorStore interface {
Create(ctx context.Context, operator *model.Operator) error
GetByID(ctx context.Context, id uuid.UUID) (*model.Operator, error)
GetByUsername(ctx context.Context, username string) (*model.Operator, error)
List(ctx context.Context, filter OperatorFilter) ([]model.Operator, int, error)
Update(ctx context.Context, operator *model.Operator) error
Delete(ctx context.Context, id uuid.UUID) error
Count(ctx context.Context) (int, error)
}
type OutboxFilter ¶
type OutboxFilter struct {
TenantID *string
Status *string
Event *string
RequestID *uuid.UUID
Page int
PerPage int
}
OutboxFilter specifies criteria for listing outbox entries.
type OutboxStore ¶
type OutboxStore interface {
CreateBatch(ctx context.Context, entries []model.OutboxEntry) error
// ClaimBatch atomically selects and locks up to `limit` pending entries for
// delivery, transitioning their status to 'processing'. This prevents
// duplicate deliveries across multiple app instances.
ClaimBatch(ctx context.Context, limit int) ([]model.OutboxEntry, error)
MarkDelivered(ctx context.Context, id uuid.UUID) error
MarkRetry(ctx context.Context, id uuid.UUID, attempts int, lastError string, nextRetryAt time.Time) error
MarkFailed(ctx context.Context, id uuid.UUID, attempts int, lastError string) error
DeleteDelivered(ctx context.Context, olderThan time.Time) (int64, error)
// List returns paginated outbox entries filtered by status, request ID, and tenant.
List(ctx context.Context, filter OutboxFilter) ([]model.OutboxEntry, int, error)
// CountByStatus returns a count of entries grouped by status, optionally scoped to a tenant.
// When since is non-nil, only entries created at or after that time are counted.
CountByStatus(ctx context.Context, tenantID *string, since *time.Time) (map[string]int, error)
// ResetAllFailed resets all failed outbox entries to pending for re-delivery.
ResetAllFailed(ctx context.Context, tenantID *string) (int64, error)
// GetByID fetches a single outbox entry.
GetByID(ctx context.Context, id uuid.UUID) (*model.OutboxEntry, error)
// ResetForRetry resets a single failed entry to pending for re-delivery.
ResetForRetry(ctx context.Context, id uuid.UUID) error
// ResetAllFailedForRequest resets all failed entries for a given request ID.
ResetAllFailedForRequest(ctx context.Context, requestID uuid.UUID) (int64, error)
}
OutboxStore manages durable webhook delivery entries.
type PolicyFilter ¶
type PolicyStore ¶
type PolicyStore interface {
Create(ctx context.Context, policy *model.Policy) error
GetByID(ctx context.Context, id uuid.UUID) (*model.Policy, error)
GetByRequestType(ctx context.Context, requestType string) (*model.Policy, error)
List(ctx context.Context, filter PolicyFilter) ([]model.Policy, int, error)
Update(ctx context.Context, policy *model.Policy) error
Delete(ctx context.Context, id uuid.UUID) error
// DistinctRequestTypes returns the unique request_type values across all policies
// for the current tenant (or all tenants when no tenant context is set).
DistinctRequestTypes(ctx context.Context) ([]string, error)
}
type RequestFilter ¶
type RequestStore ¶
type RequestStore interface {
Create(ctx context.Context, req *model.Request) error
GetByID(ctx context.Context, id uuid.UUID) (*model.Request, error)
// GetByIDForUpdate acquires a row-level lock on the request, serializing
// concurrent decision operations within a transaction.
GetByIDForUpdate(ctx context.Context, id uuid.UUID) (*model.Request, error)
GetByIdempotencyKey(ctx context.Context, key string) (*model.Request, error)
FindPendingByFingerprint(ctx context.Context, reqType string, fingerprint string) (*model.Request, error)
List(ctx context.Context, filter RequestFilter) ([]model.Request, int, error)
UpdateStatus(ctx context.Context, id uuid.UUID, status model.RequestStatus) error
UpdateStageAndStatus(ctx context.Context, id uuid.UUID, stage int, status model.RequestStatus) error
ListExpired(ctx context.Context) ([]model.Request, error)
}
type Stores ¶
type Stores struct {
Requests RequestStore
Approvals ApprovalStore
Policies PolicyStore
Webhooks WebhookStore
Audits AuditStore
Operators OperatorStore
Tenants TenantStore
Outbox OutboxStore
Close func()
// HealthCheckers exposes the underlying dependencies (database, etc.)
// for component-level health monitoring via the /health endpoint.
HealthCheckers []health.HealthChecker
// RunInTx executes fn within a database transaction. The callback receives
// a Stores instance whose stores are bound to the transaction. If fn returns
// nil the transaction is committed; otherwise it is rolled back.
RunInTx func(ctx context.Context, fn func(tx *Stores) error) error
}
Stores bundles every store interface and a Close function for the underlying connection.
type TenantFilter ¶
type TenantStore ¶
type TenantStore interface {
Create(ctx context.Context, tenant *model.Tenant) error
GetBySlug(ctx context.Context, slug string) (*model.Tenant, error)
GetByID(ctx context.Context, id uuid.UUID) (*model.Tenant, error)
List(ctx context.Context, filter TenantFilter) ([]model.Tenant, int, error)
Delete(ctx context.Context, id uuid.UUID) error
}
TenantStore manages registered tenants.
type WebhookFilter ¶
type WebhookStore ¶
type WebhookStore interface {
Create(ctx context.Context, webhook *model.Webhook) error
GetByID(ctx context.Context, id uuid.UUID) (*model.Webhook, error)
List(ctx context.Context, filter WebhookFilter) ([]model.Webhook, int, error)
ListByEventAndType(ctx context.Context, event string, requestType string) ([]model.Webhook, error)
Delete(ctx context.Context, id uuid.UUID) error
}
Directories
¶
| Path | Synopsis |
|---|---|
|
Package storetest provides shared integration tests that verify any store implementation correctly satisfies the store interfaces.
|
Package storetest provides shared integration tests that verify any store implementation correctly satisfies the store interfaces. |