y-crdt / yrs-persistence

Native persistence providers for Yrs CRDT
10 stars 4 forks source link

Support for async persistence mechanisms? (what I really want is indexeddb-backed persistence in wasm). #5

Open dnaaun opened 9 months ago

dnaaun commented 9 months ago

Hi all.

IIUC, the yrs-kvstore crate (and the KVStore trait within it) are all intended for implementing persistence with synchronous methods, right?

I want to implement indexeddb-backed (and yet in Rust, via WASM, because I wanna stay in Rust land in the frontend too) persistence. My understanding is that the JS library from you folks to do this has a promise-based (and hence async) interface, which makes sense, since the underlying IndexedDB API is async at the end of the day.

So what I'm thinking is that I either have to:

  1. Write a sync wrapper for IndexedDB's async API, or
  2. Copy KVStore and DocOpt into my own code and make them support async.

Any advice here? I currently have no idea how to do (1), and yet I'm afraid to go down the path of (2) because it feels like a lot of work.

Thanks for all your work so far and for your help in advance!

Horusiath commented 9 months ago

Sure, it seems sensible to introduce some support for async variants of primitives in the library.

One thing about async traits in Rust:

  1. Atm. Rust still doesn't support async trait methods out of the box. For convenience this is often realised by using async_trait crate
  2. There's a duality of Send: many contexts ie. tokio::spawn request that async methods called within it implement Send trait. This is usually auto-implemented based on the methods and structs used in async call chain. However some of the environments (like Cloudflare workers and many other WebAssembly targets) have APIs that are not Send-compatible. For this reason this trait will need to conditionally compile for both. Re. async_trait: it can work in both contexts via #[async_trait]/#[async_trait(?Send)] specialisation.
dnaaun commented 9 months ago

Thanks for the reply!

So I'd gotten started down the path of having an async version of KVStore, and it seems to be going well so far. I'm currently using nightly instead of the async_trait crate, and I'm working without Send bounds. All of that was because it's easier (and all I need for my use-case).

My plan for now is to actually use this for indexeddb-based persistence, and then put out that code. I hope that afterwards, someone else, or me, will take it over the finish line by (1) switching back to stable and using async_trait, and (2) doing conditional compilation for the Send requirement.