Validate downloads before installing workspace files
This commit is contained in:
@@ -70,12 +70,9 @@ func MaterializeS3Audio(ctx context.Context, req S3MaterializeRequest) (S3Materi
|
||||
if spoolPath == "" {
|
||||
return S3MaterializeResult{}, fmt.Errorf("spool path is required for s3 audio download")
|
||||
}
|
||||
if err := downloadObjectAtomic(ctx, req.Store, key, spoolPath); err != nil {
|
||||
if err := downloadObjectAtomic(ctx, req.Store, key, spoolPath, req.Object.Size); err != nil {
|
||||
return S3MaterializeResult{}, fmt.Errorf("download s3 audio object %q: %w", key, err)
|
||||
}
|
||||
if err := validateLocalAudio(spoolPath, req.Object.Size); err != nil {
|
||||
return S3MaterializeResult{}, fmt.Errorf("validate downloaded audio %q: %w", spoolPath, err)
|
||||
}
|
||||
|
||||
checksum, err := fileops.CopyFileAtomicWithChecksum(spoolPath, req.DestPath, fileops.WorkspaceFileMode)
|
||||
if err != nil {
|
||||
@@ -118,15 +115,47 @@ func validateLocalAudio(path string, expectedSize int64) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func downloadObjectAtomic(ctx context.Context, store storage.ObjectStore, key, destPath string) error {
|
||||
if strings.TrimSpace(destPath) == "" {
|
||||
return fmt.Errorf("destination path is required")
|
||||
}
|
||||
dir := filepath.Dir(destPath)
|
||||
if err := fileops.EnsureWorkspaceDirectory(dir); err != nil {
|
||||
return fmt.Errorf("create destination directory: %w", err)
|
||||
}
|
||||
return fileops.DownloadAndInstall(destPath, fileops.WorkspaceFileMode, func(destination io.Writer) error {
|
||||
func downloadObjectAtomic(ctx context.Context, store storage.ObjectStore, key, destPath string, expectedSize int64) error {
|
||||
temporaryPath, err := writeAudioTemp(destPath, func(destination io.Writer) error {
|
||||
return storage.DownloadTo(ctx, store, key, destination)
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() { _ = os.Remove(temporaryPath) }()
|
||||
if err := validateLocalAudio(temporaryPath, expectedSize); err != nil {
|
||||
return fmt.Errorf("validate downloaded audio: %w", err)
|
||||
}
|
||||
if err := fileops.InstallSiblingTempFile(temporaryPath, destPath, fileops.WorkspaceFileMode); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func writeAudioTemp(destination string, write func(io.Writer) error) (string, error) {
|
||||
if strings.TrimSpace(destination) == "" {
|
||||
return "", fmt.Errorf("destination path is required")
|
||||
}
|
||||
if write == nil {
|
||||
return "", fmt.Errorf("temporary audio writer is required")
|
||||
}
|
||||
dir := filepath.Dir(destination)
|
||||
if err := fileops.EnsureWorkspaceDirectory(dir); err != nil {
|
||||
return "", fmt.Errorf("create destination directory: %w", err)
|
||||
}
|
||||
temporary, err := os.CreateTemp(dir, "."+filepath.Base(destination)+".tmp-*")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("create sibling temporary file: %w", err)
|
||||
}
|
||||
temporaryPath := temporary.Name()
|
||||
if err := write(temporary); err != nil {
|
||||
_ = temporary.Close()
|
||||
_ = os.Remove(temporaryPath)
|
||||
return "", fmt.Errorf("write sibling temporary file: %w", err)
|
||||
}
|
||||
if err := temporary.Close(); err != nil {
|
||||
_ = os.Remove(temporaryPath)
|
||||
return "", fmt.Errorf("close sibling temporary file: %w", err)
|
||||
}
|
||||
return temporaryPath, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user