diff --git a/go/stateobjects/send.go b/go/stateobjects/send.go index 2f6d98e7..ac0c4292 100644 --- a/go/stateobjects/send.go +++ b/go/stateobjects/send.go @@ -110,7 +110,8 @@ func (s Sender) Send(label string, body []byte) ([]byte, error) { } ref := Ref{Store: s.Store, Object: objectName(label, digestOf(body)), Size: int64(len(body)), Digest: digestOf(body), Form: FormVersion} if err := s.Objects.Put(ref.Object, body); err != nil { - return nil, fmt.Errorf("the object for %s: %w", label, err) + // A send refused at its store's cap fails loudly, naming the store (design 47 G §477, §59). + return nil, fmt.Errorf("the object for %s in the sent store %s: %w", label, s.Store, err) } if s.Log != nil { if err := s.record(ref.Object); err != nil { diff --git a/go/stateobjects/values_integration_test.go b/go/stateobjects/values_integration_test.go index ab86aa0b..dd6e4efb 100644 --- a/go/stateobjects/values_integration_test.go +++ b/go/stateobjects/values_integration_test.go @@ -56,6 +56,17 @@ func TestStateObjectsWholeAgainstTheBus(t *testing.T) { } } }) + // G §477: a send past a fixture's cap fails its reply or event, naming the store. + t.Run("a send past the sent store's cap names the store", func(t *testing.T) { + small, err := js.CreateObjectStore(ctx, jetstream.ObjectStoreConfig{Bucket: "n_sent-objects", Storage: jetstream.MemoryStorage, MaxBytes: 1 << 20}) + if err != nil { + t.Fatal(err) + } + s := Sender{Objects: BusObjects{Store: small}, Store: "n_sent-objects", Limit: int(nc.MaxPayload())} + if _, err := s.Send("reply.list", []byte(`{"text":"`+strings.Repeat("y", 2<<20)+`"}`)); err == nil || !strings.Contains(err.Error(), "n_sent-objects") { + t.Fatalf("a send past the cap: %v, want it refused naming n_sent-objects", err) + } + }) t.Run("values of 1x, 10x and 100x the limit", func(t *testing.T) { valueRows(t, OverBus(kv, store, "m_views-objects"), 1, 10, 100) }) t.Run("the tools read and drop what a deleted key left", func(t *testing.T) { v := OverBus(kv, store, "m_views-objects")