ADR 0627 §2: a transfer read back from the bus takes its first chunk
A transfer is kept in a key-value state as JSON, and its empty Chunks map is omitted, so the one read back for the first chunk had none and Take panicked: every publish in parts through BusTransfers. The unit tests' transfers now round-trip JSON as the bus does. Found by the forge module's whole test (CAT-G3). Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
This commit is contained in:
@@ -1,10 +1,13 @@
|
|||||||
github.com/antithesishq/antithesis-sdk-go v0.8.0-default-no-op h1:1BOWQJweNyvZMlpAHXGLiZQn9S+QXGcz3xh94lC0w6E=
|
github.com/antithesishq/antithesis-sdk-go v0.8.0-default-no-op h1:1BOWQJweNyvZMlpAHXGLiZQn9S+QXGcz3xh94lC0w6E=
|
||||||
|
github.com/antithesishq/antithesis-sdk-go v0.8.0-default-no-op/go.mod h1:FQyySiasQQM8735Ddel3MRojmy4dA1IqCeyJ5jmPMbI=
|
||||||
github.com/google/go-tpm v0.9.8 h1:slArAR9Ft+1ybZu0lBwpSmpwhRXaa85hWtMinMyRAWo=
|
github.com/google/go-tpm v0.9.8 h1:slArAR9Ft+1ybZu0lBwpSmpwhRXaa85hWtMinMyRAWo=
|
||||||
github.com/google/go-tpm v0.9.8/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY=
|
github.com/google/go-tpm v0.9.8/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY=
|
||||||
github.com/klauspost/compress v1.20.1 h1:T7kKElXUMXrUJ2E9QhQhxFtcK5rPyLdsGZvdbLMPdiQ=
|
github.com/klauspost/compress v1.20.1 h1:T7kKElXUMXrUJ2E9QhQhxFtcK5rPyLdsGZvdbLMPdiQ=
|
||||||
|
github.com/klauspost/compress v1.20.1/go.mod h1:LUdAzn7YLVvxLpc7y3V1m40wESHTgc1422pwwBSKYuI=
|
||||||
github.com/minio/highwayhash v1.0.4 h1:asJizugGgchQod2ja9NJlGOWq4s7KsAWr5XUc9Clgl4=
|
github.com/minio/highwayhash v1.0.4 h1:asJizugGgchQod2ja9NJlGOWq4s7KsAWr5XUc9Clgl4=
|
||||||
github.com/minio/highwayhash v1.0.4/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ=
|
github.com/minio/highwayhash v1.0.4/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ=
|
||||||
github.com/nats-io/jwt/v2 v2.8.2 h1:XXRgB60MSTnqsRwejQurVDs/hcv2dkt+86GjI+I/bMc=
|
github.com/nats-io/jwt/v2 v2.8.2 h1:XXRgB60MSTnqsRwejQurVDs/hcv2dkt+86GjI+I/bMc=
|
||||||
|
github.com/nats-io/jwt/v2 v2.8.2/go.mod h1:Ag/56sq9OblL4JgdYufDd16Egb17Kr/8WwwuO/forVc=
|
||||||
github.com/nats-io/nats-server/v2 v2.11.17 h1:GKEghcFK6A+aFx11Yf1LjgLC3txAwvyhnYzhBIQZA8I=
|
github.com/nats-io/nats-server/v2 v2.11.17 h1:GKEghcFK6A+aFx11Yf1LjgLC3txAwvyhnYzhBIQZA8I=
|
||||||
github.com/nats-io/nats-server/v2 v2.11.17/go.mod h1:B1sFVz4StNosQ903ak4N1G01Fl/9f8e06mXpFIE2K24=
|
github.com/nats-io/nats-server/v2 v2.11.17/go.mod h1:B1sFVz4StNosQ903ak4N1G01Fl/9f8e06mXpFIE2K24=
|
||||||
github.com/nats-io/nats.go v1.54.0 h1:vsXoOxjHp/GmPUN+EcI7uOf/uB+iAP+kEsAFNQN0yzA=
|
github.com/nats-io/nats.go v1.54.0 h1:vsXoOxjHp/GmPUN+EcI7uOf/uB+iAP+kEsAFNQN0yzA=
|
||||||
@@ -19,3 +22,4 @@ golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
|||||||
golang.org/x/sys v0.48.0 h1:bbX/i/6MgT9BVLM9RT1thmxL04yeTAhbEz4SyadbXoo=
|
golang.org/x/sys v0.48.0 h1:bbX/i/6MgT9BVLM9RT1thmxL04yeTAhbEz4SyadbXoo=
|
||||||
golang.org/x/sys v0.48.0/go.mod h1:hNLxWAXmnKAxqDtdwIYC4bM9oQPEecfsnNMuSxOs3og=
|
golang.org/x/sys v0.48.0/go.mod h1:hNLxWAXmnKAxqDtdwIYC4bM9oQPEecfsnNMuSxOs3og=
|
||||||
golang.org/x/time v0.16.0 h1:vMb6ptszcQMkcwiRTAuNNU50gom6++Q/6gY2hDM6VDE=
|
golang.org/x/time v0.16.0 h1:vMb6ptszcQMkcwiRTAuNNU50gom6++Q/6gY2hDM6VDE=
|
||||||
|
golang.org/x/time v0.16.0/go.mod h1:rVKOqvZeKvrDKTQiAHJ7wmwP0RzleSphoEA9RcdLA0s=
|
||||||
|
|||||||
@@ -240,6 +240,10 @@ func (r *Receiver[M]) Take(id, opener, digest string, sequence int, last bool, d
|
|||||||
if err := r.Objects.Put(r.chunkName(id, digest, sequence), data); err != nil {
|
if err := r.Objects.Put(r.chunkName(id, digest, sequence), data); err != nil {
|
||||||
return Received{}, fmt.Errorf("the objects did not take the chunk: %w", err)
|
return Received{}, fmt.Errorf("the objects did not take the chunk: %w", err)
|
||||||
}
|
}
|
||||||
|
// A transfer read back from a key-value state has no Chunks until one was taken: the empty map is kept omitted.
|
||||||
|
if t.Chunks == nil {
|
||||||
|
t.Chunks = map[string]int{}
|
||||||
|
}
|
||||||
t.Chunks[digest] = sequence + 1
|
t.Chunks[digest] = sequence + 1
|
||||||
t.Last = r.now()
|
t.Last = r.now()
|
||||||
if last {
|
if last {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package parts
|
|||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -28,14 +29,31 @@ func (m memObjects) Used() (uint64, error) {
|
|||||||
return u, nil
|
return u, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type memTransfers[M any] map[string]Transfer[M]
|
// memTransfers keeps each transfer as the bus keeps it, its JSON, so every case reads back what a key-value state
|
||||||
|
// gives (BusTransfers): an empty map kept with omitempty comes back nil.
|
||||||
|
type memTransfers[M any] map[string][]byte
|
||||||
|
|
||||||
func (m memTransfers[M]) Get(id string) (Transfer[M], bool, error) { t, ok := m[id]; return t, ok, nil }
|
func (m memTransfers[M]) Get(id string) (Transfer[M], bool, error) {
|
||||||
func (m memTransfers[M]) Put(t Transfer[M]) error { m[t.ID] = t; return nil }
|
var t Transfer[M]
|
||||||
func (m memTransfers[M]) Delete(id string) error { delete(m, id); return nil }
|
raw, ok := m[id]
|
||||||
|
if !ok {
|
||||||
|
return t, false, nil
|
||||||
|
}
|
||||||
|
return t, true, json.Unmarshal(raw, &t)
|
||||||
|
}
|
||||||
|
func (m memTransfers[M]) Put(t Transfer[M]) error {
|
||||||
|
raw, err := json.Marshal(t)
|
||||||
|
m[t.ID] = raw
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
func (m memTransfers[M]) Delete(id string) error { delete(m, id); return nil }
|
||||||
func (m memTransfers[M]) List() ([]Transfer[M], error) {
|
func (m memTransfers[M]) List() ([]Transfer[M], error) {
|
||||||
var out []Transfer[M]
|
var out []Transfer[M]
|
||||||
for _, t := range m {
|
for id := range m {
|
||||||
|
t, _, err := m.Get(id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
out = append(out, t)
|
out = append(out, t)
|
||||||
}
|
}
|
||||||
return out, nil
|
return out, nil
|
||||||
|
|||||||
Reference in New Issue
Block a user