59 lines
1.8 KiB
Go
59 lines
1.8 KiB
Go
package store
|
|
|
|
import (
|
|
"database/sql"
|
|
"encoding/json"
|
|
"errors"
|
|
)
|
|
|
|
var ErrEventRejected = errors.New("original event identity was already rejected")
|
|
|
|
// A rejected identity is terminal, even if its producer later changes the body.
|
|
// Retransmit the original feedback, never adopt the changed command.
|
|
func (s *Store) ReplayRejectedEvent(dispatcherID, eventID, eventType string, tenantID int64) (bool, error) {
|
|
tx, err := s.db.Begin()
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
defer tx.Rollback()
|
|
rejected, err := replayRejectedEvent(tx, dispatcherID, eventID, eventType, tenantID)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
if err := tx.Commit(); err != nil {
|
|
return false, err
|
|
}
|
|
return rejected, nil
|
|
}
|
|
func replayRejectedEvent(tx *sql.Tx, dispatcherID, eventID, eventType string, tenantID int64) (bool, error) {
|
|
var kind string
|
|
var body []byte
|
|
err := tx.QueryRow(`SELECT event_type,body FROM dispatcher_outbox WHERE dispatcher_id=? AND event_type=? AND event_id=?`, dispatcherID, eventType, eventID).Scan(&kind, &body)
|
|
if errors.Is(err, sql.ErrNoRows) {
|
|
return false, nil
|
|
}
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
if kind != eventType {
|
|
return false, errors.New("original event identity belongs to another outbound result")
|
|
}
|
|
var receipt struct {
|
|
TenantID int64 `json:"tenant_id"`
|
|
Payload struct {
|
|
Status string `json:"status"`
|
|
} `json:"payload"`
|
|
}
|
|
if err := json.Unmarshal(body, &receipt); err != nil {
|
|
return false, err
|
|
}
|
|
if receipt.TenantID != tenantID {
|
|
return false, errors.New("original rejection tenant identity conflicts with incoming data")
|
|
}
|
|
if receipt.Payload.Status != "rejected" {
|
|
return false, nil
|
|
}
|
|
_, err = tx.Exec(`UPDATE dispatcher_outbox SET confirmed=0,confirmed_at=NULL WHERE dispatcher_id=? AND event_type=? AND event_id=?`, dispatcherID, eventType, eventID)
|
|
return err == nil, err
|
|
}
|