Files
narratio/internal/artifacts/current_state_legacy.go

99 lines
2.9 KiB
Go

package artifacts
import (
"context"
"fmt"
"os"
"strings"
"gitea.maximumdirect.net/eric/narratio/internal/adapters/storage"
"gitea.maximumdirect.net/eric/narratio/internal/manifest"
)
// This file is temporary compatibility support for sessions published before
// immutable current commits. It can be removed after legacy remote state is migrated.
func loadLegacyCurrentState(
ctx context.Context,
store storage.ObjectStore,
sessionPrefix string,
validation CurrentStateValidation,
) (*CurrentState, error) {
currentManifestKey, currentRunIDKey := ResolveCurrentStateKeys(sessionPrefix)
runID, err := loadLegacyCurrentRunPointer(ctx, store, currentRunIDKey)
if err != nil {
return nil, err
}
m, err := loadLegacyCurrentManifest(ctx, store, currentManifestKey)
if err != nil {
return nil, err
}
state := &CurrentState{
SessionPrefix: sessionPrefix,
CurrentRunIDKey: currentRunIDKey,
CurrentManifestKey: currentManifestKey,
RunID: runID,
Manifest: m,
}
if err := ValidateCurrentStateIdentity(state, validation); err != nil {
return nil, err
}
return state, nil
}
func loadLegacyCurrentRunPointer(ctx context.Context, store storage.ObjectStore, currentRunIDKey string) (string, error) {
key := strings.TrimSpace(currentRunIDKey)
if key == "" {
return "", fmt.Errorf("current run pointer key is required")
}
exists, err := store.Exists(ctx, key)
if err != nil {
return "", fmt.Errorf("check current run pointer %q: %w", key, err)
}
if !exists {
return "", &CurrentRunPointerMissingError{Key: key}
}
data, err := downloadRemoteObject(ctx, store, key, "narratio-legacy-current-run-id-*.txt")
if err != nil {
return "", fmt.Errorf("download current run pointer %q: %w", key, err)
}
runID := strings.TrimSpace(string(data))
if runID == "" {
return "", fmt.Errorf("current run pointer %q is empty", key)
}
if err := ValidateRunIdentity(runID); err != nil {
return "", fmt.Errorf("current run pointer %q contains an unsafe legacy run id; migrate remote state before use: %w", key, err)
}
return runID, nil
}
func loadLegacyCurrentManifest(ctx context.Context, store storage.ObjectStore, currentManifestKey string) (*manifest.Manifest, error) {
key := strings.TrimSpace(currentManifestKey)
if key == "" {
return nil, fmt.Errorf("current manifest key is required")
}
exists, err := store.Exists(ctx, key)
if err != nil {
return nil, fmt.Errorf("check current manifest %q: %w", key, err)
}
if !exists {
return nil, &CurrentManifestMissingError{Key: key}
}
localPath, err := storage.DownloadObjectToTemp(ctx, store, key, "narratio-legacy-current-manifest-*.json")
if err != nil {
return nil, fmt.Errorf("download current manifest %q: %w", key, err)
}
defer func() { _ = os.Remove(localPath) }()
m, err := (&manifest.LocalStore{}).Load(ctx, localPath)
if err != nil {
return nil, fmt.Errorf("current manifest decode failed: %w", err)
}
return m, nil
}