From 3e744bf31297a06dab29f9a6aee6018979433a3f Mon Sep 17 00:00:00 2001 From: Jeremie Fraeys Date: Wed, 18 Feb 2026 16:52:03 -0500 Subject: [PATCH] refactor: adopt PathRegistry in jupyter service_manager.go Update internal/jupyter/service_manager.go to use centralized PathRegistry: Changes: - Import config package for PathRegistry access - Update stateDir() to use config.FromEnv().JupyterStateDir() - Update workspaceBaseDir() to use config.FromEnv().ActiveDataDir() - Update trashBaseDir() to use config.FromEnv().JupyterStateDir() - Update NewServiceManager() to use PathRegistry for workspace metadata file - Update loadServices() to use PathRegistry for services file path - Update saveServices() to use PathRegistry with EnsureDir() - Rename parameter 'config' to 'svcConfig' to avoid shadowing import Benefits: - Consistent path management across codebase - Centralized directory creation with EnsureDir() - Environment variable override still supported (backward compatible) - Proper error handling for directory creation failures --- internal/jupyter/service_manager.go | 53 ++++++++++++++++++----------- 1 file changed, 34 insertions(+), 19 deletions(-) diff --git a/internal/jupyter/service_manager.go b/internal/jupyter/service_manager.go index f7c22e8..1b627cc 100644 --- a/internal/jupyter/service_manager.go +++ b/internal/jupyter/service_manager.go @@ -10,6 +10,7 @@ import ( "strings" "time" + "github.com/jfraeys/fetch_ml/internal/config" "github.com/jfraeys/fetch_ml/internal/container" "github.com/jfraeys/fetch_ml/internal/logging" ) @@ -32,22 +33,23 @@ const ( ) func stateDir() string { + // First check environment variable for backward compatibility if v := strings.TrimSpace(os.Getenv("FETCHML_JUPYTER_STATE_DIR")); v != "" { return v } - preferred := "/data/active/jupyter" - if err := os.MkdirAll(preferred, 0o750); err == nil { - return preferred - } - - return os.TempDir() + // Use PathRegistry for consistent path management + paths := config.FromEnv() + return paths.JupyterStateDir() } func workspaceBaseDir() string { + // First check environment variable for backward compatibility if v := strings.TrimSpace(os.Getenv("FETCHML_JUPYTER_WORKSPACE_BASE")); v != "" { return v } - return defaultWorkspaceBase + // Use PathRegistry for consistent path management + paths := config.FromEnv() + return paths.ActiveDataDir() } func resolveWorkspacePath(workspace string) (string, error) { @@ -72,11 +74,13 @@ func resolveWorkspacePath(workspace string) (string, error) { } func trashBaseDir() string { + // First check environment variable for backward compatibility if v := strings.TrimSpace(os.Getenv("FETCHML_JUPYTER_TRASH_DIR")); v != "" { return v } - // Default to state dir to keep behavior consistent across deployments. - return filepath.Join(stateDir(), "trash", "jupyter") + // Use PathRegistry for consistent path management + paths := config.FromEnv() + return filepath.Join(paths.JupyterStateDir(), "trash") } type trashInfo struct { @@ -332,14 +336,18 @@ type StartRequest struct { } // NewServiceManager creates a new Jupyter service manager -func NewServiceManager(logger *logging.Logger, config *ServiceConfig) (*ServiceManager, error) { +func NewServiceManager(logger *logging.Logger, svcConfig *ServiceConfig) (*ServiceManager, error) { podman, err := container.NewPodmanManager(logger) if err != nil { return nil, fmt.Errorf("failed to create podman manager: %w", err) } - // Initialize workspace metadata manager - dataFile := filepath.Join(stateDir(), "fetch_ml_jupyter_workspaces.json") + // Initialize workspace metadata manager using PathRegistry + paths := config.FromEnv() + dataFile := paths.JupyterWorkspacesFile() + if err := paths.EnsureDir(paths.JupyterStateDir()); err != nil { + return nil, fmt.Errorf("failed to create jupyter state directory: %w", err) + } workspaceMetadataMgr := NewWorkspaceMetadataManager(logger, dataFile) // Initialize security manager with enhanced config @@ -369,7 +377,7 @@ func NewServiceManager(logger *logging.Logger, config *ServiceConfig) (*ServiceM sm := &ServiceManager{ logger: logger, podman: podman, - config: config, + config: svcConfig, services: make(map[string]*JupyterService), workspaceMetadataMgr: workspaceMetadataMgr, securityMgr: securityMgr, @@ -1083,9 +1091,14 @@ func (sm *ServiceManager) waitForJupyterReady( return url, nil } -// loadServices loads existing services from disk +// loadServices loads existing services from disk using PathRegistry func (sm *ServiceManager) loadServices() error { - servicesFile := filepath.Join(stateDir(), "fetch_ml_jupyter_services.json") + paths := config.FromEnv() + servicesFile := paths.JupyterServicesFile() + + if err := paths.EnsureDir(paths.JupyterStateDir()); err != nil { + return fmt.Errorf("failed to create jupyter state directory: %w", err) + } data, err := os.ReadFile(servicesFile) if err != nil { @@ -1166,11 +1179,13 @@ func (sm *ServiceManager) loadServices() error { return nil } -// saveServices saves services to disk +// saveServices saves services to disk using PathRegistry func (sm *ServiceManager) saveServices() error { - servicesFile := filepath.Join(stateDir(), "fetch_ml_jupyter_services.json") - if err := os.MkdirAll(filepath.Dir(servicesFile), 0o750); err != nil { - return err + paths := config.FromEnv() + servicesFile := paths.JupyterServicesFile() + + if err := paths.EnsureDir(paths.JupyterStateDir()); err != nil { + return fmt.Errorf("failed to create jupyter state directory: %w", err) } data, err := json.MarshalIndent(sm.services, "", " ")