class
Sepia::Storage
- Sepia::Storage
- Reference
- Object
Overview
Central storage management class.
The Storage class manages pluggable storage backends and provides
both a modern class-based API and backward compatibility with the
original singleton pattern.
⚠️ WARNING: The Storage API and backend interfaces are subject to change. The on-disk format for the filesystem backend is not stable.
Supported Backends
:filesystem- Default file-based storage (FileStorage):memory- In-memory storage for testing (InMemoryStorage)
Usage
# Configure storage backend
Sepia::Storage.configure(:filesystem, {"path" => "./data"})
# Or use in-memory storage
Sepia::Storage.configure(:memory)
# Class-based API (recommended)
Sepia::Storage.save(my_object)
loaded = Sepia::Storage.load(MyClass, "object-id")
# Legacy singleton API (still supported)
Sepia::Storage::INSTANCE.save(my_object)
loaded = Sepia::Storage::INSTANCE.load(MyClass, "object-id")
Defined in:
sepia/storage.crConstant Summary
-
INSTANCE =
new -
Legacy singleton instance for backward compatibility.
Provides the same API as the class methods for existing code that relies on the singleton pattern.
Class Method Summary
-
.backend
Returns the current storage backend.
-
.backend=(backend : StorageBackend)
Sets the current storage backend.
-
.backup(objects : Array(Sepia::Object), output_path : String) : String
Creates a backup of the specified objects.
-
.backup(object : Sepia::Object, output_path : String) : String
Creates a backup of a single object and its references.
-
.backup_all(output_path : String, progress_callback = nil) : String
Creates a backup of all objects in the current storage.
-
.backup_supported? : Bool
Checks if the current storage backend supports backup operations.
-
.build_generation_path(base_path : String | Nil, generation_id : String) : String | Nil
Build a generation-specific path from a base path and generation ID.
-
.clear
Bulk operations
-
.configure(backend : Symbol, config : Hash(String, String | Bool | Hash(String, String)) = {} of String => String)
Configures storage using a named backend.
- .count(object_class : Class) : Int32
- .delete(object : Serializable | Container, cache : Bool = true, metadata = nil)
- .delete(class_name : String, id : String, cache : Bool = true)
- .exists?(object_class : Class, id : String) : Bool
- .export_data : Hash(String, Array(Hash(String, String)))
- .gc(roots : Enumerable(Sepia::Object), dry_run : Bool = false) : Hash(String, Array(String))
-
.get_latest_generation(object_class : Class, base_id : String)
Get the latest generation object for a given base ID.
- .import_data(data : Hash(String, Array(Hash(String, String))))
-
.last_event(object_class : Class, id : String) : LogEvent | Nil
Get the last event for a specific object.
-
.list_all(object_class : Class) : Array(String)
Discovery API - delegates to current backend
- .list_all_objects : Hash(String, Array(String))
- .load(object_class : T.class, id : String, path : String | Nil = nil, cache : Bool = true) : T forall T
-
.next_generation_number(object_class : Class, base_id : String) : Int32
Get the next generation number for an object based on existing files.
-
.object_events(object_class : Class, id : String) : Array(LogEvent)
Get all events for a specific object.
-
.save(object : Serializable, path : String | Nil = nil, cache : Bool = true, metadata = nil, *, force_new_generation : Bool = false)
Class methods with cache integration (caching is default)
- .save(object : Container, path : String | Nil = nil, cache : Bool = true, metadata = nil, *, force_new_generation : Bool = false)
Instance Method Summary
-
#backup(objects : Array(Sepia::Object), output_path : String) : String
Instance version of backup method for backward compatibility.
-
#backup(object : Sepia::Object, output_path : String) : String
Instance version of single object backup method.
-
#backup_all(output_path : String, progress_callback = nil) : String
Instance version of backup_all method.
-
#backup_supported? : Bool
Instance version of backup_supported? method.
- #delete(object : Serializable | Container, cache : Bool = true, metadata = nil)
-
#load(object_class : T.class, id : String, path : String | Nil = nil, cache : Bool = true) : T forall T
Loads an object using the current backend.
-
#path : String
Legacy path property (only works with FileStorage)
- #path=(path : String)
-
#save(object : Serializable, path : String | Nil = nil, cache : Bool = true, metadata = nil, *, force_new_generation : Bool = false)
Saves a Serializable object using the current backend.
-
#save(object : Container, path : String | Nil = nil, cache : Bool = true, metadata = nil, *, force_new_generation : Bool = false)
Saves a Container object using the current backend.
Class Method Detail
Returns the current storage backend.
Returns
The currently active StorageBackend instance.
Example
backend = Sepia::Storage.backend
puts backend.class # => FileStorage or InMemoryStorage
Sets the current storage backend.
Allows switching to a different backend implementation at runtime.
Parameters
- backend : A StorageBackend instance to use
Example
# Switch to custom backend
custom_backend = MyCustomStorage.new
Sepia::Storage.backend = custom_backend
Creates a backup of the specified objects.
This is a convenience method that wraps the Sepia::Backup.create method
and validates that the current storage backend supports backup operations.
Parameters
- objects : Array of objects to include in the backup
- output_path : Path where the backup tar file will be created
Returns
The path to the created backup file
Example
# Backup specific objects
documents = [doc1, doc2, doc3]
backup_path = Sepia::Storage.backup(documents, "docs_backup.tar")
# Backup a user's entire object tree
user_data = [user_object]
backup_path = Sepia::Storage.backup(user_data, "user_backup_#{Time.utc.to_unix}.tar")
Raises
Sepia::Backup::BackendNotSupportedErrorif current backend doesn't support backupsSepia::Backup::BackupCreationErrorif backup creation fails
Creates a backup of a single object and its references.
Convenience method for backing up one object tree.
Parameters
- object : Root object to backup (includes all referenced objects)
- output_path : Path where the backup tar file will be created
Returns
The path to the created backup file
Example
# Backup a project and all its documents
project = Sepia::Storage.load(Project, "project-123")
backup_path = Sepia::Storage.backup(project, "project_backup.tar")
Creates a backup of all objects in the current storage.
This method attempts to backup all objects currently stored in the storage backend. Be aware that this can be resource-intensive for large storage systems.
Parameters
- output_path : Path where the backup tar file will be created
- progress_callback : Optional callback for progress updates
Returns
The path to the created backup file
Example
# Backup everything with progress updates
backup_path = Sepia::Storage.backup_all("full_backup.tar") do |progress|
puts "Backup progress: #{progress} objects processed"
end
Checks if the current storage backend supports backup operations.
Currently, only FileStorage supports backup operations as it provides access to the underlying file system structure.
Returns
true if backup is supported, false otherwise
Example
if Sepia::Storage.backup_supported?
puts "Backup operations are available"
else
puts "Switch to FileStorage to enable backup features"
end
Build a generation-specific path from a base path and generation ID.
Configures storage using a named backend.
Provides a convenient way to configure common backends without instantiating them manually.
Parameters
- backend : Symbol identifying the backend type (
:filesystemor:memory) - config : Optional configuration hash for the backend
Configuration Options
For :filesystem backend:
"path": Root directory path (defaults to system temp directory)"watch": Enable file system watcher (default: false)true: Enable watcher with default settingsfalse: Disable watcherHash: Custom watcher configuration options
For :memory backend:
- No configuration options available
Examples
# Configure filesystem storage with custom path
Sepia::Storage.configure(:filesystem, {"path" => "./app_data"})
# Configure filesystem storage with watcher enabled
Sepia::Storage.configure(:filesystem, {"watch" => true})
# Configure filesystem storage with custom watcher settings
Sepia::Storage.configure(:filesystem, {
"path" => "./app_data",
"watch" => {
"recursive" => true,
"latency" => 0.1,
},
})
# Configure in-memory storage
Sepia::Storage.configure(:memory)
Get the latest generation object for a given base ID.
Returns the object with the highest generation number, or nil if no generations exist.
Get the last event for a specific object.
Parameters
- object_class : The class of the object
- id : The object's unique identifier
Returns
The last event for the object, or nil if no events exist
Example
last_event = Sepia::Storage.last_event(MyDocument, "doc-123")
if last_event
puts "Last modified: #{last_event.timestamp}"
end
Discovery API - delegates to current backend
Get the next generation number for an object based on existing files.
Scans the filesystem to find the highest existing generation number and returns the next one. This is independent of event logging.
Parameters
- object_class : The class of the object
- base_id : The base ID without generation suffix
Returns
The next generation number (1 if no generations exist)
Get all events for a specific object.
Parameters
- object_class : The class of the object
- id : The object's unique identifier
Returns
Array of events for the specified object, ordered by timestamp
Example
events = Sepia::Storage.object_events(MyDocument, "doc-123")
events.each { |event| puts "#{event.timestamp}: #{event.event_type}" }
Class methods with cache integration (caching is default)
Instance Method Detail
Instance version of backup method for backward compatibility.
Example
Sepia::Storage::INSTANCE.backup([doc1, doc2], "backup.tar")
Instance version of single object backup method.
Instance version of backup_all method.
Loads an object using the current backend.
First checks the cache for the object. If not found, loads from backend
and automatically caches the result for future retrievals. Set cache: false
to disable caching for this operation.
Parameters
- object_class : The class of object to load
- id : The object's unique identifier
- path : Optional custom load path
- cache : Whether to use cache (default: true)
Returns
An instance of type T loaded from storage.
Example
# Load with caching (default)
doc = Sepia::Storage.load(MyDocument, "doc-uuid")
# Load without caching
doc = Sepia::Storage.load(MyDocument, "doc-uuid", cache: false)
# Type is inferred, no casting needed
puts doc.content # doc is typed as MyDocument
Saves a Serializable object using the current backend.
Automatically caches the object for faster retrieval. Set cache: false
to disable caching for this operation. Optionally logs the save operation
if the object's class has event logging enabled.
Parameters
- object : The Serializable object to save
- path : Optional custom save path
- cache : Whether to cache the object (default: true)
- metadata : Optional metadata for event logging
Example
doc = MyDocument.new("Hello")
Sepia::Storage.save(doc) # Save with caching (default)
Sepia::Storage.save(doc, cache: false) # Save without caching
Sepia::Storage.save(doc, metadata: {"user" => "alice"}) # Save with event logging
Saves a Container object using the current backend.
Automatically caches the object for faster retrieval. Set cache: false
to disable caching for this operation. Optionally logs the save operation
if the object's class has event logging enabled.
Parameters
- object : The Container object to save
- path : Optional custom save path
- cache : Whether to cache the object (default: true)
- metadata : Optional metadata for event logging
Example
board = Board.new("My Board")
Sepia::Storage.save(board) # Save with caching (default)
Sepia::Storage.save(board, cache: false) # Save without caching
Sepia::Storage.save(board, metadata: {"user" => "alice"}) # Save with event logging