Code Monkey home page Code Monkey logo

pg_turso's Introduction

⚠️ This project is now deprecated and no longer supported ⚠️

Turso makes it easy to create thousands of databases using the CLI and Platform API.


pg_turso

Postgres output plugin for replicating data to Turso.

Status

Replicating tables and views is more or less supported, but:

  1. Only basic types - integers and text - were tested. Postgres has way more types, and they may prove problematic to replicate. We can probably just cast them to generic binary blobs and replicate them in that form.

Installation

This guide assumes that you have a local installation of Postgres. Get one from https://www.postgresql.org/download/

Please note that you need to download zig development version 2023-06-20 or higher: https://ziglang.org/download/

cd /tmp
git clone https://github.com/turso-extended/pg_turso.git
cd pg_turso
export ZIG=<path where zig executable is>
make
make install # may need sudo

Getting Started

Let's assume that you have the following table and materialized view that you wish to replicate to the edge with Turso:

CREATE TABLE IF NOT EXISTS menu(
   dish_id int PRIMARY KEY,
   name text,
   price float
);
CREATE MATERIALIZED VIEW assorted_collection_of_dirt_cheap_dishes
  AS SELECT dish_id, name FROM menu WHERE price <= 2.99;

The Turso table corresponding to our materialized view will be automatically created by the plugin, and is going to look more or less as follows:

CREATE TABLE assorted_collection_of_dirt_cheap_dishes(
   dish_id int PRIMARY KEY ON CONFLICT REPLACE,
   name
);

The way replication plugins work is as follows.

First, you need to change your "wal level" to logical. Logical WAL means that WAL entries can be parsed and structured logically as row changes. In order to switch to logical WAL level, do the following, once:

ALTER SYSTEM SET wal_level = logical;

Then you need to restart the Postgres server, otherwise the change wouldn't take effect. After a restart, verify with:

SHOW wal_level;
 wal_level 
-----------
 logical
(1 row)

Then, you need to create a "logical replication slot". You can do that by calling a builtin function and passing two parameters to it - the first is the name of your slot, and you can pick whatever name you like. The second is the plugin used, and it needs to match the shared library name you compiled above, so pg_turso.

SELECT pg_create_logical_replication_slot('pg_turso_slot', 'pg_turso');

Then, you can fill the table with some data:

INSERT INTO menu VALUES (1, 'salami', 2.49);
INSERT INTO menu VALUES (2, 'pastrami', 4.99);
INSERT INTO menu VALUES (3, 'wasabi', 1.99);

No replication has happened yet. In Postgres, replication is triggered by calling a function. This function takes the replication slot name and optional parameters. pg_turso requires two parameters - the url and the token, to be able to communicate with a Turso instance, e.g.

SELECT * FROM pg_logical_slot_get_changes('pg_turso_slot', NULL, NULL, 'url', 'https://your-unique-link.turso.io/', 'auth', 's3cr3t-p4s5');

Note that this is a regular SELECT statement, so you're free to fetch the secret token value from another table, if it should remain secret.

The call triggers parsing WAL and processing all the logical changes. These changes are sent to Turso.

How to use the pg_turso extension with helper functions

Instead of replicating manually, you can use our pg_turso extension. It's based on pg_cron and allows the replication to be automated.

  1. Set up Turso authentication - helper functions that return the database URL and token
-- token
CREATE OR REPLACE FUNCTION turso_token() RETURNS text LANGUAGE SQL AS $$ SELECT <your-token-generated-with-turso-db-tokens-create>; $$;

-- url
CREATE OR REPLACE FUNCTION turso_url() RETURNS text LANGUAGE SQL AS $$ SELECT 'https://workerscounter-psarna.turso.io/'; $$;
  1. Load the extension and schedule replication. The interval accepts pg_cron syntax.
CREATE EXTENSION pg_turso;
SELECT turso_schedule_mv_replication('assorted_collection_of_dirt_cheap_dishes', '30 seconds'); -- refreshing materialized views in Postgres is costly, beware!

Voilà! Your data is now replicated to Turso.

Replicating tables

On top of replicating parts of your table to Turso as Postgres materialized views, you can also use pg_turso to replicate tables. In the future, we're also considering adding custom filters to table replication. In order to replicate a table, simply call:

