feat: persist and transfer script command payloads

This commit is contained in:
2026-09-06 11:11:36 +00:00
parent 26ac4c1cac
commit 3f84d3b2f1
18 changed files with 1155 additions and 31 deletions
+10 -1
View File
@@ -102,7 +102,7 @@ func (store *Store) AppendScriptChunk(ctx context.Context, issueUUID domain.UUID
if err != nil {
return ScriptStatus{}, err
}
if row.Committed {
if row.Committed && offset >= row.ReceivedBytes {
return ScriptStatus{}, ErrScriptTerminal
}
if offset > row.ReceivedBytes {
@@ -123,8 +123,17 @@ func (store *Store) AppendScriptChunk(ctx context.Context, issueUUID domain.UUID
if end > row.ReceivedBytes || !bytes.Equal(raw[offset:end], data) {
return ScriptStatus{}, ErrScriptOverlap
}
// A reconnect can replay a chunk after the client has already committed
// the complete script. Exact byte-for-byte replays are safe and must be
// idempotent; a new byte after commit remains forbidden.
if row.Committed {
return ScriptStatus{ReceivedBytes: row.ReceivedBytes, Committed: true, Duplicate: true}, tx.Commit()
}
return ScriptStatus{ReceivedBytes: row.ReceivedBytes, Duplicate: true}, tx.Commit()
}
if row.Committed {
return ScriptStatus{}, ErrScriptTerminal
}
updatedRaw := append(raw, data...)
stored, err := compressScript(updatedRaw)
if err != nil {
+4
View File
@@ -63,6 +63,10 @@ func TestScriptUploadDurableExactReplayAndCommit_HP_SCRIPT_01(t *testing.T) {
if err != nil || !duplicate.Duplicate || !duplicate.Committed {
t.Fatalf("ScriptCommit replay = %#v, %v", duplicate, err)
}
duplicate, err = store.AppendScriptChunk(ctx, issue, 0, raw[:len(first)], sha256.Sum256(raw[:len(first)]))
if err != nil || !duplicate.Duplicate || !duplicate.Committed || duplicate.ReceivedBytes != uint64(len(raw)) {
t.Fatalf("post-commit ScriptChunk replay = %#v, %v", duplicate, err)
}
if _, err := store.AppendScriptChunk(ctx, issue, uint64(len(raw)), []byte("!"), sha256.Sum256([]byte("!"))); !errors.Is(err, ErrScriptTerminal) {
t.Fatalf("post-commit chunk error = %v, want ErrScriptTerminal", err)
}