Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Live Query API #104

Merged
merged 5 commits into from
Jul 25, 2024
Merged

Live Query API #104

merged 5 commits into from
Jul 25, 2024

Conversation

samwillis
Copy link
Collaborator

@samwillis samwillis commented Jun 21, 2024

This added a new "Live Query" plugin (our first one).

To use the extension it needs adding to the PGlite instance when creating it:

import { PGlite } from "@electric-sql/pglite";
import { live } from "@electric-sql/pglite/live";

const pg = new PGlite({
  extensions: {
    live,
  },
});

There are three methods on the live namespace:

  • live.query() for basic live queries. Less machinery in PG so quicker for small results sets and narrow rows.
  • live.incrementalQuery() for incremental queries. It materialises the full result set on each update in js. Perfect for feeding into React
  • live.changes() a lower level api that emits the changes (insert/update/delete) that can then be mapped to mutation in a UI or other datastore.

query()

This is very similar to a standard query, but takes an additional callback that receives the results whenever they change:

const ret = pg.live.query("SELECT * FROM test ORDER BY rand;", null, (res) => {
  // res is the same as a standard query result object
});

The returned value from the call is an object with this interface:

export interface LiveQueryReturn<T> {
initialResults: Results<T>;
unsubscribe: () => Promise<void>;
refresh: () => Promise<void>;
}

  • initialResults is the initial results set (also sent to the callback
  • unsubscribe allow you to unsubscribe from the live query
  • refresh allows you to force a refresh of the query

Internally it watches for the tables that the query depends on, and reruns the query whenever they are changes.

incrementalQuery()

Similar to above, but maintains a temp table inside of Postgres of the previous state. When the tables it depends on change the query is re-run and diffed with the last state. Only the changes from the last version of the query are copied from WASM into JS.

It requires an additional key argument, the name of a column (often a PK) to key the diff on.

const ret = pg.live.incrementalQuery(
  "SELECT * FROM test ORDER BY rand;", [], "id",
  (res) => {
   // res is the same as a standard query result object
  }
);

The returned value is of the same type as the query method above.

live.changes()

A lower level API that is the backend for the incrementalQuery, it emits the change that have happed. It again requires a key to key the diff on:

const ret = pg.live.changes(
  "SELECT * FROM test ORDER BY rand;", [], "id",
  (res) => {
   // res is a change result object
  }
);

the returned value from the call is defined by this interface:

export interface LiveChangesReturn<T = { [key: string]: any }> {
fields: { name: string; dataTypeID: number }[];
initialChanges: Array<Change<T>>;
unsubscribe: () => Promise<void>;
refresh: () => Promise<void>;
}

The results passed to the callback are array of Change objects:

export type ChangeInsert<T> = {
__changed_columns__: string[];
__op__: "INSERT";
__after__: number;
} & T;
export type ChangeDelete<T> = {} & {
__changed_columns__: string[];
__op__: "DELETE";
__after__: undefined;
} & T;
export type ChangeUpdate<T> = {} & {
__changed_columns__: string[];
__op__: "UPDATE";
__after__: number;
} & T;
export type Change<T> = ChangeInsert<T> | ChangeDelete<T> | ChangeUpdate<T>;

Each change has it's new values as part of the object along with:

  • __changed_columns__ the columns names that were changes
  • __op__ the operation that is required to update the state (INSERT, UPDATE, DELETE)
  • __after__ the key of the row that this row should be after, it will be included in __changed_columns__ if it has been changed.

To do:

  • Docs
  • Tests

@samwillis samwillis force-pushed the samwillis/extension-api branch from b8668a1 to 5c9ec28 Compare June 21, 2024 13:05
@samwillis samwillis force-pushed the samwillis/live-queries branch from 7165eb8 to d720c48 Compare June 21, 2024 13:06
@samwillis samwillis force-pushed the samwillis/extension-api branch from 5c9ec28 to c0f5766 Compare June 21, 2024 13:10
@samwillis samwillis force-pushed the samwillis/live-queries branch 4 times, most recently from 1f0f7e0 to a678da0 Compare June 21, 2024 20:54
@samwillis samwillis mentioned this pull request Jun 23, 2024
@samwillis samwillis changed the title WIP Live Query API Live Query API Jun 23, 2024
@samwillis samwillis marked this pull request as ready for review June 23, 2024 20:16
@samwillis samwillis force-pushed the samwillis/extension-api branch from db0bd3e to 0523b6d Compare June 25, 2024 21:31
@jueinin
Copy link

jueinin commented Jul 10, 2024

any updates for this PR ?

@samwillis
Copy link
Collaborator Author

Hey @jueinin
I need to rebase this on top of the new version we are building here #112, it will then get released with it. We are getting there.

@samwillis samwillis changed the base branch from samwillis/extension-api to main July 13, 2024 12:10
@samwillis samwillis force-pushed the samwillis/live-queries branch from a678da0 to 9217de5 Compare July 13, 2024 12:27
@samwillis samwillis changed the base branch from main to next July 13, 2024 12:28
Copy link
Contributor

github-actions bot commented Jul 13, 2024

@github-actions github-actions bot temporarily deployed to pull request July 13, 2024 12:36 Inactive
@samwillis samwillis force-pushed the samwillis/live-queries branch from 9217de5 to 671e446 Compare July 24, 2024 08:24
@samwillis samwillis changed the base branch from next to main July 24, 2024 08:24
@github-actions github-actions bot temporarily deployed to pull request July 24, 2024 09:21 Inactive
@samwillis samwillis force-pushed the samwillis/live-queries branch from 2ed0f7e to 2b636ea Compare July 24, 2024 09:27
@github-actions github-actions bot temporarily deployed to pull request July 24, 2024 09:28 Inactive
@samwillis samwillis requested review from kevin-dp and thruflo July 24, 2024 12:03
Copy link
Contributor

@thruflo thruflo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great to me 👍

@samwillis samwillis force-pushed the samwillis/live-queries branch from 2b636ea to 6ea99b2 Compare July 25, 2024 18:49
@github-actions github-actions bot temporarily deployed to pull request July 25, 2024 18:57 Inactive
@github-actions github-actions bot temporarily deployed to pull request July 25, 2024 22:47 Inactive
@samwillis samwillis merged commit 5cfbed1 into main Jul 25, 2024
2 checks passed
@samwillis samwillis deleted the samwillis/live-queries branch August 1, 2024 11:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants