Implemented shared S3 audio caching for prepare and restore --include-audio
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
package artifacts
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
@@ -89,6 +91,44 @@ func SessionSpoolAudioDir(spoolRoot, campaign, sessionID, runID string) string {
|
||||
return filepath.Join(spoolRoot, campaign, sessionID, runID, config.PathAudioDirSegment)
|
||||
}
|
||||
|
||||
// SessionSpoolRestoreAudioDir returns the local spool audio path for restore downloads.
|
||||
func SessionSpoolRestoreAudioDir(spoolRoot, campaign, sessionID string) string {
|
||||
return filepath.Join(spoolRoot, campaign, sessionID, "restore", config.PathAudioDirSegment)
|
||||
}
|
||||
|
||||
// S3AudioCachePath returns the durable local cache path for one S3 audio object.
|
||||
func S3AudioCachePath(cacheRoot, bucket, key string) (string, error) {
|
||||
root := filepath.Clean(strings.TrimSpace(cacheRoot))
|
||||
if root == "." || root == "" {
|
||||
return "", fmt.Errorf("cache root is required")
|
||||
}
|
||||
bucket = strings.Trim(strings.TrimSpace(bucket), "/")
|
||||
if bucket == "" || bucket == "." || bucket == ".." || strings.Contains(bucket, "/") || strings.Contains(bucket, `\`) {
|
||||
return "", fmt.Errorf("bucket is required and must be a single path segment")
|
||||
}
|
||||
rawKey := strings.ReplaceAll(strings.TrimSpace(key), `\`, "/")
|
||||
if strings.HasPrefix(rawKey, "/") {
|
||||
return "", fmt.Errorf("s3 key must not be absolute")
|
||||
}
|
||||
cleanKey := cleanCacheS3Key(rawKey)
|
||||
if cleanKey == "" {
|
||||
return "", fmt.Errorf("s3 key is required")
|
||||
}
|
||||
if cleanKey == ".." || strings.HasPrefix(cleanKey, "../") || strings.HasPrefix(cleanKey, "/") {
|
||||
return "", fmt.Errorf("s3 key must not escape cache root")
|
||||
}
|
||||
return filepath.Join(root, "s3", bucket, filepath.FromSlash(cleanKey)), nil
|
||||
}
|
||||
|
||||
func cleanCacheS3Key(key string) string {
|
||||
normalized := strings.ReplaceAll(strings.TrimSpace(key), `\`, "/")
|
||||
normalized = strings.Trim(normalized, "/")
|
||||
if normalized == "" {
|
||||
return ""
|
||||
}
|
||||
return path.Clean(normalized)
|
||||
}
|
||||
|
||||
// SessionPreviousDir returns the previous-session state directory for already-resolved session paths.
|
||||
func SessionPreviousDir(paths SessionPaths) string {
|
||||
return paths.PreviousDir
|
||||
|
||||
Reference in New Issue
Block a user