SqlPersistenceStore
IPersistenceStore in the orchestrator's database (NebulaDatabase: SQLite or PostgreSQL), table nebula_entity.
Nebula · Packages/com.1by3.nebula/Services~/Nebula.Services/Storage/SqlPersistenceStore.cspublic sealed class SqlPersistenceStore : IPersistenceStoreIPersistenceStore in the orchestrator's database (NebulaDatabase: SQLite or PostgreSQL), table nebula_entity. One writer thread runs every save, delete and query in order on one connection, so the epoch rule (a save older than what is stored is dropped) is one conditional upsert and a later save never overtakes an earlier one. Answers are handed back from Tick on the main thread. When the database is unreachable the queue waits and the connection is retried; the mesh keeps simulating meanwhile, and workers keep their own queues (RemotePersistenceStore).
Constructors
SqlPersistenceStore
public SqlPersistenceStore(NebulaDatabase db);Fields
RetrySeconds
public const float RetrySeconds = 2f;CountIntervalSeconds
public const float CountIntervalSeconds = 2f;Seconds between refreshes of KnownCount while writes keep coming.
Properties
IsConnected
public bool IsConnected { get; }Backend
public string Backend { get; }KnownCount
public int KnownCount { get; }PendingJobs
public int PendingJobs { get; }Jobs waiting for the writer thread.
StaleSavesDropped
public long StaleSavesDropped { get; }Saves refused since the store was created because the stored record had a newer epoch. The first refusal of each key is also logged as a warning.
Methods
Connect
public void Connect();Tick
public void Tick();Dispose
public void Dispose();Save
public void Save(PersistedEntityRecord record);Delete
public void Delete(string key);WhenWritten
public void WhenWritten(Action onWritten);Clear
public void Clear();Load
public void Load(string key, Action<PersistedEntityRecord> onLoaded);LoadContainers
public void LoadContainers(IReadOnlyList<string> containerIds, Action<IReadOnlyDictionary<string, IReadOnlyList<PersistedEntityRecord>>> onLoaded);One job on the writer thread, one SELECT ... WHERE container_id IN (...) per PersistenceHost.MaxContainersPerLoad ids (the nebula_entity_container index answers it), answered once when every chunk has been read.
LoadCarried
public void LoadCarried(IReadOnlyList<string> carrierKeys, Action<IReadOnlyDictionary<string, IReadOnlyList<PersistedEntityRecord>>> onLoaded);One job on the writer thread, one SELECT ... WHERE carrier_key IN (...) per PersistenceHost.MaxCarriersPerLoad keys (the nebula_entity_carrier index answers it), answered once when every chunk has been read.
LoadWhere
public void LoadWhere(Func<PersistedEntityRecord, bool> predicate, Action<IReadOnlyList<PersistedEntityRecord>> onLoaded);CountRecords
public void CountRecords(string scopeKey, string containerId, Action<int> onCounted);A COUNT on the scope key (and the container id when one is given): no row is read back.