Skip to content

Commit

Permalink
Merge pull request #4705 from rmosolgo/relay-persisted-subscriptions-…
Browse files Browse the repository at this point in the history
…action-cable

Support Relay persisted queries in ActionCable handler
  • Loading branch information
rmosolgo authored Nov 17, 2023
2 parents 57da3a2 + 7b84e92 commit f82d193
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 3 deletions.
16 changes: 16 additions & 0 deletions guides/javascript_client/relay_subscriptions.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,22 @@ var subscriptionHandler = createRelaySubscriptionHandler({
var network = Network.create(fetchQuery, subscriptionHandler)
```

## With Relay Persisted Queries

If you're using Relay's built-in [persisted query support](https://relay.dev/docs/guides/persisted-queries/), you can pass `clientName:` to the handler in order to build IDs that work with the {% internal_link "OperationStore", "/operation_store/overview.html" %}. For example:

```js
var subscriptionHandler = createRelaySubscriptionHandler({
cable: createConsumer(...),
clientName: "web-frontend", // This should match the one you use for `sync`
})

// Create a Relay Modern network with the handler
var network = Network.create(fetchQuery, subscriptionHandler)
```

Then, the ActionCable handler will use Relay's provided operation IDs to interact with the OperationStore.

## fetchOperation function

The `fetchOperation` function can be extracted from your `fetchQuery` function. Its signature is:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { createActionCableHandler } from "../createActionCableHandler"
import type { Consumer } from "@rails/actioncable"

describe("createActionCableHandler", () => {
it("returns a function producing a disposable subscription", () => {
var wasDisposed = false
Expand All @@ -21,4 +22,43 @@ describe("createActionCableHandler", () => {

expect(wasDisposed).toEqual(true)
})

it("uses a provided clientName and operation.id", () => {
var handlers: any
var log: [string, any][]= []

var dummyActionCableConsumer = {
subscriptions: {
create: (_conn: any, newHandlers: any) => {
handlers = newHandlers
return {
perform: (evt: string, data: any) => {
log.push([evt, data])
}
}
}
}
}

var options = {
cable: (dummyActionCableConsumer as unknown) as Consumer,
clientName: "client-1",
}

var producer = createActionCableHandler(options);

producer(
{text: "", name: "", id: "abcdef"},
{},
{},
{ onError: () => {}, onNext: () => {}, onCompleted: () => {} }
)

handlers.connected() // trigger the GraphQL send

expect(log).toEqual([
["send", { operationId: "client-1/abcdef", operationName: "", query: "", variables: {} }],
["execute", { operationId: "client-1/abcdef", operationName: "", query: "", variables: {} }],
])
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ interface ActionCableHandlerOptions {
cable: Consumer
operations?: { getOperationId: Function}
channelName?: string
clientName?: string
}

function createActionCableHandler(options: ActionCableHandlerOptions) {
return function (operation: { text: string, name: string}, variables: object, _cacheConfig: object, observer: {onError: Function, onNext: Function, onCompleted: Function}) {
return function (operation: { text: string, name: string, id?: string }, variables: object, _cacheConfig: object, observer: {onError: Function, onNext: Function, onCompleted: Function}) {
// unique-ish
var channelId = Math.round(Date.now() + Math.random() * 100000).toString(16)
var cable = options.cable
Expand All @@ -39,7 +40,8 @@ function createActionCableHandler(options: ActionCableHandlerOptions) {
channelParams = {
variables: variables,
operationName: operation.name,
query: operation.text
query: operation.text,
operationId: (operation.id && options.clientName ? (options.clientName + "/" + operation.id) : null),
}
}
channel.perform('send', channelParams)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ function createLegacyRelaySubscriptionHandler(options: ActionCableHandlerOptions
} else if ((options as AblyHandlerOptions).ably) {
handler = createAblyHandler(options as AblyHandlerOptions)
} else {
throw new Error("Missing options for subscribtion handler")
throw new Error("Missing options for subscription handler")
}
return handler
}
Expand Down Expand Up @@ -47,6 +47,7 @@ function createRelaySubscriptionHandler(options: ActionCableHandlerOptions | Pus
{
text: request.text || "",
name: request.name,
id: request.id,
},
variables,
{},
Expand Down

0 comments on commit f82d193

Please sign in to comment.