Replies: 1 comment 1 reply
-
Dumb question, but I'm trying to square this limitation with the web worker compat notes for Svelte which imply collections work on the main thread and in web workers. What are the current limitations today in 1.x w.r.t. querying and modifying the collections off the main thread?
Is the idea that the reactive context would be set up on a per component basis? With Svelte, I've moved to a model with the reactive contexts consolidated in one place that initializes at startup, using db.svelte.ts let feeds = $state.raw<Feed[]>([]);
let episodes = $state.raw<Episode[]>([]);
$effect.root(() => {
$effect(() => {
const feedsCursor = db.feeds.find();
feeds = feedsCursor.fetch();
return () => {
feedsCursor.cleanup();
};
});
$effect(() => {
const episodesCursor = db.episodes.find();
episodes = episodesCursor.fetch();
return () => {
episodesCursor.cleanup();
};
});
function getFeeds() {
return feeds;
}
function getEpisodes() {
return episodes;
}
export { getFeeds, getEpisodes }; component import { getEpisodes, getFeeds } from '$lib/stores/db.svelte';
let episodes = $derived(
getEpisodes()
.filter((episode) => episode.feedId === feedId)
.sort((a, b) => b.publishedAt.getTime() - a.publishedAt.getTime())
.slice(0, limit)
);
let feed = $derived(getFeeds().find((feed) => feed.id === feedId)); So far so good, even with ~12K rows in the episodes collection. Having this global state management is nice w.r.t. keeping components simple, but curious for your thoughts on this approach in general and in context of the data layer idea. Thanks! |
Beta Was this translation helpful? Give feedback.
-
As already discussed some time ago on discord, Here are my ideas and plans for the improved data handling for SignalDB. Keep in mind that this is a draft and not final. I'm open for feedback and suggestions. Feel free to add your comments and to challenge the design.
Currently all data is stored in memory as well as in the storage of the persistence adapters. This is not optimal, as the data is stored twice and the memory usage is quite high.
Another issue with this is, that all operation take place in the main thread as the memory is accessed from here.
My plan is to move to add a separate layer that handles the data storage, querying and write operations. This layer can be moved to a separate thread or web worker to not block the main thread. This data layer will "talk" to the connected collection in the mean threads via events and also update the data in the collection.
The data in the collection itself is just a cached representation of the data in the data layer. The collection "registeres" a query, once it's used in a reactive context. The query result then will be empty in the first place, but will trigger the data layer to fetch the data from the storage and update the collection with the result. The data will be then cached in the collection and the query will rerun and present the result. There will be also a way to get the current loading state of a query, so that the UI can show a loading indicator. If the reactive context is terminated, the query will be “unregistered” and the cache will be cleared (maybe with a configurable grace period).
The collection class will be trimmed down to a minimum. The most logic will be moved to the data layer. The collection only acts as a proxy to the data layer. It doesn’t store any data and also does not contain any complex logic. The API of the collection stays the same as current. But calling methods will then communicate with the data layer. So the collection act more as a reactivity proxy for the data layer.
The
memoryAdapter
of the collection will be ditched as it's functionality will be obsolete or merged into the data layer.The data layer will be collection agnostic and can act as the backend for many collection instances.
Usage
The API how collections are instanciated will slightly change. It's also thinkable to develop the whole thing backwards compatible, but I'm unsure if it's worth it.
The data layer will be created with a factory function that takes the storage adapter as an argument. The storage adapter will be created with a factory function that takes the storage name as an argument. This way the storage adapter can be used for multiple collection instances.
The data layer will be passed to the collection constructor. The collection will then be connected to the data layer and will be able to communicate with it.
Implementation
Data Layer
The main benefits of this design are a reduced memory footprint as well as that are more operations not blocking the UI thread anymore (if a web worker is used)
Open questions:
Connected issues/discussions: #397, #998
Beta Was this translation helpful? Give feedback.
All reactions