100 lines
2.8 KiB
Go
100 lines
2.8 KiB
Go
package storage
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"github.com/tech/sendico/pkg/db"
|
|
"github.com/tech/sendico/pkg/mlogger"
|
|
"go.mongodb.org/mongo-driver/v2/bson"
|
|
)
|
|
|
|
// TaskStatus tracks delivery task lifecycle.
|
|
type TaskStatus string
|
|
|
|
const (
|
|
TaskStatusPending TaskStatus = "PENDING"
|
|
TaskStatusRetry TaskStatus = "RETRY"
|
|
TaskStatusDelivered TaskStatus = "DELIVERED"
|
|
TaskStatusFailed TaskStatus = "FAILED"
|
|
)
|
|
|
|
// Endpoint describes one target callback endpoint.
|
|
type Endpoint struct {
|
|
ID bson.ObjectID
|
|
ClientID string
|
|
URL string
|
|
SigningMode string
|
|
SecretRef string
|
|
Headers map[string]string
|
|
MaxAttempts int
|
|
MinDelay time.Duration
|
|
MaxDelay time.Duration
|
|
RequestTimeout time.Duration
|
|
}
|
|
|
|
// Task is one callback delivery job.
|
|
type Task struct {
|
|
ID bson.ObjectID
|
|
EventID string
|
|
EndpointID bson.ObjectID
|
|
EndpointURL string
|
|
SigningMode string
|
|
SecretRef string
|
|
Headers map[string]string
|
|
Payload []byte
|
|
Attempt int
|
|
MaxAttempts int
|
|
MinDelay time.Duration
|
|
MaxDelay time.Duration
|
|
RequestTimeout time.Duration
|
|
Status TaskStatus
|
|
NextAttemptAt time.Time
|
|
}
|
|
|
|
// TaskDefaults are applied when creating tasks.
|
|
type TaskDefaults struct {
|
|
MaxAttempts int
|
|
MinDelay time.Duration
|
|
MaxDelay time.Duration
|
|
RequestTimeout time.Duration
|
|
}
|
|
|
|
// Options configures mongo collections.
|
|
type Options struct {
|
|
InboxCollection string
|
|
TasksCollection string
|
|
EndpointsCollection string
|
|
}
|
|
|
|
// InboxRepo controls event dedupe state.
|
|
type InboxRepo interface {
|
|
TryInsert(ctx context.Context, eventID, clientID, eventType string, at time.Time) (bool, error)
|
|
}
|
|
|
|
// EndpointRepo resolves endpoints for events.
|
|
type EndpointRepo interface {
|
|
FindActiveByClientAndType(ctx context.Context, clientID, eventType string) ([]Endpoint, error)
|
|
}
|
|
|
|
// TaskRepo manages callback tasks.
|
|
type TaskRepo interface {
|
|
UpsertTasks(ctx context.Context, eventID string, endpoints []Endpoint, payload []byte, defaults TaskDefaults, at time.Time) error
|
|
LockNextTask(ctx context.Context, now time.Time, workerID string, lockTTL time.Duration) (*Task, error)
|
|
MarkDelivered(ctx context.Context, taskID bson.ObjectID, httpCode int, latency time.Duration, at time.Time) error
|
|
MarkRetry(ctx context.Context, taskID bson.ObjectID, attempt int, nextAttemptAt time.Time, lastError string, httpCode int, at time.Time) error
|
|
MarkFailed(ctx context.Context, taskID bson.ObjectID, attempt int, lastError string, httpCode int, at time.Time) error
|
|
}
|
|
|
|
// Repository is the callbacks persistence contract.
|
|
type Repository interface {
|
|
Inbox() InboxRepo
|
|
Endpoints() EndpointRepo
|
|
Tasks() TaskRepo
|
|
}
|
|
|
|
// New creates a Mongo-backed callbacks repository.
|
|
func New(logger mlogger.Logger, conn *db.MongoConnection) (Repository, error) {
|
|
return newMongoRepository(logger, conn)
|
|
}
|