Complete artifact binary transfer streaming
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
@@ -24,6 +25,7 @@ type ArtifactBodyStore interface {
|
||||
PutPayload(string, []byte) error
|
||||
GetPayload(string) ([]byte, error)
|
||||
ReadPayloadRange(string, int64, int) ([]byte, error)
|
||||
OpenPayloadRange(string, int64, int64) (io.ReadCloser, error)
|
||||
CommitTransferPayload(domain.ArtifactTransferSession) error
|
||||
}
|
||||
|
||||
@@ -89,6 +91,17 @@ func (store *MemoryArtifactBodyStore) ReadPayloadRange(artifactID string, offset
|
||||
return domain.CopyBytes(payload[int(offset) : int(offset)+length]), nil
|
||||
}
|
||||
|
||||
func (store *MemoryArtifactBodyStore) OpenPayloadRange(artifactID string, offset int64, length int64) (io.ReadCloser, error) {
|
||||
if length < 0 || length > int64(int(^uint(0)>>1)) {
|
||||
return nil, fmt.Errorf("artifact range is invalid")
|
||||
}
|
||||
payload, err := store.ReadPayloadRange(artifactID, offset, int(length))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return io.NopCloser(bytes.NewReader(payload)), nil
|
||||
}
|
||||
|
||||
func (store *MemoryArtifactBodyStore) CommitTransferPayload(session domain.ArtifactTransferSession) error {
|
||||
store.mu.Lock()
|
||||
defer store.mu.Unlock()
|
||||
@@ -243,6 +256,40 @@ func (store *FileArtifactBodyStore) ReadPayloadRange(artifactID string, offset i
|
||||
return payload, nil
|
||||
}
|
||||
|
||||
func (store *FileArtifactBodyStore) OpenPayloadRange(artifactID string, offset int64, length int64) (io.ReadCloser, error) {
|
||||
if offset < 0 || length < 0 {
|
||||
return nil, fmt.Errorf("artifact range is invalid")
|
||||
}
|
||||
store.mu.Lock()
|
||||
defer store.mu.Unlock()
|
||||
file, err := os.Open(store.payloadPath(artifactID))
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
return nil, repo.ErrNotFound
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("open artifact payload: %w", err)
|
||||
}
|
||||
info, err := file.Stat()
|
||||
if err != nil {
|
||||
_ = file.Close()
|
||||
return nil, fmt.Errorf("stat artifact payload: %w", err)
|
||||
}
|
||||
if offset > info.Size() || length > info.Size()-offset {
|
||||
_ = file.Close()
|
||||
return nil, fmt.Errorf("artifact range is invalid")
|
||||
}
|
||||
return sectionReadCloser{SectionReader: io.NewSectionReader(file, offset, length), file: file}, nil
|
||||
}
|
||||
|
||||
type sectionReadCloser struct {
|
||||
*io.SectionReader
|
||||
file *os.File
|
||||
}
|
||||
|
||||
func (reader sectionReadCloser) Close() error {
|
||||
return reader.file.Close()
|
||||
}
|
||||
|
||||
func (store *FileArtifactBodyStore) CommitTransferPayload(session domain.ArtifactTransferSession) error {
|
||||
store.mu.Lock()
|
||||
defer store.mu.Unlock()
|
||||
|
||||
Reference in New Issue
Block a user