Coder Social home page Coder Social logo

pg_crdt's Introduction

pg_crdt (experimental)

pg_crdt is an experimental extension adding support for conflict-free replicated data types (CRDTs) in Postgres.

CRDTs are decentralized data structures that can safely be replicated and synchronized across multiple computers/nodes. They are the enabling technology for collaborative editing applications like Notion.

Why

For an in-depth background, read the blog post.

Our goal was to evaluate if we could leverage a Postgres-backed CRDT and Supabase's existing Realtime API for change-data-capture to enable development of collaborative apps on the Supabase platform.

The pg_crdt extension is a proof-of-concept that wraps rust's yrs and automerge libraries using the pgx framework to add a Postgres native CRDT, crdt.ydoc. The extension supports creating a new crdt.ydoc and merging crdt.ydocs. For a full list of available methods see API.

Challenges

The experiment was successful in that it enabled a proof-of-concept CRDT-as-a-service. Through that experience we found that there are significant technical hurdles to using Postgres as a CRDT source-of-truth with updates broadcasted to collaborators using supabase/realtime.

For example:

  • Frequently updated CRDTs produce a lot of WAL and dead tuples

  • Large CRDT types in Postgres generate significant serialization/deserialization overhead on-update

  • supabase/realtime broadcasts database changes from the Postgres write ahead log (WAL). The WAL includes a complete copy of the the underlying data so small updates cause the entire document to broadcast to all collaborators

While many of these challenges are solvable, CRDT support does not trivially drop-in to our stack using this approach. In the short term we're opening this repo to allow others to continue building on the experiment. We're also brainstorming new ways to bring these technologies together to make supabase the go-to choice for collaborative apps.


Technical

Design

The database's internal representation of a CRDT Doc is the Doc's state vector encoded as an update. This format can be rehydrated to apply updates. It is also what new clients need first when they join the shared data structure.

  • When clients join a Doc, initial state is queried from a table
  • When updates from remote clients occur, realtime can broadcast the changes to subscribers

Usage

Create the extension

create extension pg_crdt;

Define a table with a CRDT column

create table posts (
  id serial primary key,
  content crdt.ydoc default crdt.new_ydoc()
);

Insert a row into the table

insert into posts (content)
values (crdt.new_ydoc())
returning id;

Update the CRDT by merging an update, where change is a CRDT doc change

update posts 
set content = crdt.merge(content, change)
where id = 1;

There is a convenience || infix operator that is equivalent to crdt.merge. To use it, make sure your search path includes the crdt schema:

set search_path to public,crdt;

update posts 
set content = content || crdt.new_ydoc()
where id = 1;

API: Yjs/Yrs

crdt.new_ydoc()::crdt.ydoc

Creates a new, empty, Yjs document (YDoc)

crdt.merge(crdt.ydoc, crdt.ydoc)::crdt.ydoc

Merges two documents into one.

Synonymous to the || operator available in the crdt schema.

crdt.merge(crdt.ydoc, crdt.yupdate)::crdt.ydoc

Applies an update to a document. YUpdate can be created by casting byte array (bytea) to crdt.yupdate

Synonymous to the || operator available in the crdt schema.

API: Automerge

crdt.new_autodoc()::crdt.autodoc

Creates a new, empty, Automerge document

crdt.merge(crdt.autodoc, crdt.autodoc)::crdt.autodoc

Merges two documents into one.

Synonymous to the || operator available in the crdt schema.

crdt.merge(crdt.autodoc, crdt.autochange)::crdt.autodoc

Applies an update to a document. AutoChange can be created by casting byte array (bytea) to crdt.autochange

Synonymous to the || operator available in the crdt schema.

Installation

Docker

git clone https://github.com/supabase/pg_crdt.git
cd pg_crdt
docker-compose up

The Postgres database is available at postgresql://postgres:password@localhost:5582/sdb

To enable the extension in Postgres, execute the create extension statement

create extension pg_crdt;

System

First, install pgx

Then clone the repo and install using