CREATE EXTENSION pg_turso;
SELECT turso_schedule_table_replication('assorted_collection_of_dirt_cheap_dishes', '5 seconds');

Table replication is also more efficient than materialized view replication, because it does not involve refreshing the materialized view. Enjoy!

pg_turso's People

Contributors

notrab avatar penberg avatar psarna avatar tristenharr 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

Watchers

 avatar  avatar  avatar  avatar  avatar

pg_turso's Issues

Background replication

You currently need to execute the pg_logical_slot_get_changes() function to replicate:

SELECT * FROM pg_logical_slot_get_changes('pgturso_slot', NULL, NULL, 'url', 'http://127.0.0.1:8080/', 'auth', 's3cr3t');

Let's look into ways to make the replication happen automatically in the background.

PostgreSQL 14 support?

We currently target PostgreSQL 15, but Fedora, for example, has PostgreSQL 14. Unfortunately due to PostgreSQL differences, the extension doesn't build:

zig build-lib pgturso Debug native: error: the following command failed with 2 compilation errors:
/home/penberg/src/turso/pgturso/zig/zig-linux-x86_64-0.11.0-dev.3724+32cb9462f/zig build-lib /home/penberg/src/turso/pgturso/src/main.zig -lc --cache-dir /home/penberg/src/turso/pgturso/zig-cache --global-cache-dir /home/penberg/.cache/zig --name pgturso -dynamic --version 0.1.0 -I /home/penberg/src/turso/pgturso/postgres/src/include --listen=-
Build Summary: 0/3 steps succeeded; 1 failed (disable with --summary none)
install transitive failure
└─ install pgturso transitive failure
   └─ zig build-lib pgturso Debug native 2 errors
src/main.zig:124:60: error: root struct of file '.home.penberg.src.turso.pgturso.zig-cache.o.6ed60b876cfd6a06a91994233d262fa0.cimport' has no member named 'String'
            const url_string = std.mem.span(@ptrCast([*c]pg.String, @alignCast(@import("std").meta.alignment([*c]pg.String), elem.*.arg)).*.sval);
                                                         ~~^~~~~~~
referenced by:
    _PG_output_plugin_init: src/main.zig:51:24
    remaining reference traces hidden; use '-freference-trace' to see all reference traces

/home/penberg/src/turso/pgturso/zig-cache/o/6ed60b876cfd6a06a91994233d262fa0/cimport.zig:12087:25: error: unable to translate C expr: expected ')' instead got '='
pub const fastgetattr = @compileError("unable to translate C expr: expected ')' instead got '='"); // /home/penberg/src/turso/pgturso/postgres/src/include/access/htup_details.h:711:9
                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
make: *** [Makefile:18: all] Error 2

Use `CREATE MATERIALIZED VIEW` SQL syntax

The CREATE MATERIALIZED VIEW has a USING method and WITH (storage_parameter = [value]... options. If we require the materialized view to materialize on PostgreSQL side also and replicate the already computed views, that lets us hook into a nicer syntax.

Mac OS integration

make                                                        
  GIT     submodules
Submodule path 'postgres': checked out '8382864eb5c9f9ebe962ac20b3392be5ae304d23'
  MAKE    postgres headers
  ZIG     pg_turso
/private/tmp/pg_turso/build.zig:25:24: error: expected type 'Build.LazyPath', found '*const [20:0]u8'
    lib.addIncludePath("postgres/src/include");
                       ^~~~~~~~~~~~~~~~~~~~~~
/usr/local/Cellar/zig/0.11.0/lib/zig/std/Build.zig:1672:22: note: union declared here
pub const LazyPath = union(enum) {
                     ^~~~~
/usr/local/Cellar/zig/0.11.0/lib/zig/std/Build/Step/Compile.zig:1030:45: note: parameter type declared here
pub fn addIncludePath(self: *Compile, path: LazyPath) void {
                                            ^~~~~~~~
referenced by:
    runBuild__anon_6722: /usr/local/Cellar/zig/0.11.0/lib/zig/std/Build.zig:1638:27
    remaining reference traces hidden; use '-freference-trace' to see all reference traces
make: *** [all] Error 2

what I am missing... even brew install postgres@16 (just in case) ?

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.