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.
-
.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
- #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
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
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