72 lines
2.7 KiB
Go
72 lines
2.7 KiB
Go
package store
|
|
|
|
import (
|
|
"errors"
|
|
"testing"
|
|
)
|
|
|
|
func TestLocalFinalResultOwnsUploadDeliveryWithoutSplitNotification(t *testing.T) {
|
|
for _, tc := range []struct {
|
|
name string
|
|
outcome LocalRecordingOutcome
|
|
finalState string
|
|
}{
|
|
{name: "uploaded", outcome: LocalRecordingOutcome{
|
|
Status: "uploaded", Bucket: "mock-bucket", ObjectKey: "tenant/call/rec.wav", SizeBytes: 128000,
|
|
ChecksumSHA256: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
|
}, finalState: "completed"},
|
|
{name: "unavailable", outcome: LocalRecordingOutcome{Status: "unavailable", ErrorCode: "upload_timeout"}, finalState: "failed"},
|
|
} {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
st, terminal := readyLocalRecordingTerminal(t)
|
|
grant := UploadRecord{
|
|
UploadID: terminal.Recording.UploadID, Binding: []byte("bound-agent"), Asset: []byte("bound-recording"),
|
|
Grant: []byte("one-put-only"), Bucket: "mock-bucket", ObjectKey: "tenant/call/rec.wav",
|
|
State: "granted", CreatedAt: terminal.EndedAt,
|
|
}
|
|
if _, err := st.IssueUploadGrant(grant, "op-a", "request-a"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
tc.outcome.ObservedAt = terminal.EndedAt.Add(LocalRecordingDeadline)
|
|
if err := st.RecordLocalRecordingOutcome(terminal.ExecutionID, tc.outcome); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
loaded, err := st.LoadUpload(grant.UploadID)
|
|
if err != nil || loaded.State != "uploaded" {
|
|
t.Fatalf("completed upload still offered a second PUT: state=%q err=%v", loaded.State, err)
|
|
}
|
|
if _, err := st.IssueUploadGrant(grant, "op-b", "request-b"); !errors.Is(err, ErrUploadMismatch) {
|
|
t.Fatalf("second PUT grant issued after durable outcome: %v", err)
|
|
}
|
|
event := localFinalEventFixture()
|
|
if err := st.EnqueueLocalFinalEvent(terminal.ExecutionID, terminal.CallID, event); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
messages, err := st.ClaimOutbox(10)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
found := false
|
|
for _, message := range messages {
|
|
if message.EventID == event.EventID {
|
|
found = true
|
|
if err := st.MarkOutboxPublished(message.ID); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
}
|
|
if !found {
|
|
t.Fatal("single final result was not queued")
|
|
}
|
|
loaded, err = st.LoadUpload(grant.UploadID)
|
|
if err != nil || loaded.State != tc.finalState {
|
|
t.Fatalf("upload delivery was marked before/without the final result: state=%q want=%q err=%v", loaded.State, tc.finalState, err)
|
|
}
|
|
var splitEvents int
|
|
if err := st.DB().QueryRow(`SELECT COUNT(*) FROM upload_notifications WHERE upload_id=?`, grant.UploadID).Scan(&splitEvents); err != nil || splitEvents != 0 {
|
|
t.Fatalf("obsolete recording.uploaded notification persisted: count=%d err=%v", splitEvents, err)
|
|
}
|
|
})
|
|
}
|
|
}
|