Documentation
¶
Overview ¶
Package botsfwstore defines persistence-neutral state contracts used by bots-fw.
Implementations may use DALgo, SQL, an in-memory map, or a remote service. The contracts intentionally do not expose database connections, transactions, records, or storage keys.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrIdentityConflict = errors.New("bot identity conflict")
ErrIdentityConflict reports that the same platform identity was resolved to different application users. This normally means an AppUserStore violated its idempotency contract or identity state was changed concurrently.
var ErrNotFound = errors.New("bot state not found")
ErrNotFound reports that a requested bot-state item does not exist.
Functions ¶
func RequireAppUserID ¶
RequireAppUserID validates an app-user ID returned by a store implementation. It is exported for adapters so all implementations report malformed linked state consistently.
Types ¶
type AppUser ¶
type AppUser struct {
ID string
Data botsfwmodels.AppUserData
}
AppUser is the persistence-neutral view of an application user. Application-specific data remains owned by the consumer application.
type Identity ¶
type Identity struct {
PlatformID string
BotID string
BotUserID string
ChatID string
FirstName string
LastName string
Username string
LanguageCode string
}
Identity identifies a platform user and, when present, the chat through which the bot is interacting with that user. All IDs are platform-provided opaque strings. Implementations must not interpret them as numeric IDs.
type LinkRequest ¶
type LinkRequest struct {
Identity Identity
// ReadPlatformUserData returns an empty platform-user value for decoding an
// existing record. It is separate from NewPlatformUserData because the latter
// is only valid once the application-user ID is known.
ReadPlatformUserData func() botsfwmodels.PlatformUserData
NewPlatformUserData func(appUserID string) (botsfwmodels.PlatformUserData, error)
NewChatData func(appUserID string, accessGranted bool) (botsfwmodels.BotChatData, error)
}
LinkRequest describes the one framework-owned identity use case: make sure a platform user, application-user link, and (when ChatID is present) bot chat exist. Implementations keep their own persistence atomic; the framework never receives their transaction handle.
Factories are called only when an item must be created. They must be free of external side effects because a persistence adapter may call them again when its database retries a transaction. They keep the framework's platform-specific field population out of store implementations.
func (LinkRequest) Validate ¶
func (v LinkRequest) Validate() error
Validate checks that a link request contains the factories necessary to create missing identity state.
type LinkedIdentity ¶
type LinkedIdentity struct {
AppUser AppUser
PlatformUser PlatformUser
ChatData botsfwmodels.BotChatData
}
LinkedIdentity is the state made available to a webhook after identity resolution. ChatData is nil for inputs that do not belong to a chat.
type PlatformUser ¶
type PlatformUser struct {
ID string
Data botsfwmodels.PlatformUserData
}
PlatformUser is the persistence-neutral view of a platform user. It intentionally contains no storage record or key.
type StateStore ¶
type StateStore interface {
WebhookUpdateInbox
// EnsureLinked resolves or creates the identity state described by request.
// A durable implementation must atomically persist its own database changes
// before returning; router dispatch happens after this call returns.
EnsureLinked(ctx context.Context, request LinkRequest) (LinkedIdentity, error)
// PlatformUser returns a platform user without exposing its storage record.
PlatformUser(ctx context.Context, identity Identity, newData func() botsfwmodels.PlatformUserData) (PlatformUser, error)
// AppUser returns application-user data associated with a bot. Consumers own
// the concrete data type and its application persistence.
AppUser(ctx context.Context, botID, appUserID string) (AppUser, error)
// SaveChat persists chat state. It is intentionally separate from application
// business transactions and must not send external messages from a retryable
// persistence callback.
SaveChat(ctx context.Context, identity Identity, data botsfwmodels.BotChatData) error
// SetPlatformUserAccessGranted changes the framework's access flag and returns
// the updated neutral platform-user view.
SetPlatformUserAccessGranted(ctx context.Context, identity Identity, newData func() botsfwmodels.PlatformUserData, value bool) (PlatformUser, error)
}
StateStore provides the framework's persistence use cases. It is deliberately narrow: command handlers get no generic database access through this contract.
type WebhookUpdateClaim ¶ added in v0.14.1
type WebhookUpdateClaim struct {
Status WebhookUpdateClaimStatus
LeaseID string
Attempts int
}
func (WebhookUpdateClaim) CanDispatch ¶ added in v0.14.1
func (c WebhookUpdateClaim) CanDispatch() bool
type WebhookUpdateClaimStatus ¶ added in v0.14.1
type WebhookUpdateClaimStatus string
const ( // WebhookUpdateClaimAcquired gives this caller the lease and permits dispatch. WebhookUpdateClaimAcquired WebhookUpdateClaimStatus = "acquired" // WebhookUpdateClaimCompleted means an earlier caller completed the update. WebhookUpdateClaimCompleted WebhookUpdateClaimStatus = "completed" // WebhookUpdateClaimLeased means another caller still owns a valid lease. WebhookUpdateClaimLeased WebhookUpdateClaimStatus = "leased" )
type WebhookUpdateFailureCode ¶ added in v0.14.1
type WebhookUpdateFailureCode string
WebhookUpdateFailureCode is a deliberately small operational classification. It must not contain an error message, provider payload, identifier, or other user-controlled value.
const ( WebhookUpdateFailureUnknown WebhookUpdateFailureCode = "unknown" WebhookUpdateFailureProcessing WebhookUpdateFailureCode = "processing_failed" WebhookUpdateFailurePanic WebhookUpdateFailureCode = "panic" )
func NormalizeWebhookUpdateFailureCode ¶ added in v0.14.1
func NormalizeWebhookUpdateFailureCode(code WebhookUpdateFailureCode) WebhookUpdateFailureCode
NormalizeWebhookUpdateFailureCode prevents implementations from retaining arbitrary caller input. Unknown values are intentionally coarsened.
type WebhookUpdateInbox ¶ added in v0.14.1
type WebhookUpdateInbox interface {
ClaimWebhookUpdate(ctx context.Context, key WebhookUpdateKey, leaseUntil time.Time) (WebhookUpdateClaim, error)
CompleteWebhookUpdate(ctx context.Context, key WebhookUpdateKey, leaseID string) error
// failureCode is an operational category, never a raw error message or
// provider payload. Implementations must normalize it before persistence.
FailWebhookUpdate(ctx context.Context, key WebhookUpdateKey, leaseID string, failureCode WebhookUpdateFailureCode) error
}
WebhookUpdateInbox is a durable, leased inbox. Claim must be atomic: at most one live lease for a key may be returned at a time. Failed or expired leases may be claimed again; completed updates are never dispatched again. Implementations retain completed records for an operator-configured period.
type WebhookUpdateKey ¶ added in v0.14.1
WebhookUpdateKey identifies one provider delivery. The platform and bot are part of the key so provider update IDs cannot collide across bot webhooks.
func (WebhookUpdateKey) Validate ¶ added in v0.14.1
func (k WebhookUpdateKey) Validate() error
Directories
¶
| Path | Synopsis |
|---|---|
|
Package botsfwstoretest provides persistence-neutral test doubles for store consumers.
|
Package botsfwstoretest provides persistence-neutral test doubles for store consumers. |