feat: add chunked desktop client release uploads
Deployment Config CI / Deployment Config (push) Successful in 28s
Frontend CI / Frontend (push) Successful in 2m12s
Backend CI / Backend (push) Successful in 14m44s

This commit is contained in:
2026-06-01 01:31:54 +08:00
parent c5da0cf507
commit 76df672133
14 changed files with 1195 additions and 57 deletions
@@ -1,8 +1,13 @@
package app
import (
"bytes"
"context"
"crypto/sha256"
"encoding/hex"
"errors"
"io"
"os"
"testing"
"time"
@@ -213,9 +218,60 @@ func TestResolveDownloadURLResultUsesSignedDownloadURL(t *testing.T) {
require.Empty(t, storage.publicURLCalls)
}
func TestDesktopClientReleaseChunkedUploadCompletesOutOfOrder(t *testing.T) {
t.Parallel()
storage := &desktopReleaseDownloadURLStorage{
existsByKey: map[string]bool{},
objects: map[string][]byte{},
}
svc := NewDesktopClientReleaseService(nil, storage, nil).WithReleaseUploadDir(t.TempDir())
content := bytes.Repeat([]byte("release-package-"), 1024*1024)
sum := sha256.Sum256(content)
wantSHA := hex.EncodeToString(sum[:])
initResult, err := svc.InitiateChunkedUpload(context.Background(), DesktopClientReleaseChunkedUploadInitInput{
Platform: "darwin",
Arch: "arm64",
Channel: "stable",
Version: "1.2.3",
Kind: DesktopClientAssetKindInstaller,
FileName: "client.dmg",
FileSizeBytes: int64(len(content)),
ChunkSizeBytes: 5 * 1024 * 1024,
})
require.NoError(t, err)
require.Equal(t, 4, initResult.ChunkCount)
order := []int{2, 0, 3, 1}
for _, index := range order {
start := int64(index) * initResult.ChunkSizeBytes
end := min(start+initResult.ChunkSizeBytes, int64(len(content)))
result, err := svc.UploadChunk(context.Background(), DesktopClientReleaseChunkUploadInput{
UploadID: initResult.UploadID,
ChunkIndex: index,
ContentReader: bytes.NewReader(content[start:end]),
ContentSizeBytes: end - start,
})
require.NoError(t, err)
require.Equal(t, index, result.ChunkIndex)
}
result, err := svc.CompleteChunkedUpload(context.Background(), initResult.UploadID)
require.NoError(t, err)
require.Equal(t, wantSHA, result.SHA256)
require.Equal(t, int64(len(content)), result.FileSizeBytes)
require.Equal(t, "desktop-client/releases/blobs/"+wantSHA+".dmg", result.OSSObjectKey)
require.Equal(t, content, storage.objects[result.OSSObjectKey])
_, err = os.Stat(svc.desktopReleaseUploadSessionDir(initResult.UploadID))
require.True(t, errors.Is(err, os.ErrNotExist))
}
type desktopReleaseDownloadURLStorage struct {
publicURLCalls []string
downloadURLCalls []string
existsByKey map[string]bool
objects map[string][]byte
}
func (s *desktopReleaseDownloadURLStorage) Validate() error {
@@ -226,11 +282,30 @@ func (s *desktopReleaseDownloadURLStorage) PutBytes(context.Context, string, []b
return nil
}
func (s *desktopReleaseDownloadURLStorage) PutReader(_ context.Context, objectKey string, reader io.Reader, _ int64, _ string) error {
if s.objects == nil {
s.objects = map[string][]byte{}
}
content, err := io.ReadAll(reader)
if err != nil {
return err
}
s.objects[objectKey] = content
if s.existsByKey == nil {
s.existsByKey = map[string]bool{}
}
s.existsByKey[objectKey] = true
return nil
}
func (s *desktopReleaseDownloadURLStorage) GetBytes(context.Context, string) ([]byte, error) {
return nil, errors.New("not implemented")
}
func (s *desktopReleaseDownloadURLStorage) Exists(context.Context, string) (bool, error) {
func (s *desktopReleaseDownloadURLStorage) Exists(_ context.Context, objectKey string) (bool, error) {
if s.existsByKey != nil {
return s.existsByKey[objectKey], nil
}
return true, nil
}