Add immutable remote commit reader
This commit is contained in:
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"gitea.maximumdirect.net/eric/narratio/internal/adapters/storage"
|
||||
@@ -44,8 +43,11 @@ type CurrentState struct {
|
||||
SessionPrefix string
|
||||
CurrentRunIDKey string
|
||||
CurrentManifestKey string
|
||||
CurrentPointerKey string
|
||||
RunID string
|
||||
Manifest *manifest.Manifest
|
||||
Commit *RemoteCommitManifest
|
||||
Pointer *CurrentCommitPointer
|
||||
}
|
||||
|
||||
type CurrentStateValidation struct {
|
||||
@@ -55,74 +57,6 @@ type CurrentStateValidation struct {
|
||||
ValidateRunID bool
|
||||
}
|
||||
|
||||
func LoadCurrentRunPointer(ctx context.Context, store storage.ObjectStore, currentRunIDKey string) (string, error) {
|
||||
if store == nil {
|
||||
return "", fmt.Errorf("object store is required")
|
||||
}
|
||||
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}
|
||||
}
|
||||
|
||||
localPath, err := storage.DownloadObjectToTemp(ctx, store, key, "narratio-current-run-id-*.txt")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("download current run pointer %q: %w", key, err)
|
||||
}
|
||||
defer func() { _ = os.Remove(localPath) }()
|
||||
|
||||
data, err := os.ReadFile(localPath)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("read downloaded 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 LoadCurrentManifest(ctx context.Context, store storage.ObjectStore, currentManifestKey string) (*manifest.Manifest, error) {
|
||||
if store == nil {
|
||||
return nil, fmt.Errorf("object store is required")
|
||||
}
|
||||
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-current-manifest-*.json")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("download current manifest %q: %w", key, err)
|
||||
}
|
||||
defer func() { _ = os.Remove(localPath) }()
|
||||
|
||||
manifestStore := &manifest.LocalStore{}
|
||||
m, err := manifestStore.Load(ctx, localPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("current manifest decode failed: %w", err)
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func LoadCurrentState(
|
||||
ctx context.Context,
|
||||
store storage.ObjectStore,
|
||||
@@ -133,27 +67,19 @@ func LoadCurrentState(
|
||||
if prefix == "" {
|
||||
return nil, fmt.Errorf("session prefix is required")
|
||||
}
|
||||
currentManifestKey, currentRunIDKey := ResolveCurrentStateKeys(prefix)
|
||||
runID, err := LoadCurrentRunPointer(ctx, store, currentRunIDKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m, err := LoadCurrentManifest(ctx, store, currentManifestKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if store == nil {
|
||||
return nil, fmt.Errorf("object store is required")
|
||||
}
|
||||
|
||||
state := &CurrentState{
|
||||
SessionPrefix: prefix,
|
||||
CurrentRunIDKey: currentRunIDKey,
|
||||
CurrentManifestKey: currentManifestKey,
|
||||
RunID: runID,
|
||||
Manifest: m,
|
||||
pointerKey := S3CurrentCommitPointerKey(prefix)
|
||||
pointerExists, err := store.Exists(ctx, pointerKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("check current commit pointer %q: %w", pointerKey, err)
|
||||
}
|
||||
if err := ValidateCurrentStateIdentity(state, validation); err != nil {
|
||||
return nil, err
|
||||
if pointerExists {
|
||||
return loadCommittedCurrentState(ctx, store, prefix, pointerKey, validation)
|
||||
}
|
||||
return state, nil
|
||||
return loadLegacyCurrentState(ctx, store, prefix, validation)
|
||||
}
|
||||
|
||||
func ValidateCurrentStateIdentity(state *CurrentState, validation CurrentStateValidation) error {
|
||||
|
||||
Reference in New Issue
Block a user