graphile / graphile/crystal

Filtering subscription events

Open
#1,820 4 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
12.9k
Forks
625
Avg merge
5h 23m
Merged PRs (30d)
24

Description

### Feature description

Similar to this[ feature request](https://github.com/graphile/graphile-engine/issues/595) in Postgraphile v4, it would be very helpful to filter unnecessary events in the server runtime.

### Motivating example

The motivation is the same as described in that above Github issue for v4. Our database sends a lot of notifications, but our frontend clients only care about a subset. We want to be able to write GraphQL subscription schemas that include filtering criteria, so that frontend clients _only_ get notified of events that match that criteria.

Using the example in [v5 documentation](https://postgraphile.org/postgraphile/next/subscriptions/#example), it would be great if we can write logic like this in the `subscriptionPlan`

```
import { makeExtendSchemaPlugin } from "postgraphile/utils";
import { context, lambda, listen } from "postgraphile/grafast";
import { jsonParse } from "postgraphile/@dataplan/json";

const MySubscriptionPlugin = makeExtendSchemaPlugin((build) => {
const { messages } = build.input.pgRegistry.pgResources;
return {
typeDefs: /* GraphQL */ `
extend type Subscription {
forumMessage(forumId: Int!, evenNumbersOnly: Boolean): ForumMessageSubscriptionPayload
}

type ForumMessageSubscriptionPayload {
event: String
message: Message
}
`,
plans: {
Subscription: {
forumMessage: {
subscribePlan(_$root, args) {
const $pgSubscriber = context().get("pgSubscriber");
const $forumId = args.get("forumId");
const $topic = lambda($forumId, (id) => `forum:${id}:message`);
return listen($pgSubscriber, $topic, $payload => {
const $evenNumbersOnly = args.get("evenNumbersOnly");
const $jsonObject = jsonParse($payload);
const $handleIfPresent = lambda([$jsonObject, $evenNumbersOnly], (jsonObject, evenNumbersOnly) => {
if (!!evenNumbersOnly) {
if (jsonObject['id'] % 2 === 0) {
return jsonObject; / present value signifies event should be included
} else {
return null; // null signifies that the event should be discarded
}
}
return jsonObject; // present value signifies event should be included
});
});
},
plan($event) {
return $event;
},
},
},
ForumMessageSubscriptionPayload: {
event($event) {
return $event.get("event");
},
message($event) {
const $id = $event.get("id");
return messages.get({ id: $id });
},
},
},
};
});
```

### Breaking changes

Unknown

### Supporting development

I [tick all that apply]:

- [ ] am interested in building this feature myself
- [x] am interested in collaborating on building this feature
- [x] am willing to help testing this feature before it's released
- [ ] am willing to write a test-driven test suite for this feature (before it exists)
- [ ] am a [Graphile sponsor](https://www.graphile.org/sponsor/) ❤️
- [ ] have an active [support or consultancy contract](https://www.graphile.org/support/) with Graphile

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.