Skip to content

Commit 6752a49

Browse files
fix: remove mandatory attrs response in MRD (#13585)
1 parent 1347004 commit 6752a49

File tree

2 files changed

+46
-25
lines changed

2 files changed

+46
-25
lines changed

storage/grpc_reader_multi_range.go

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,9 @@ func (c *grpcStorageClient) NewMultiRangeDownloader(ctx context.Context, params
115115
manager.wg.Wait()
116116
return nil, manager.permanentErr
117117
}
118-
mrd.Attrs = manager.attrs
118+
if manager.attrs != nil {
119+
mrd.Attrs = *manager.attrs
120+
}
119121
return mrd, nil
120122
case <-ctx.Done():
121123
cancel()
@@ -220,7 +222,7 @@ type multiRangeDownloaderManager struct {
220222
waiters []chan struct{}
221223
readSpec *storagepb.BidiReadObjectSpec
222224
lastReadHandle []byte
223-
attrs ReaderObjectAttrs
225+
attrs *ReaderObjectAttrs
224226
attrsReady chan struct{}
225227
attrsOnce sync.Once
226228
spanCtx context.Context
@@ -487,8 +489,8 @@ func (m *multiRangeDownloaderManager) handleAddCmd(ctx context.Context, cmd *mrd
487489
}
488490
m.readIDCounter++
489491

490-
// Attributes should be ready if we are processing Add commands
491-
if req.offset < 0 {
492+
// Convert to positive offset only if attributes are available.
493+
if m.attrs != nil && req.offset < 0 {
492494
err := m.convertToPositiveOffset(req)
493495
if err != nil {
494496
return
@@ -517,23 +519,20 @@ func (m *multiRangeDownloaderManager) convertToPositiveOffset(req *rangeRequest)
517519
if req.offset >= 0 {
518520
return nil
519521
}
520-
objSize := m.attrs.Size
521-
if objSize <= 0 {
522-
err := errors.New("storage: cannot resolve negative offset without object size")
523-
m.failRange(req, err)
524-
return err
522+
var objSize int64
523+
if m.attrs != nil {
524+
objSize = m.attrs.Size
525525
}
526-
if req.length != 0 {
527-
err := fmt.Errorf("storage: negative offset with non-zero length is not supported (offset: %d, length: %d)", req.origOffset, req.origLength)
526+
if objSize <= 0 {
527+
err := errors.New("storage: cannot resolve negative offset with object size as 0")
528528
m.failRange(req, err)
529529
return err
530530
}
531-
start := objSize + req.offset
532-
if start < 0 {
533-
start = 0
534-
}
531+
start := max(objSize+req.offset, 0)
535532
req.offset = start
536-
req.length = objSize - start
533+
if req.length == 0 {
534+
req.length = objSize - start
535+
}
537536
return nil
538537
}
539538

@@ -573,15 +572,12 @@ func (m *multiRangeDownloaderManager) processSessionResult(result mrdSessionResu
573572
if meta := resp.GetMetadata(); meta != nil {
574573
obj := newObjectFromProto(meta)
575574
attrs := readerAttrsFromObject(obj)
576-
m.attrs = attrs
577-
575+
m.attrs = &attrs
578576
for _, req := range m.pendingRanges {
579577
if req.offset < 0 {
580578
_ = m.convertToPositiveOffset(req)
581579
}
582580
}
583-
} else {
584-
m.handleStreamEnd(mrdSessionResult{err: errors.New("storage: first response from BidiReadObject stream missing metadata")})
585581
}
586582
})
587583

storage/integration_test.go

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -528,9 +528,10 @@ func TestIntegration_MRDCallbackReturnsDataLength(t *testing.T) {
528528
func TestIntegration_MRDWithReadHandle(t *testing.T) {
529529
multiTransportTest(skipAllButZonal(context.Background(), "Bidi Read API test"), t, func(t *testing.T, ctx context.Context, bucket string, _ string, client *Client) {
530530
const (
531-
dataSize = 1000
532-
offset = 0
533-
limit = 100
531+
dataSize = 1000
532+
offset = 0
533+
limit = 100
534+
negativeOffset = -200
534535
)
535536

536537
// Generate random content for testing.
@@ -562,7 +563,7 @@ func TestIntegration_MRDWithReadHandle(t *testing.T) {
562563
}
563564

564565
// Perform the read operation.
565-
var res1, res2 multiRangeDownloaderOutput
566+
var res1, res2, res3, res4 multiRangeDownloaderOutput
566567
mrd.Add(&res1.buf, offset, limit, func(x, y int64, err error) {
567568
res1.offset = x
568569
res1.limit = y
@@ -573,14 +574,28 @@ func TestIntegration_MRDWithReadHandle(t *testing.T) {
573574
res2.limit = y
574575
res2.err = err
575576
})
577+
mrd2.Add(&res3.buf, negativeOffset, limit, func(x, y int64, err error) {
578+
res3.offset = x
579+
res3.limit = y
580+
res3.err = err
581+
})
582+
mrd2.Add(&res4.buf, negativeOffset, 0, func(x, y int64, err error) {
583+
res4.offset = x
584+
res4.limit = y
585+
res4.err = err
586+
})
576587

577588
mrd.Wait()
578589
mrd2.Wait()
590+
579591
if res1.err != nil {
580592
t.Fatalf("mrd.Add callback returned error: %v", res1.err)
581593
}
582594
if res2.err != nil {
583-
t.Fatalf("mrd2.Add callback returned error: %v", res2.err)
595+
t.Fatalf("mrd2.Add callback returned error for res2: %v", res2.err)
596+
}
597+
if res3.err != nil {
598+
t.Fatalf("mrd2.Add callback returned error for res3: %v", res3.err)
584599
}
585600

586601
// Validate results for mrd with read handle.
@@ -593,6 +608,16 @@ func TestIntegration_MRDWithReadHandle(t *testing.T) {
593608
t.Errorf("mrd2 downloaded content mismatch. got %d bytes, want %d bytes", len(got), len(want))
594609
}
595610

611+
want = content[max(0, dataSize+negativeOffset):min(dataSize, max(0, dataSize+negativeOffset)+limit)]
612+
if got := res3.buf.Bytes(); !bytes.Equal(got, want) {
613+
t.Errorf("mrd2 downloaded content mismatch. got %v bytes, want %v bytes. %v", got, want, content)
614+
}
615+
616+
want = content[max(0, dataSize+negativeOffset):]
617+
if got := res4.buf.Bytes(); !bytes.Equal(got, want) {
618+
t.Errorf("mrd2 downloaded content mismatch. got %v bytes, want %v bytes. %v", got, want, content)
619+
}
620+
596621
if err := mrd.Close(); err != nil {
597622
t.Fatalf("Error while closing reader: %v", err)
598623
}

0 commit comments

Comments
 (0)