Removed legacy interfaces and old documentation references to the previous on-disk layout
This commit is contained in:
@@ -30,18 +30,13 @@ func NewLocalStore(workspaceRoot string) *LocalStore {
|
||||
return &LocalStore{WorkspaceRoot: workspaceRoot}
|
||||
}
|
||||
|
||||
// SessionPaths resolves legacy paths for a session workdir.
|
||||
func (s *LocalStore) SessionPaths(sessionID string) SessionPaths {
|
||||
return buildLegacySessionPaths(s.WorkspaceRoot, sessionID)
|
||||
}
|
||||
|
||||
// SessionPathsFor resolves canonical campaign-aware paths for a session workdir.
|
||||
func (s *LocalStore) SessionPathsFor(campaign, sessionID string) SessionPaths {
|
||||
return buildSessionPaths(s.WorkspaceRoot, campaign, sessionID)
|
||||
}
|
||||
|
||||
// ResolveSessionPathsFor resolves the active session path with legacy compatibility.
|
||||
func (s *LocalStore) ResolveSessionPathsFor(campaign, sessionID string) (SessionPaths, error) {
|
||||
// EnsureLayoutFor creates and verifies campaign-aware session layout.
|
||||
func (s *LocalStore) EnsureLayoutFor(campaign, sessionID string) (SessionPaths, error) {
|
||||
if strings.TrimSpace(s.WorkspaceRoot) == "" {
|
||||
return SessionPaths{}, fmt.Errorf("workspace root is required")
|
||||
}
|
||||
@@ -51,50 +46,10 @@ func (s *LocalStore) ResolveSessionPathsFor(campaign, sessionID string) (Session
|
||||
|
||||
campaign = strings.TrimSpace(campaign)
|
||||
if campaign == "" {
|
||||
return s.SessionPaths(sessionID), nil
|
||||
return SessionPaths{}, fmt.Errorf("campaign is required")
|
||||
}
|
||||
|
||||
canonical := s.SessionPathsFor(campaign, sessionID)
|
||||
legacy := s.SessionPaths(sessionID)
|
||||
canonicalExists, err := dirExists(canonical.Root)
|
||||
if err != nil {
|
||||
return SessionPaths{}, fmt.Errorf("check canonical session root %q: %w", canonical.Root, err)
|
||||
}
|
||||
legacyExists, err := dirExists(legacy.Root)
|
||||
if err != nil {
|
||||
return SessionPaths{}, fmt.Errorf("check legacy session root %q: %w", legacy.Root, err)
|
||||
}
|
||||
|
||||
switch {
|
||||
case canonicalExists && legacyExists:
|
||||
return SessionPaths{}, fmt.Errorf(
|
||||
"ambiguous session workspace roots for campaign %q session %q: canonical=%q legacy=%q",
|
||||
campaign,
|
||||
sessionID,
|
||||
canonical.Root,
|
||||
legacy.Root,
|
||||
)
|
||||
case canonicalExists:
|
||||
return canonical, nil
|
||||
case legacyExists:
|
||||
return legacy, nil
|
||||
default:
|
||||
return canonical, nil
|
||||
}
|
||||
}
|
||||
|
||||
// EnsureLayout creates and verifies the canonical session workdir directory layout.
|
||||
func (s *LocalStore) EnsureLayout(sessionID string) (SessionPaths, error) {
|
||||
return s.ensureLayout(s.SessionPaths(sessionID))
|
||||
}
|
||||
|
||||
// EnsureLayoutFor creates and verifies campaign-aware session layout, with controlled legacy compatibility.
|
||||
func (s *LocalStore) EnsureLayoutFor(campaign, sessionID string) (SessionPaths, error) {
|
||||
paths, err := s.ResolveSessionPathsFor(campaign, sessionID)
|
||||
if err != nil {
|
||||
return SessionPaths{}, err
|
||||
}
|
||||
return s.ensureLayout(paths)
|
||||
return s.ensureLayout(s.SessionPathsFor(campaign, sessionID))
|
||||
}
|
||||
|
||||
func (s *LocalStore) ensureLayout(paths SessionPaths) (SessionPaths, error) {
|
||||
@@ -129,15 +84,6 @@ func (s *LocalStore) ensureLayout(paths SessionPaths) (SessionPaths, error) {
|
||||
return paths, nil
|
||||
}
|
||||
|
||||
// CopyInput copies an input file into the session workdir under destRelativePath.
|
||||
func (s *LocalStore) CopyInput(sessionID, srcPath, destRelativePath string) (Ref, error) {
|
||||
paths, err := s.EnsureLayout(sessionID)
|
||||
if err != nil {
|
||||
return Ref{}, err
|
||||
}
|
||||
return s.copyInputWithPaths(paths, sessionID, srcPath, destRelativePath)
|
||||
}
|
||||
|
||||
// CopyInputFor copies an input file into the campaign-aware session workdir under destRelativePath.
|
||||
func (s *LocalStore) CopyInputFor(campaign, sessionID, srcPath, destRelativePath string) (Ref, error) {
|
||||
paths, err := s.EnsureLayoutFor(campaign, sessionID)
|
||||
@@ -248,15 +194,6 @@ func (s *LocalStore) Checksum(path string) (string, error) {
|
||||
return digest, nil
|
||||
}
|
||||
|
||||
// AcquireSessionLock acquires an exclusive lock file for a session workdir.
|
||||
func (s *LocalStore) AcquireSessionLock(sessionID string) (*LockHandle, error) {
|
||||
paths, err := s.EnsureLayout(sessionID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.acquireSessionLockForPaths(paths)
|
||||
}
|
||||
|
||||
// AcquireSessionLockFor acquires an exclusive lock file for a campaign/session workdir.
|
||||
func (s *LocalStore) AcquireSessionLockFor(campaign, sessionID string) (*LockHandle, error) {
|
||||
paths, err := s.EnsureLayoutFor(campaign, sessionID)
|
||||
@@ -290,17 +227,6 @@ func (s *LocalStore) acquireSessionLockForPaths(paths SessionPaths) (*LockHandle
|
||||
return &LockHandle{path: paths.LockPath, file: f}, nil
|
||||
}
|
||||
|
||||
func dirExists(path string) (bool, error) {
|
||||
info, err := os.Stat(path)
|
||||
if err == nil {
|
||||
return info.IsDir(), nil
|
||||
}
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
return false, nil
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
|
||||
// ReleaseSessionLock releases a previously acquired session lock.
|
||||
func (s *LocalStore) ReleaseSessionLock(lock *LockHandle) error {
|
||||
if lock == nil {
|
||||
|
||||
@@ -36,40 +36,14 @@ func TestEnsureLayoutCreatesExpectedDirectories(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveSessionPathsForLegacyFallback(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
store := NewLocalStore(root)
|
||||
legacyRoot := SessionWorkDir(root, "session-1")
|
||||
if err := os.MkdirAll(legacyRoot, 0o755); err != nil {
|
||||
t.Fatalf("MkdirAll() error = %v", err)
|
||||
}
|
||||
|
||||
paths, err := store.ResolveSessionPathsFor("sample-campaign", "session-1")
|
||||
if err != nil {
|
||||
t.Fatalf("ResolveSessionPathsFor() error = %v", err)
|
||||
}
|
||||
if paths.Root != legacyRoot {
|
||||
t.Fatalf("paths.Root = %q, want legacy root %q", paths.Root, legacyRoot)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveSessionPathsForAmbiguousRoots(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
store := NewLocalStore(root)
|
||||
legacyRoot := SessionWorkDir(root, "session-1")
|
||||
canonicalRoot := SessionWorkDirForCampaign(root, "sample-campaign", "session-1")
|
||||
for _, dir := range []string{legacyRoot, canonicalRoot} {
|
||||
if err := os.MkdirAll(dir, 0o755); err != nil {
|
||||
t.Fatalf("MkdirAll(%q) error = %v", dir, err)
|
||||
}
|
||||
}
|
||||
|
||||
_, err := store.ResolveSessionPathsFor("sample-campaign", "session-1")
|
||||
func TestEnsureLayoutForRequiresCampaign(t *testing.T) {
|
||||
store := NewLocalStore(t.TempDir())
|
||||
_, err := store.EnsureLayoutFor("", "session-1")
|
||||
if err == nil {
|
||||
t.Fatal("expected ambiguity error, got nil")
|
||||
t.Fatal("expected campaign-required error, got nil")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "ambiguous session workspace roots") {
|
||||
t.Fatalf("error = %v, want ambiguity message", err)
|
||||
if !strings.Contains(err.Error(), "campaign is required") {
|
||||
t.Fatalf("error = %v, want campaign-required error", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,11 +27,6 @@ type SessionPaths struct {
|
||||
LockPath string
|
||||
}
|
||||
|
||||
// SessionWorkDir returns the legacy work directory for one session.
|
||||
func SessionWorkDir(rootDir, sessionID string) string {
|
||||
return filepath.Join(rootDir, config.PathWorkDirSegment, sessionID)
|
||||
}
|
||||
|
||||
// SessionWorkDirForCampaign returns the canonical campaign-aware work directory for one session.
|
||||
func SessionWorkDirForCampaign(rootDir, campaign, sessionID string) string {
|
||||
return filepath.Join(rootDir, config.PathWorkDirSegment, campaign, sessionID)
|
||||
@@ -62,21 +57,11 @@ func SessionRunStageDirForCampaign(rootDir, campaign, sessionID, runID, stageNam
|
||||
return filepath.Join(SessionRunRootForCampaign(rootDir, campaign, sessionID, runID), stageName)
|
||||
}
|
||||
|
||||
// SessionRunWorkDir returns the legacy campaign/session/run scoped local work directory.
|
||||
func SessionRunWorkDir(rootDir, campaign, sessionID, runID string) string {
|
||||
return filepath.Join(rootDir, config.PathWorkDirSegment, campaign, sessionID, runID)
|
||||
}
|
||||
|
||||
// SessionSpoolAudioDir returns the campaign/session/run scoped local spool audio path.
|
||||
func SessionSpoolAudioDir(spoolRoot, campaign, sessionID, runID string) string {
|
||||
return filepath.Join(spoolRoot, campaign, sessionID, runID, config.PathAudioDirSegment)
|
||||
}
|
||||
|
||||
func buildLegacySessionPaths(workspaceRoot, sessionID string) SessionPaths {
|
||||
root := SessionWorkDir(workspaceRoot, sessionID)
|
||||
return buildSessionPathsFromRoot(workspaceRoot, "", sessionID, root)
|
||||
}
|
||||
|
||||
func buildSessionPaths(workspaceRoot, campaign, sessionID string) SessionPaths {
|
||||
root := SessionWorkDirForCampaign(workspaceRoot, campaign, sessionID)
|
||||
return buildSessionPathsFromRoot(workspaceRoot, campaign, sessionID, root)
|
||||
|
||||
@@ -5,15 +5,6 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSessionRunWorkDir(t *testing.T) {
|
||||
root := "/tmp/workspace"
|
||||
got := SessionRunWorkDir(root, "forsaken", "2026-04-19", "20260515T031522Z-a1b2c3d4")
|
||||
want := filepath.Join(root, "work", "forsaken", "2026-04-19", "20260515T031522Z-a1b2c3d4")
|
||||
if got != want {
|
||||
t.Fatalf("SessionRunWorkDir() = %q, want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSessionWorkDirForCampaign(t *testing.T) {
|
||||
root := "/tmp/workspace"
|
||||
got := SessionWorkDirForCampaign(root, "forsaken", "2026-04-19")
|
||||
|
||||
@@ -11,36 +11,16 @@ type S3Store struct {
|
||||
Prefix string
|
||||
}
|
||||
|
||||
// SessionPaths is not implemented for S3-backed storage.
|
||||
func (s *S3Store) SessionPaths(_ string) SessionPaths {
|
||||
return SessionPaths{}
|
||||
}
|
||||
|
||||
// SessionPathsFor is not implemented for S3-backed storage.
|
||||
func (s *S3Store) SessionPathsFor(_, _ string) SessionPaths {
|
||||
return SessionPaths{}
|
||||
}
|
||||
|
||||
// ResolveSessionPathsFor is not implemented for S3-backed storage.
|
||||
func (s *S3Store) ResolveSessionPathsFor(_, _ string) (SessionPaths, error) {
|
||||
return SessionPaths{}, fmt.Errorf("artifacts s3 resolve session paths: not yet implemented")
|
||||
}
|
||||
|
||||
// EnsureLayout returns a not-yet-implemented error in the scaffold.
|
||||
func (s *S3Store) EnsureLayout(_ string) (SessionPaths, error) {
|
||||
return SessionPaths{}, fmt.Errorf("artifacts s3 ensure layout: not yet implemented")
|
||||
}
|
||||
|
||||
// EnsureLayoutFor returns a not-yet-implemented error in the scaffold.
|
||||
func (s *S3Store) EnsureLayoutFor(_, _ string) (SessionPaths, error) {
|
||||
return SessionPaths{}, fmt.Errorf("artifacts s3 ensure layout for campaign/session: not yet implemented")
|
||||
}
|
||||
|
||||
// CopyInput returns a not-yet-implemented error in the scaffold.
|
||||
func (s *S3Store) CopyInput(_, _, _ string) (Ref, error) {
|
||||
return Ref{}, fmt.Errorf("artifacts s3 copy input: not yet implemented")
|
||||
}
|
||||
|
||||
// CopyInputFor returns a not-yet-implemented error in the scaffold.
|
||||
func (s *S3Store) CopyInputFor(_, _, _, _ string) (Ref, error) {
|
||||
return Ref{}, fmt.Errorf("artifacts s3 copy input for campaign/session: not yet implemented")
|
||||
@@ -66,11 +46,6 @@ func (s *S3Store) Checksum(_ string) (string, error) {
|
||||
return "", fmt.Errorf("artifacts s3 checksum: not yet implemented")
|
||||
}
|
||||
|
||||
// AcquireSessionLock returns a not-yet-implemented error in the scaffold.
|
||||
func (s *S3Store) AcquireSessionLock(_ string) (*LockHandle, error) {
|
||||
return nil, fmt.Errorf("artifacts s3 acquire lock: not yet implemented")
|
||||
}
|
||||
|
||||
// AcquireSessionLockFor returns a not-yet-implemented error in the scaffold.
|
||||
func (s *S3Store) AcquireSessionLockFor(_, _ string) (*LockHandle, error) {
|
||||
return nil, fmt.Errorf("artifacts s3 acquire lock for campaign/session: not yet implemented")
|
||||
|
||||
@@ -15,18 +15,13 @@ type Ref struct {
|
||||
|
||||
// Store is the local artifact/workdir abstraction used by orchestration code.
|
||||
type Store interface {
|
||||
SessionPaths(sessionID string) SessionPaths
|
||||
SessionPathsFor(campaign, sessionID string) SessionPaths
|
||||
ResolveSessionPathsFor(campaign, sessionID string) (SessionPaths, error)
|
||||
EnsureLayout(sessionID string) (SessionPaths, error)
|
||||
EnsureLayoutFor(campaign, sessionID string) (SessionPaths, error)
|
||||
CopyInput(sessionID, srcPath, destRelativePath string) (Ref, error)
|
||||
CopyInputFor(campaign, sessionID, srcPath, destRelativePath string) (Ref, error)
|
||||
Exists(path string) (bool, error)
|
||||
ExistsRef(ref Ref) (bool, error)
|
||||
WriteFileAtomic(path string, data []byte, perm os.FileMode) error
|
||||
Checksum(path string) (string, error)
|
||||
AcquireSessionLock(sessionID string) (*LockHandle, error)
|
||||
AcquireSessionLockFor(campaign, sessionID string) (*LockHandle, error)
|
||||
ReleaseSessionLock(lock *LockHandle) error
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user