{"id":10085,"library":"pycrdt-store","title":"PyCRDT Store","description":"pycrdt-store provides persistent storage solutions for `pycrdt`, specifically offering a `SQLiteYStore` implementation. It enables `pycrdt` documents to persist their state beyond application lifetime, supporting features like history squashing, cleanup based on database size, and performance optimizations. The current version is 0.1.3, and the library is under active development with frequent minor releases addressing performance, features, and bug fixes.","status":"active","version":"0.1.3","language":"en","source_language":"en","source_url":"https://github.com/y-crdt/pycrdt-store","tags":["CRDT","Y-CRDT","Database","SQLite","Realtime","Persistence","Offline-first"],"install":[{"cmd":"pip install pycrdt-store","lang":"bash","label":"Install stable release"}],"dependencies":[{"reason":"Core dependency for CRDT document management, as pycrdt-store provides its persistence layer.","package":"pycrdt"}],"imports":[{"symbol":"SQLiteYStore","correct":"from pycrdt_store import SQLiteYStore"},{"note":"YDoc is part of the 'pycrdt' library, not 'pycrdt_store'.","symbol":"YDoc","correct":"from pycrdt import YDoc"}],"quickstart":{"code":"import asyncio\nfrom pycrdt import YDoc\nfrom pycrdt_store import SQLiteYStore\n\nasync def main():\n    # Use an in-memory database for quick testing, or provide a file path\n    # e.g., SQLiteYStore(path=\"./my_document.db\")\n    store = SQLiteYStore(path=\":memory:\")\n    await store.setup() # Initialize the store connection\n\n    doc_name = \"my_persistent_doc\"\n    ydoc = YDoc(doc_name, store) # Associate YDoc with the store\n\n    # Perform CRDT operations\n    text = ydoc.get_text(\"my_text\")\n    text.insert(0, \"Hello, world!\")\n\n    # Changes are automatically synchronized with the store by YDoc\n\n    print(f\"Document content: {text.to_py()}\")\n\n    await store.close() # Close the store connection\n\nif __name__ == \"__main__\":\n    asyncio.run(main())\n","lang":"python","description":"This quickstart demonstrates how to set up `SQLiteYStore` with a `pycrdt.YDoc` to enable persistent storage. It initializes an in-memory SQLite database, performs a simple text insertion, and then properly closes the store. For file-based persistence, replace `:memory:` with a file path like `./my_document.db`."},"warnings":[{"fix":"Review the `SQLiteYStore` constructor arguments for `cleanup_when_db_size_above`, `squash_history_older_than`, and `squash_no_more_often_than` to configure the automatic maintenance behavior.","message":"Version 0.1.3 introduced automatic database cleanup and history squashing features (`cleanup_when_db_size_above`, `squash_history_older_than`). While these improve performance and manageability, they are active by default or through configuration. Users upgrading may want to review and explicitly configure these options to match their desired data retention and database size policies.","severity":"gotcha","affected_versions":">=0.1.3"},{"fix":"Always ensure `await store.setup()` is called before using the store, and `await store.close()` is called when the store is no longer needed, typically at application shutdown.","message":"Asynchronous setup and teardown of `SQLiteYStore` are crucial. Forgetting to `await store.setup()` or `await store.close()` can lead to uninitialized stores, resource leaks, or unsaved data, especially in file-based persistence scenarios.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Ensure that every `YDoc` instance using the same `SQLiteYStore` has a distinct `doc_name` string passed during its initialization: `YDoc(unique_doc_name, store)`.","message":"While `SQLiteYStore` can manage multiple `YDoc` instances, each `YDoc` must have a unique `doc_name` when associated with the same store. Reusing a `doc_name` for different `YDoc` objects can lead to data corruption or unexpected behavior.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-17T00:00:00.000Z","next_check":"2026-07-16T00:00:00.000Z","problems":[{"fix":"Ensure only one `SQLiteYStore` instance or application process is actively writing to a specific SQLite database file at a time. If concurrent writes are necessary, consider using an in-memory database (`:memory:`) for transient data or explore alternative CRDT storage backends that support higher concurrency.","cause":"SQLite databases are designed for single-writer access. This error occurs when multiple processes or threads attempt to write to the same database file concurrently without proper locking mechanisms or when a previous connection was not properly closed.","error":"sqlite3.OperationalError: database is locked"},{"fix":"Ensure `pycrdt-store` is updated to a recent version (0.1.0+). Always call `setup()` and `close()` asynchronously: `await store.setup()` and `await store.close()`.","cause":"This error likely occurs if you are attempting to call `store.setup()` synchronously or if you are on a very old version of `pycrdt-store` where `setup` was not an awaitable method or didn't exist.","error":"AttributeError: 'SQLiteYStore' object has no attribute 'setup'"},{"fix":"Verify that your `SQLiteYStore` instance is correctly created before attempting to `await` its methods. Check for exceptions during the `SQLiteYStore(...)` constructor call.","cause":"This often happens if the `store` object itself is `None` (e.g., due to an error in its creation) when you try to `await store.setup()` or `await store.close()`.","error":"TypeError: object NoneType can't be used in 'await' expression"}]}