Problem
Currently, persistToStorage() and loadFromStorage() inside poc-sync-engine/src/SyncQueue.ts are empty placeholders:
private persistToStorage() {
}
private loadFromStorage() {
this.queue = [];
}
To make the sync queue modular and reusable across both web (browser localStorage) and React Note (MMKV, SQLite, or WatermelonDB), we should decouple storage operations from the queue implementation.
However, async storage backends introduce initialization ordering concerns that cannot safely be handled inside the constructor, potentially creating race conditions if queue operations (like enqueue or peek) are called before storage hydration completes. Furthermore, introducing asynchronous persistence requires ensuring write ordering/concurrency remains deterministic, and that corrupted or invalid serialized state is handled gracefully.
Proposed Solution
- Define a generic
IStorageProvider interface:
export interface IStorageProvider {
getItem(key: string): string | null | Promise<string | null>;
setItem(key: string, value: string): void | Promise;
}
- Accept a storage adapter implementation during initialization. To handle the asynchronous serialization lifecycle safely, possible approaches include:
- Using a Static Factory Method (e.g.,
SyncQueue.create(storage)) to ensure hydration completes before returning the initialized instance.
- Using an explicit asynchronous lifecycle method (e.g.,
.initialize() or .hydrate()).
- Safely deserialize the stored queue state (handling JSON parsing failures gracefully to avoid bricking queue initialization).
- Implement writes to the storage engine, ensuring that write ordering/concurrency remains deterministic for async storage operations.
Acceptance Criteria
Problem
Currently,
persistToStorage()andloadFromStorage()inside poc-sync-engine/src/SyncQueue.ts are empty placeholders:To make the sync queue modular and reusable across both web (browser localStorage) and React Note (MMKV, SQLite, or WatermelonDB), we should decouple storage operations from the queue implementation.
However, async storage backends introduce initialization ordering concerns that cannot safely be handled inside the constructor, potentially creating race conditions if queue operations (like
enqueueorpeek) are called before storage hydration completes. Furthermore, introducing asynchronous persistence requires ensuring write ordering/concurrency remains deterministic, and that corrupted or invalid serialized state is handled gracefully.Proposed Solution
IStorageProviderinterface:export interface IStorageProvider {
getItem(key: string): string | null | Promise<string | null>;
setItem(key: string, value: string): void | Promise;
}
SyncQueue.create(storage)) to ensure hydration completes before returning the initialized instance..initialize()or.hydrate()).Acceptance Criteria
SyncQueuedepends on an injectedIStorageProviderinterface rather than environment-specific APIs.