Add support for tracking and persisting snapshot IDs
Introduce `currentSnapshotID` to track the active snapshot and persist its state in a file. This change ensures the current snapshot ID is restored during initialization and maintained consistently across snapshot operations.
This commit is contained in:
parent
3efa753394
commit
fb2ae39b47
89
api.go
89
api.go
@ -36,10 +36,12 @@ type AgateOptions struct {
|
|||||||
|
|
||||||
// Agate is the main entry point for the snapshot library.
|
// Agate is the main entry point for the snapshot library.
|
||||||
type Agate struct {
|
type Agate struct {
|
||||||
manager SnapshotManager
|
manager SnapshotManager
|
||||||
options AgateOptions
|
options AgateOptions
|
||||||
metadataDir string
|
metadataDir string
|
||||||
blobsDir string
|
blobsDir string
|
||||||
|
currentSnapshotID string
|
||||||
|
currentIDFile string
|
||||||
}
|
}
|
||||||
|
|
||||||
// New initializes a new instance of the Agate library with the given options.
|
// New initializes a new instance of the Agate library with the given options.
|
||||||
@ -90,16 +92,38 @@ func New(options AgateOptions) (*Agate, error) {
|
|||||||
return nil, fmt.Errorf("failed to create snapshot manager: %w", err)
|
return nil, fmt.Errorf("failed to create snapshot manager: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Agate{
|
// Create a file path for storing the current snapshot ID
|
||||||
manager: manager,
|
currentIDFile := filepath.Join(options.WorkDir, "current_snapshot_id")
|
||||||
options: options,
|
|
||||||
metadataDir: metadataDir,
|
agate := &Agate{
|
||||||
blobsDir: blobsDir,
|
manager: manager,
|
||||||
}, nil
|
options: options,
|
||||||
|
metadataDir: metadataDir,
|
||||||
|
blobsDir: blobsDir,
|
||||||
|
currentIDFile: currentIDFile,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load the current snapshot ID if it exists
|
||||||
|
if _, err := os.Stat(currentIDFile); err == nil {
|
||||||
|
data, err := os.ReadFile(currentIDFile)
|
||||||
|
if err == nil && len(data) > 0 {
|
||||||
|
agate.currentSnapshotID = string(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call OpenFunc if provided to initialize resources in the active directory
|
||||||
|
if options.OpenFunc != nil {
|
||||||
|
if err := options.OpenFunc(options.BlobStore.GetActiveDir()); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to open resources during initialization: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return agate, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SaveSnapshot creates a new snapshot from the current state of the active directory.
|
// SaveSnapshot creates a new snapshot from the current state of the active directory.
|
||||||
// If parentID is provided, it will be set as the parent of the new snapshot.
|
// If parentID is provided, it will be set as the parent of the new snapshot.
|
||||||
|
// If parentID is empty, it will use the ID of the snapshot currently loaded in the active directory.
|
||||||
// Returns the ID of the created snapshot.
|
// Returns the ID of the created snapshot.
|
||||||
func (a *Agate) SaveSnapshot(ctx context.Context, name string, parentID string) (string, error) {
|
func (a *Agate) SaveSnapshot(ctx context.Context, name string, parentID string) (string, error) {
|
||||||
// Call CloseFunc if provided
|
// Call CloseFunc if provided
|
||||||
@ -109,12 +133,23 @@ func (a *Agate) SaveSnapshot(ctx context.Context, name string, parentID string)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If parentID is not provided, use the current snapshot ID
|
||||||
|
effectiveParentID := parentID
|
||||||
|
|
||||||
// Create the snapshot
|
// Create the snapshot
|
||||||
snapshot, err := a.manager.CreateSnapshot(ctx, a.options.BlobStore.GetActiveDir(), name, parentID)
|
snapshot, err := a.manager.CreateSnapshot(ctx, a.options.BlobStore.GetActiveDir(), name, effectiveParentID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("failed to create snapshot: %w", err)
|
return "", fmt.Errorf("failed to create snapshot: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update the current snapshot ID to the newly created snapshot
|
||||||
|
a.currentSnapshotID = snapshot.ID
|
||||||
|
|
||||||
|
// Save the current snapshot ID to a file
|
||||||
|
if err := a.saveCurrentSnapshotID(); err != nil {
|
||||||
|
return "", fmt.Errorf("failed to save current snapshot ID: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
// Call OpenFunc if provided
|
// Call OpenFunc if provided
|
||||||
if a.options.OpenFunc != nil {
|
if a.options.OpenFunc != nil {
|
||||||
if err := a.options.OpenFunc(a.options.BlobStore.GetActiveDir()); err != nil {
|
if err := a.options.OpenFunc(a.options.BlobStore.GetActiveDir()); err != nil {
|
||||||
@ -139,6 +174,14 @@ func (a *Agate) RestoreSnapshot(ctx context.Context, snapshotID string) error {
|
|||||||
return fmt.Errorf("failed to extract snapshot: %w", err)
|
return fmt.Errorf("failed to extract snapshot: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Save the ID of the snapshot that was restored
|
||||||
|
a.currentSnapshotID = snapshotID
|
||||||
|
|
||||||
|
// Save the current snapshot ID to a file
|
||||||
|
if err := a.saveCurrentSnapshotID(); err != nil {
|
||||||
|
return fmt.Errorf("failed to save current snapshot ID: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
// Call OpenFunc if provided
|
// Call OpenFunc if provided
|
||||||
if a.options.OpenFunc != nil {
|
if a.options.OpenFunc != nil {
|
||||||
if err := a.options.OpenFunc(a.options.BlobStore.GetActiveDir()); err != nil {
|
if err := a.options.OpenFunc(a.options.BlobStore.GetActiveDir()); err != nil {
|
||||||
@ -163,6 +206,16 @@ func (a *Agate) RestoreSnapshotToDir(ctx context.Context, snapshotID string, dir
|
|||||||
return fmt.Errorf("failed to extract snapshot: %w", err)
|
return fmt.Errorf("failed to extract snapshot: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If restoring to the active directory, save the snapshot ID
|
||||||
|
if dir == a.options.BlobStore.GetActiveDir() {
|
||||||
|
a.currentSnapshotID = snapshotID
|
||||||
|
|
||||||
|
// Save the current snapshot ID to a file
|
||||||
|
if err := a.saveCurrentSnapshotID(); err != nil {
|
||||||
|
return fmt.Errorf("failed to save current snapshot ID: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Call OpenFunc if provided
|
// Call OpenFunc if provided
|
||||||
if a.options.OpenFunc != nil {
|
if a.options.OpenFunc != nil {
|
||||||
if err := a.options.OpenFunc(dir); err != nil {
|
if err := a.options.OpenFunc(dir); err != nil {
|
||||||
@ -188,6 +241,20 @@ func (a *Agate) DeleteSnapshot(ctx context.Context, snapshotID string) error {
|
|||||||
return a.manager.DeleteSnapshot(ctx, snapshotID)
|
return a.manager.DeleteSnapshot(ctx, snapshotID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// saveCurrentSnapshotID saves the current snapshot ID to a file in the WorkDir
|
||||||
|
func (a *Agate) saveCurrentSnapshotID() error {
|
||||||
|
if a.currentSnapshotID == "" {
|
||||||
|
// If there's no current snapshot ID, remove the file if it exists
|
||||||
|
if _, err := os.Stat(a.currentIDFile); err == nil {
|
||||||
|
return os.Remove(a.currentIDFile)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the current snapshot ID to the file
|
||||||
|
return os.WriteFile(a.currentIDFile, []byte(a.currentSnapshotID), 0644)
|
||||||
|
}
|
||||||
|
|
||||||
// Close releases all resources used by the Agate instance.
|
// Close releases all resources used by the Agate instance.
|
||||||
func (a *Agate) Close() error {
|
func (a *Agate) Close() error {
|
||||||
// Currently, we don't have a way to close the manager directly
|
// Currently, we don't have a way to close the manager directly
|
||||||
|
Loading…
Reference in New Issue
Block a user