Skip to content

v4.4.0 - Subscriptions and Live Queries now OSS 🎉

Compare
Choose a tag to compare
@benjie benjie released this 03 May 12:47

Please sponsor development (anything from $1/mo) or take out a support contract to help fund ongoing development on the project. PostGraphile is liberally licensed and relies on crowd-funding to advance.

Thanks to the continuing sponsorship from PostGraphile's community, we've added to PostGraphile core what you've all been waiting for - GraphQL Subscriptions, and Live Queries!

GraphQL Subscriptions

We've enhanced PostGraphile with subscriptions / websockets functionality, including adding subscriptions support to our built in GraphiQL IDE (no more need to test with external GraphQL clients!). To get this you have to opt-in via the --subscriptions flag (library: subscriptions: true).

You can use our simple subscriptions listen endpoint, or easily write your own subscription endpoints using makeExtendSchemaPlugin - it's all documented on our website. PostGraphile subscriptions can use Postgres' LISTEN/NOTIFY, or any other source of realtime data — you decide what makes sense for your application.

Subscriptions are the recommended way for adding realtime features to PostGraphile.

PostGraphile Live Queries

More experimental and much heavier on the database is our live queries support — suitable for use in internal tooling within your company, but perhaps not for the internet at large. You can opt-in via the --live flag.

We've built into the core of PostGraphile the ability to track when collections/records are referenced (and the filters that apply to them, such as foreign key constraints and conditions); you can then combine this with one or more realtime provider plugins which inform PostGraphile when these tracked resources change, triggering the query to be re-executed and the result sent to the user.

This feature is exposed over standard GraphQL subscription operations so you should be able to just switch out query with subscription at the beginning of your GraphQL document to make it live. No need for specific client support — it supports all clients that support subscriptions. (We plan to support the @live directive optimisation available in Apollo Client in a future release, should demand be sufficient.)

We recommend using simple request documents with live queries because each time a relevant row is changed the entire document is recalculated and sent to the user: more complex queries will consume more resources when recalculated and will likely be triggered more frequently, leading to non-linear performance costs. (Note: we throttle updates to prevent overwhelming the client or the server, and this throttle period is configurable.)

Our first live queries provider plugin, @graphile/subscriptions-lds uses PostgreSQL's extremely efficient logical decoding functionality to stream changes out of the database using the replication interface. It requires you to tweak a couple of settings in postgresql.conf but is otherwise simple to set up - see the documentation on the website which also includes instructions for Amazon RDS.

Note that live queries are still experimental, and have not been performance optimised yet - please let us know of any issues you face!

Other features

Docker compose/kubernetes users may appreciate the new --retry-on-init-fail flag that means PostGraphile will keep trying to rebuild the initial schema, so with this flag it can be started before the database is ready. (Uses exponential backoff with a 30s cap.)

We've increased performance for queries that use large offset values (so long as the relevant table is not using column-level select grants, which are not recommended with PostGraphile).

makeExtendSchemaPlugin now has support for re-using existing Relay Connections; it can also be used with the @pgQuery directive to add connections deeper into the schema. The documentation has been updated with more details.

You can now add your own aggregates to connections using our new aggregates infrastructure. totalCount on connections has been re-written to use this, and there are more examples (e.g. exposing SUM(...)) in the PR description: graphile/graphile-engine#415; if you require certain aggregates please get in touch.

Thanks to @dijam we now accept Buffer objects as jwtSecret in addition to strings.

build.scopeByType was added to enable plugin authors to get from a GraphQL type the scope it was created with - useful for finding the PostgreSQL table associated with a GraphQL object type, for example.

Plugins now have a dependency ordering system, so we can move to using --append-plugins for everything and have hooks register their own positions. This system is not yet documented (or final) so is not officially supported yet, but it's a good way to easily enable features that previously involved a complex setup.

Many more tests were added.

--owner-connection / ownerConnectionString setting added, to give PostGraphile access to a privileged Postgres account. It is needed for logical decoding, but it's now also used (if present) to install watch fixtures and avoid the "Failed to setup watch fixtures in Postgres database" error. It is recommended in development for the watch schema, but only recommended in production if you are using live queries.

Newly introduced @simpleCollections smart comment enables you to override the simpleCollections setting on a per-table, per-relation and per-function basis. I.e. you can now opt-in to using the list interface (rather than Relay connection interface) in certain places without affecting the rest of your schema.

Filterable, filter-by-able, sortable and sort-by-able functions support was introduced in 4.3.1.

GraphiQL Explorer support added in 4.3.2;

🚨 Breaking fixes

These are fixes that might break you schema if you were relying on the broken behaviour (please don't do that!). We've added flags to some of them so you can maintain the old (broken) behaviour should you need to.

  • Fixed issues with arrays of certain types (interval, etc) incorrectly having a String input type (opt out with disableIssue390Fix - ref graphile/graphile-engine#405)
  • If you're using --simple-collections only we still used to add Relay edges to mutation payloads (these edges are pointless without the connections they applied to). We've corrected this oversight by removing them, but you can add them back with the disableIssue397Fix flag - ref graphile/graphile-engine#408)
  • graphile-utils: if you were using makeExtendSchemaPlugin to add a field returning a Connection type, this will not have been working correctly. Instead of returning return {data: await selectGraphQLResultFromTable(...)} from your custom resolver you should now just return the result of selectGraphQLResultFromTable directly: return await selectGraphQLResultFromTable(...), and then pageInfo and the rest will work correctly. The makeExtendSchemaPlugin docs have been updated, worth a re-read. If you're affected by this and don't make this change, you'll see errors like TypeError: data.data.map is not a function.

Fixes

  • PostGraphile handles PostgreSQL server restart much more gracefully
  • Improved error messages when no values were deleted/updated because of RLS
  • Fully qualify reference to hstore to handle issues in search_path
  • Lots of improvements to TypeScript typings
  • Domains with defaults now exposed as nullable (thanks @mattbretl)
  • Fixed an issue with relations on custom mutation payloads when the custom mutation returned null without an error
  • Fixed an issue with an entire record being returned as null when you only request nullable columns. The fix requires you to provide --subscriptions or --live flags as it requires you to have granted select to at least the primary keys of the tables you expose
  • makeWrapResolversPlugin can now replace the arguments that are pass to PostgreSQL function calls for root-level custom queries and mutations.
  • totalCount is now non-nullable because I couldn't find any justification for it being nullable and no issues came up during the beta and RC phase
  • Fixed a bug in the times generated by the PostGraphile logs
  • Exposed the X-GraphQL-Event-Stream header (thanks @imolorhe)
  • Stricter pool validation
  • Fixed an issue with HTTP2 support in Fastify
  • Fixed hasVersion to allow pre-releases
  • Include namespaceName in introspection for extensions