feat: use postgres
This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
package notificationstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
pgtable "galaxy/notification/internal/adapters/postgres/jet/notification/table"
|
||||
"galaxy/notification/internal/service/malformedintent"
|
||||
|
||||
pg "github.com/go-jet/jet/v2/postgres"
|
||||
)
|
||||
|
||||
// Record stores entry idempotently by stream entry id. The helper satisfies
|
||||
// `worker.MalformedIntentRecorder`. Re-recording an entry with the same
|
||||
// `stream_entry_id` is a silent no-op via `ON CONFLICT DO NOTHING`.
|
||||
func (store *Store) Record(ctx context.Context, entry malformedintent.Entry) error {
|
||||
if store == nil {
|
||||
return errors.New("record malformed intent: nil store")
|
||||
}
|
||||
if ctx == nil {
|
||||
return errors.New("record malformed intent: nil context")
|
||||
}
|
||||
if err := entry.Validate(); err != nil {
|
||||
return fmt.Errorf("record malformed intent: %w", err)
|
||||
}
|
||||
|
||||
rawFields, err := marshalRawFields(entry.RawFields)
|
||||
if err != nil {
|
||||
return fmt.Errorf("record malformed intent: %w", err)
|
||||
}
|
||||
|
||||
operationCtx, cancel, err := store.operationContext(ctx, "record malformed intent")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer cancel()
|
||||
|
||||
stmt := pgtable.MalformedIntents.INSERT(
|
||||
pgtable.MalformedIntents.StreamEntryID,
|
||||
pgtable.MalformedIntents.NotificationType,
|
||||
pgtable.MalformedIntents.Producer,
|
||||
pgtable.MalformedIntents.IdempotencyKey,
|
||||
pgtable.MalformedIntents.FailureCode,
|
||||
pgtable.MalformedIntents.FailureMessage,
|
||||
pgtable.MalformedIntents.RawFields,
|
||||
pgtable.MalformedIntents.RecordedAt,
|
||||
).VALUES(
|
||||
entry.StreamEntryID,
|
||||
entry.NotificationType,
|
||||
entry.Producer,
|
||||
entry.IdempotencyKey,
|
||||
string(entry.FailureCode),
|
||||
entry.FailureMessage,
|
||||
rawFields,
|
||||
entry.RecordedAt.UTC(),
|
||||
).ON_CONFLICT(pgtable.MalformedIntents.StreamEntryID).DO_NOTHING()
|
||||
|
||||
query, args := stmt.Sql()
|
||||
if _, err := store.db.ExecContext(operationCtx, query, args...); err != nil {
|
||||
return fmt.Errorf("record malformed intent: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetMalformedIntent loads one malformed-intent entry by stream entry id.
|
||||
// Returns found=false when no such row exists.
|
||||
func (store *Store) GetMalformedIntent(ctx context.Context, streamEntryID string) (malformedintent.Entry, bool, error) {
|
||||
if store == nil {
|
||||
return malformedintent.Entry{}, false, errors.New("get malformed intent: nil store")
|
||||
}
|
||||
if ctx == nil {
|
||||
return malformedintent.Entry{}, false, errors.New("get malformed intent: nil context")
|
||||
}
|
||||
|
||||
operationCtx, cancel, err := store.operationContext(ctx, "get malformed intent")
|
||||
if err != nil {
|
||||
return malformedintent.Entry{}, false, err
|
||||
}
|
||||
defer cancel()
|
||||
|
||||
stmt := pg.SELECT(
|
||||
pgtable.MalformedIntents.NotificationType,
|
||||
pgtable.MalformedIntents.Producer,
|
||||
pgtable.MalformedIntents.IdempotencyKey,
|
||||
pgtable.MalformedIntents.FailureCode,
|
||||
pgtable.MalformedIntents.FailureMessage,
|
||||
pgtable.MalformedIntents.RawFields,
|
||||
pgtable.MalformedIntents.RecordedAt,
|
||||
).FROM(pgtable.MalformedIntents).
|
||||
WHERE(pgtable.MalformedIntents.StreamEntryID.EQ(pg.String(streamEntryID)))
|
||||
|
||||
query, args := stmt.Sql()
|
||||
row := store.db.QueryRowContext(operationCtx, query, args...)
|
||||
|
||||
var (
|
||||
notificationType string
|
||||
producer string
|
||||
idempotencyKey string
|
||||
failureCode string
|
||||
failureMessage string
|
||||
rawFields []byte
|
||||
)
|
||||
entry := malformedintent.Entry{StreamEntryID: streamEntryID}
|
||||
if err := row.Scan(
|
||||
¬ificationType,
|
||||
&producer,
|
||||
&idempotencyKey,
|
||||
&failureCode,
|
||||
&failureMessage,
|
||||
&rawFields,
|
||||
&entry.RecordedAt,
|
||||
); err != nil {
|
||||
if isNoRows(err) {
|
||||
return malformedintent.Entry{}, false, nil
|
||||
}
|
||||
return malformedintent.Entry{}, false, fmt.Errorf("get malformed intent: %w", err)
|
||||
}
|
||||
entry.NotificationType = notificationType
|
||||
entry.Producer = producer
|
||||
entry.IdempotencyKey = idempotencyKey
|
||||
entry.FailureCode = malformedintent.FailureCode(failureCode)
|
||||
entry.FailureMessage = failureMessage
|
||||
entry.RecordedAt = entry.RecordedAt.UTC()
|
||||
fields, err := unmarshalRawFields(rawFields)
|
||||
if err != nil {
|
||||
return malformedintent.Entry{}, false, fmt.Errorf("get malformed intent: %w", err)
|
||||
}
|
||||
entry.RawFields = fields
|
||||
return entry, true, nil
|
||||
}
|
||||
Reference in New Issue
Block a user