package session import ( "context" "encoding/json" "fmt" "os" "path/filepath" "github.com/paramah/ai_devs4/s01e03/internal/domain" ) // FileStorage implements domain.SessionStorage using JSON files type FileStorage struct { baseDir string } // NewFileStorage creates a new file-based session storage func NewFileStorage(baseDir string) *FileStorage { return &FileStorage{ baseDir: baseDir, } } // Get retrieves a session from file storage func (s *FileStorage) Get(ctx context.Context, sessionID string) (*domain.Session, error) { filePath := s.getFilePath(sessionID) // Check if file exists if _, err := os.Stat(filePath); os.IsNotExist(err) { // Return empty session if file doesn't exist return &domain.Session{ ID: sessionID, Messages: []domain.Message{}, }, nil } data, err := os.ReadFile(filePath) if err != nil { return nil, fmt.Errorf("reading session file: %w", err) } var session domain.Session if err := json.Unmarshal(data, &session); err != nil { return nil, fmt.Errorf("unmarshaling session: %w", err) } return &session, nil } // Save saves a session to file storage func (s *FileStorage) Save(ctx context.Context, session *domain.Session) error { filePath := s.getFilePath(session.ID) // Ensure directory exists if err := os.MkdirAll(s.baseDir, 0755); err != nil { return fmt.Errorf("creating cache directory: %w", err) } data, err := json.MarshalIndent(session, "", " ") if err != nil { return fmt.Errorf("marshaling session: %w", err) } if err := os.WriteFile(filePath, data, 0644); err != nil { return fmt.Errorf("writing session file: %w", err) } return nil } func (s *FileStorage) getFilePath(sessionID string) string { return filepath.Join(s.baseDir, fmt.Sprintf("%s.json", sessionID)) }