snapshot of https://github.com/ThreeDotsLabs/watermill.git (master, 2026-09-15; blobs > 131072B omitted)
Some checks failed
master / ci (push) Failing after 0s
Some checks failed
master / ci (push) Failing after 0s
This commit is contained in:
99
tools/pq/backend/postgres.go
Normal file
99
tools/pq/backend/postgres.go
Normal file
@@ -0,0 +1,99 @@
|
||||
package backend
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/jmoiron/sqlx"
|
||||
_ "github.com/lib/pq"
|
||||
|
||||
"github.com/ThreeDotsLabs/watermill/components/delay"
|
||||
"github.com/ThreeDotsLabs/watermill/tools/pq/cli"
|
||||
)
|
||||
|
||||
type PostgresMessage struct {
|
||||
Offset int `db:"offset"`
|
||||
UUID string `db:"uuid"`
|
||||
Payload string `db:"payload"`
|
||||
Metadata string `db:"metadata"`
|
||||
}
|
||||
|
||||
type PostgresBackend struct {
|
||||
db *sqlx.DB
|
||||
config cli.BackendConfig
|
||||
}
|
||||
|
||||
func NewPostgresBackend(ctx context.Context, config cli.BackendConfig) (*PostgresBackend, error) {
|
||||
dbURL := os.Getenv("DATABASE_URL")
|
||||
if dbURL == "" {
|
||||
return nil, fmt.Errorf("missing DATABASE_URL")
|
||||
}
|
||||
|
||||
db, err := sqlx.Connect("postgres", dbURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &PostgresBackend{
|
||||
db: db,
|
||||
config: config,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (r *PostgresBackend) AllMessages(ctx context.Context) ([]cli.Message, error) {
|
||||
var dbMessages []PostgresMessage
|
||||
err := r.db.SelectContext(ctx, &dbMessages, fmt.Sprintf(`SELECT "offset", uuid, payload, metadata FROM %v WHERE acked = false ORDER BY "offset"`, r.topic()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var messages []cli.Message
|
||||
|
||||
for _, dbMsg := range dbMessages {
|
||||
var metadata map[string]string
|
||||
err := json.Unmarshal([]byte(dbMsg.Metadata), &metadata)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
msg, err := cli.NewMessage(fmt.Sprint(dbMsg.Offset), dbMsg.UUID, dbMsg.Payload, metadata)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
messages = append(messages, msg)
|
||||
}
|
||||
|
||||
return messages, nil
|
||||
}
|
||||
|
||||
func (r *PostgresBackend) Requeue(ctx context.Context, msg cli.Message) error {
|
||||
_, err := r.db.ExecContext(ctx, fmt.Sprintf(`UPDATE %v SET metadata = metadata::jsonb || jsonb_build_object($1::text, $2::text) WHERE "offset" = $3`, r.topic()),
|
||||
delay.DelayedUntilKey, time.Now().UTC().Format(time.RFC3339), msg.ID,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *PostgresBackend) Ack(ctx context.Context, msg cli.Message) error {
|
||||
_, err := r.db.ExecContext(ctx, fmt.Sprintf(`UPDATE %v SET acked = true WHERE "offset" = %v`, r.topic(), msg.ID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *PostgresBackend) topic() string {
|
||||
if r.config.Topic != "" {
|
||||
return fmt.Sprintf(`"watermill_%v"`, r.config.Topic)
|
||||
}
|
||||
|
||||
return fmt.Sprintf(`"%v"`, r.config.RawTopic)
|
||||
}
|
||||
Reference in New Issue
Block a user