67 lines
2.4 KiB
Go
67 lines
2.4 KiB
Go
package store
|
|
|
|
import (
|
|
"database/sql"
|
|
"encoding/json"
|
|
"errors"
|
|
)
|
|
|
|
// VerifyLocalAcceptedCommand binds a final call result to the exact accepted
|
|
// command and execution recorded in the durable inbox and receipt outbox.
|
|
func (s *Store) VerifyLocalAcceptedCommand(tenantID, tenantKey, commandID, executionID, taskID string) error {
|
|
if tenantID == "" || tenantKey == "" || commandID == "" || executionID == "" || taskID == "" {
|
|
return ErrCommandConflict
|
|
}
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
var storedTenantKey, status string
|
|
var commandBody, receiptBody []byte
|
|
err := s.db.QueryRow(`SELECT i.tenant_key, i.status, i.body, o.body
|
|
FROM inbox i
|
|
JOIN mq_command_receipts r ON r.tenant_id=i.tenant_id AND r.command_id=i.command_id
|
|
JOIN outbox o ON o.event_id=r.response_id
|
|
WHERE i.tenant_id=? AND i.command_id=?`, tenantID, commandID).Scan(&storedTenantKey, &status, &commandBody, &receiptBody)
|
|
if errors.Is(err, sql.ErrNoRows) {
|
|
return ErrCommandConflict
|
|
}
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if storedTenantKey != tenantKey || status != "persisted" {
|
|
return ErrCommandConflict
|
|
}
|
|
var command struct {
|
|
CommandID string `json:"command_id"`
|
|
CommandType string `json:"command_type"`
|
|
TenantID string `json:"tenant_id"`
|
|
TenantKey string `json:"tenant_key"`
|
|
Payload struct {
|
|
TaskID string `json:"task_id"`
|
|
} `json:"payload"`
|
|
}
|
|
if err := json.Unmarshal(commandBody, &command); err != nil {
|
|
return ErrCommandConflict
|
|
}
|
|
var receipt struct {
|
|
EventType string `json:"event_type"`
|
|
TenantID string `json:"tenant_id"`
|
|
TenantKey string `json:"tenant_key"`
|
|
Payload struct {
|
|
CommandID string `json:"command_id"`
|
|
CommandType string `json:"command_type"`
|
|
Status string `json:"status"`
|
|
ExecutionID string `json:"execution_id"`
|
|
} `json:"payload"`
|
|
}
|
|
if err := json.Unmarshal(receiptBody, &receipt); err != nil {
|
|
return ErrCommandConflict
|
|
}
|
|
if command.CommandID != commandID || command.CommandType != "call.execute" || command.TenantID != tenantID ||
|
|
command.TenantKey != tenantKey || command.Payload.TaskID != taskID || receipt.EventType != "command.result" ||
|
|
receipt.TenantID != tenantID || receipt.TenantKey != tenantKey || receipt.Payload.CommandID != commandID ||
|
|
receipt.Payload.CommandType != "call.execute" || receipt.Payload.Status != "accepted" || receipt.Payload.ExecutionID != executionID {
|
|
return ErrCommandConflict
|
|
}
|
|
return nil
|
|
}
|