git clone https://github.com/supabase/pg_crdt.git
cd pg_crdt
cargo pgx run pg14

Which starts a psql prompt.

To enable the extension in Postgres, execute the create extension statement

create extension pg_crdt;

pg_crdt's People

Contributors

isaiah-hamilton avatar kiwicopple avatar olirice avatar snagasawa avatar yrashk avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pg_crdt's Issues

Upgrading to pgrx 0.9

If I can figure out how to upgrade pg_crdt to pgrx 0.9, I will create a PR.

Bug report

  • I confirm this is a bug with Supabase, not with my own application.
  • I confirm I have searched the Docs, GitHub Discussions, and Discord.

Describe the bug

cargo pgrx run ... fails because it's looking for ~/.pgx instead of ~/.pgrx

Error: /Users/dg/.pgx/config.toml not found. Have you run cargo pgx init yet?

I ran the following as a workaround:

ln -s ~/.pgrx ~/.pgx

That got me further but I eventually hit a build error. See Actual Results below.

To Reproduce

I installed rust, pgrx, initialized pgrx (with defaults), and verified the sample extension could be installed. (cargo pgrx new ..)

Then I cloned pg_crdt and

ln -s ~/.pgrx ~/.pgx
cd *pg_crdt
cargo pgrx run pg14

Expected behavior

Installation works

Actual behavior

   Copying control file to /Users/dg/.pgrx/14.8/pgrx-install/share/postgresql/extension/pg_crdt.control
     Copying shared library to /Users/dg/.pgrx/14.8/pgrx-install/lib/postgresql/pg_crdt.so
 Discovering SQL entities
  Discovered 0 SQL entities: 0 schemas (0 unique), 0 functions, 0 types, 0 enums, 0 sqls, 0 ords, 0 hashes, 0 aggregates, 0 triggers
The application panicked (crashed).
Message:  Couldn't call __pgrx_marker: DlSym { desc: "dlsym(0x7fac764fc0e0, __pgrx_marker): symbol not found" }
Location: /Users/dg/.cargo/registry/src/github.com-1ecc6299db9ec823/cargo-pgrx-0.9.0/src/command/schema.rs:408

  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ SPANTRACE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

   0: cargo_pgrx::command::schema::generate_schema with pg_version=14.8 profile=Dev test=false path=/Users/dg/.pgrx/14.8/pgrx-install/share/postgresql/extension/pg_crdt--0.0.1.sql features=["pg14"]
      at /Users/dg/.cargo/registry/src/github.com-1ecc6299db9ec823/cargo-pgrx-0.9.0/src/command/schema.rs:172
   1: cargo_pgrx::command::install::install_extension with pg_version=14.8 profile=Dev test=false features=["pg14"]
      at /Users/dg/.cargo/registry/src/github.com-1ecc6299db9ec823/cargo-pgrx-0.9.0/src/command/install.rs:94
   2: cargo_pgrx::command::run::run with pg_version=14.8 profile=Dev
      at /Users/dg/.cargo/registry/src/github.com-1ecc6299db9ec823/cargo-pgrx-0.9.0/src/command/run.rs:94
   3: cargo_pgrx::command::run::execute
      at /Users/dg/.cargo/registry/src/github.com-1ecc6299db9ec823/cargo-pgrx-0.9.0/src/command/run.rs:55

Screenshots

If applicable, add screenshots to help explain your problem.

System information

MacOS Big Sur 11.7.8 Intel

rustup --version
rustup 1.26.0 (5af9b9484 2023-04-05)
info: This is the version for the rustup toolchain manager, not the rustc compiler.
info: The currently active `rustc` version is `rustc 1.69.0 (84c898d65 2023-04-16)`

Additional context

Add any other context about the problem here.

pgx installation

Improve documentation

Link

README.md

Describe the problem

pgx was renamed to pgrx which is incompatible with pg_crdt as of May 2023

Describe the improvement

Install pgx via cargo install --locked cargo-pgx@^0.6

Additional context

Add any other context or screenshots that help clarify your question.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.