Skip to content

Commit 809a8c8

Browse files
authoredFeb 21, 2024··
azurestore: Buffer upload data on disk instead of in-memory (#1070)
Closes #1031
1 parent 9bcb112 commit 809a8c8

File tree

2 files changed

+43
-11
lines changed

2 files changed

+43
-11
lines changed
 

‎pkg/azurestore/azurestore.go

+37-10
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
package azurestore
22

33
import (
4-
"bufio"
54
"bytes"
65
"context"
7-
"encoding/binary"
86
"encoding/json"
7+
"errors"
98
"fmt"
109
"io"
10+
"io/fs"
11+
"os"
1112
"strings"
1213

1314
"github.com/tus/tusd/v2/internal/uid"
@@ -18,13 +19,20 @@ type AzureStore struct {
1819
Service AzService
1920
ObjectPrefix string
2021
Container string
22+
23+
// TemporaryDirectory is the path where AzureStore will create temporary files
24+
// on disk during the upload. An empty string ("", the default value) will
25+
// cause AzureStore to use the operating system's default temporary directory.
26+
TemporaryDirectory string
2127
}
2228

2329
type AzUpload struct {
2430
ID string
2531
InfoBlob AzBlob
2632
BlockBlob AzBlob
2733
InfoHandler *handler.FileInfo
34+
35+
tempDir string
2836
}
2937

3038
func New(service AzService) *AzureStore {
@@ -73,6 +81,7 @@ func (store AzureStore) NewUpload(ctx context.Context, info handler.FileInfo) (h
7381
InfoHandler: &info,
7482
InfoBlob: infoBlob,
7583
BlockBlob: blockBlob,
84+
tempDir: store.TemporaryDirectory,
7685
}
7786

7887
err = azUpload.writeInfo(ctx)
@@ -128,6 +137,7 @@ func (store AzureStore) GetUpload(ctx context.Context, id string) (handler.Uploa
128137
InfoHandler: &info,
129138
InfoBlob: infoBlob,
130139
BlockBlob: blockBlob,
140+
tempDir: store.TemporaryDirectory,
131141
}, nil
132142
}
133143

@@ -140,21 +150,38 @@ func (store AzureStore) AsLengthDeclarableUpload(upload handler.Upload) handler.
140150
}
141151

142152
func (upload *AzUpload) WriteChunk(ctx context.Context, offset int64, src io.Reader) (int64, error) {
143-
r := bufio.NewReader(src)
144-
buf := new(bytes.Buffer)
145-
n, err := r.WriteTo(buf)
153+
// Create a temporary file for holding the uploaded data
154+
file, err := os.CreateTemp(upload.tempDir, "tusd-az-tmp-")
155+
if err != nil {
156+
return 0, err
157+
}
158+
defer os.Remove(file.Name())
159+
160+
// Copy the entire request body into the file
161+
n, err := io.Copy(file, src)
146162
if err != nil {
163+
file.Close()
147164
return 0, err
148165
}
149166

150-
chunkSize := int64(binary.Size(buf.Bytes()))
151-
if chunkSize > MaxBlockBlobChunkSize {
152-
return 0, fmt.Errorf("azurestore: Chunk of size %v too large. Max chunk size is %v", chunkSize, MaxBlockBlobChunkSize)
167+
// Seek to the beginning
168+
if _, err := file.Seek(0, 0); err != nil {
169+
file.Close()
170+
return 0, err
171+
}
172+
173+
if n > MaxBlockBlobChunkSize {
174+
file.Close()
175+
return 0, fmt.Errorf("azurestore: Chunk of size %v too large. Max chunk size is %v", n, MaxBlockBlobChunkSize)
153176
}
154177

155-
re := bytes.NewReader(buf.Bytes())
156-
err = upload.BlockBlob.Upload(ctx, re)
178+
err = upload.BlockBlob.Upload(ctx, file)
157179
if err != nil {
180+
file.Close()
181+
return 0, err
182+
}
183+
184+
if err := file.Close(); err != nil && !errors.Is(err, fs.ErrClosed) {
158185
return 0, err
159186
}
160187

‎pkg/azurestore/azurestore_test.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,12 @@ func TestWriteChunk(t *testing.T) {
290290
infoBlob.EXPECT().Download(ctx).Return(newReadCloser(data), nil).Times(1),
291291
service.EXPECT().NewBlob(ctx, mockID).Return(blockBlob, nil).Times(1),
292292
blockBlob.EXPECT().GetOffset(ctx).Return(offset, nil).Times(1),
293-
blockBlob.EXPECT().Upload(ctx, bytes.NewReader([]byte(mockReaderData))).Return(nil).Times(1),
293+
blockBlob.EXPECT().Upload(ctx, gomock.Any()).DoAndReturn(func(_ context.Context, reader io.ReadSeeker) error {
294+
actual, err := io.ReadAll(reader)
295+
assert.Nil(err)
296+
assert.Equal(mockReaderData, string(actual))
297+
return nil
298+
}).Times(1),
294299
)
295300

296301
upload, err := store.GetUpload(ctx, mockID)

0 commit comments

Comments
 (0)
Please sign in to comment.