From 7a4997edd9dfb3bb7d7c3b182362d02c5cfac2ed Mon Sep 17 00:00:00 2001 From: Virgil Date: Sat, 4 Apr 2026 08:17:20 +0000 Subject: [PATCH] feat(workspace): add explicit orphan-preserving close Co-Authored-By: Virgil --- workspace.go | 7 +++++++ workspace_test.go | 26 ++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/workspace.go b/workspace.go index 4e4a55c..1745c34 100644 --- a/workspace.go +++ b/workspace.go @@ -63,6 +63,13 @@ func (workspace *Workspace) DatabasePath() string { return workspace.databasePath } +// Usage example: `if err := workspace.Close(); err != nil { return }` +// Close releases the workspace database handle but keeps the on-disk file so a +// later store instance can recover it as an orphan. +func (workspace *Workspace) Close() error { + return workspace.closeWithoutRemovingFiles() +} + func (workspace *Workspace) ensureReady(operation string) error { if workspace == nil { return core.E(operation, "workspace is nil", nil) diff --git a/workspace_test.go b/workspace_test.go index 72359d0..56f0b2f 100644 --- a/workspace_test.go +++ b/workspace_test.go @@ -177,6 +177,32 @@ func TestWorkspace_Discard_Good_Idempotent(t *testing.T) { assert.False(t, testFilesystem().Exists(workspace.databasePath)) } +func TestWorkspace_Close_Good_PreservesFileForRecovery(t *testing.T) { + stateDirectory := useWorkspaceStateDirectory(t) + + storeInstance, err := New(":memory:") + require.NoError(t, err) + defer storeInstance.Close() + + workspace, err := storeInstance.NewWorkspace("close-session") + require.NoError(t, err) + + require.NoError(t, workspace.Put("like", map[string]any{"user": "@alice"})) + require.NoError(t, workspace.Close()) + + assert.True(t, testFilesystem().Exists(workspace.databasePath)) + + err = workspace.Put("like", map[string]any{"user": "@bob"}) + require.Error(t, err) + + orphans := storeInstance.RecoverOrphans(stateDirectory) + require.Len(t, orphans, 1) + assert.Equal(t, "close-session", orphans[0].Name()) + assert.Equal(t, map[string]any{"like": 1}, orphans[0].Aggregate()) + orphans[0].Discard() + assert.False(t, testFilesystem().Exists(workspace.databasePath)) +} + func TestWorkspace_RecoverOrphans_Good(t *testing.T) { stateDirectory := useWorkspaceStateDirectory(t)