GraphQL AnyCable PostgreSQL Store
PostgreSQL subscription store for graphql-anycable.
This gem stores GraphQL subscription state in PostgreSQL. It does not deliver AnyCable broadcasts itself; delivery still goes through the AnyCable broadcast adapter configured by the application.
This gem requires a graphql-anycable version that supports custom subscription stores.
Installation
Add this line to your application's Gemfile:
gem "graphql-anycable_postgresql-store"
Then configure graphql-anycable to use the store:
GraphQL::AnyCable.configure do |config|
config.subscription_store = :postgresql
end
The gem also registers :postgres as an alias for :postgresql.
Configuration
Configure the PostgreSQL connection and table names with environment variables:
GRAPHQL_ANYCABLE_POSTGRESQL_STORE_POSTGRES_URL=postgres://localhost:5432/postgres
GRAPHQL_ANYCABLE_POSTGRESQL_STORE_SUBSCRIPTIONS_TABLE=graphql_anycable_subscriptions
GRAPHQL_ANYCABLE_POSTGRESQL_STORE_SUBSCRIPTION_EVENTS_TABLE=graphql_anycable_subscription_events
GRAPHQL_ANYCABLE_POSTGRESQL_STORE_CHANNEL_SUBSCRIPTIONS_TABLE=graphql_anycable_channel_subscriptions
Or configure the gem from application code:
GraphQL::AnyCable::PostgreSQLStore.configure do |config|
config.postgres_url = ENV["DATABASE_URL"]
config.subscriptions_table = "graphql_anycable_subscriptions"
config.subscription_events_table = "graphql_anycable_subscription_events"
config.channel_subscriptions_table = "graphql_anycable_channel_subscriptions"
end
If postgres_url is not configured, the store falls back to AnyCable.config.postgres_url when available, then to DATABASE_URL. If none are set, PG.connect uses libpq defaults.
Database schema
Rails applications with ActiveRecord can install the migration:
bin/rails generate graphql:anycable:postgresql_store:install
bin/rails db:migrate
The generator skips migration creation when ActiveRecord generator support is not available.
Applications can also create the tables directly:
CREATE TABLE graphql_anycable_subscriptions (
id text PRIMARY KEY,
query_string text NOT NULL,
variables text NOT NULL,
context text NOT NULL,
operation_name text NOT NULL,
events jsonb NOT NULL DEFAULT '{}',
expires_at timestamptz,
created_at timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE graphql_anycable_subscription_events (
subscription_id text NOT NULL REFERENCES graphql_anycable_subscriptions(id) ON DELETE CASCADE,
topic text NOT NULL,
fingerprint text NOT NULL,
created_at timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (subscription_id, topic, fingerprint)
);
CREATE INDEX index_graphql_anycable_subscription_events_topic_fingerprint
ON graphql_anycable_subscription_events (topic, fingerprint);
CREATE INDEX index_graphql_anycable_subscription_events_fingerprint
ON graphql_anycable_subscription_events (fingerprint);
CREATE TABLE graphql_anycable_channel_subscriptions (
channel_id text NOT NULL,
subscription_id text NOT NULL REFERENCES graphql_anycable_subscriptions(id) ON DELETE CASCADE,
created_at timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (channel_id, subscription_id)
);
Stats
GraphQL::AnyCable.stats delegates to this store when subscription_store is
configured as :postgresql or :postgres. The store reports active
subscriptions, topics, fingerprints, and channels with SQL aggregate queries;
scan_count is accepted for graphql-anycable interface compatibility and is not
used by PostgreSQL.
Development
Install dependencies and run tests:
GRAPHQL_ANYCABLE_PATH=../graphql-anycable bundle exec rspec
Set POSTGRES_URL or DATABASE_URL to run the store integration spec against PostgreSQL.
CI runs the spec suite against a PostgreSQL service and checks out the graphql-anycable interface branch until the custom store API is released.
Release
Release notes are kept in CHANGELOG.md and published through GitHub Releases.
Build the gem with:
bundle exec rake build
Publish the same versioned gem artifact to RubyGems and GitHub Releases:
gem push pkg/graphql-anycable_postgresql-store-0.1.0.gem
gh release create v0.1.0 pkg/graphql-anycable_postgresql-store-0.1.0.gem \
--title "v0.1.0" \
--notes-file CHANGELOG.md