# GraphQL Subscriptions

**URL:** <https://community.bluescape.com/t/graphql-subscriptions/2018>\
**Category:** Developer\
**Tags:** api\
**Created:** [July 26, 2022, 6:43pm UTC](https://community.bluescape.com/t/graphql-subscriptions/2018 "2022-07-26T18:43:43Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![Tom\_Garrett](https://avatars.discourse-cdn.com/v4/letter/t/258eb7/32.png) [@Tom\_Garrett](https://community.bluescape.com/u/Tom_Garrett)\
**Post date:** [July 26, 2022, 6:43pm UTC](https://community.bluescape.com/t/graphql-subscriptions/2018/1 "2022-07-26T18:43:43Z")

</div>

GraphQL Subscriptions enable clients to listen to real-time messages whenever important changes happen inside Bluescape workspaces and organizations. The client connects to the server with a bi-directional communication channel using the WebSocket protocol and sends a subscription query that specifies which event it is interested in. When an event is triggered, the Bluescape server executes the stored GraphQL query, and the result is sent back to the client using the same communication channel.

The client can unsubscribe by sending a message to the Bluescape server. The Bluescape server can also unsubscribe at any time due to errors or timeouts.

 ![](https://us1.discourse-cdn.com/bluescape/original/1X/350c64186a9f6b61412825ca13c3f95e8760138a.png)

### List of Subscriptions

You can access the playground via the [GraphQL Playground](https://api.apps.us.bluescape.com/v3/graphql) page. Click the **Docs** link on the far right border and look for the list of currently available subscriptions in the SUBSCRIPTIONS section at the bottom of the column.

### Example of implementation

Content in this page:

- [Subscription implementation in GraphQL Playground](https://community.bluescape.com/t/wip-graphql-subscriptions/2018#subscription-implementation-in-graphql-playground-4)
- [Subscription implementation in a NodeJS script](https://community.bluescape.com/t/wip-graphql-subscriptions/2018#subscription-implementation-in-a-nodejs-script-5)
- [Example of use of subscriptions: check ingestion status of uploads](https://community.bluescape.com/t/wip-graphql-subscriptions/2018#example-of-use-of-subscriptions-check-ingestion-status-of-uploads-6)
- [Example of use of subscriptions: use cursor to reconnect to a subscription](https://community.bluescape.com/t/wip-graphql-subscriptions/2018#example-of-use-of-subscriptions-use-the-cursor-to-reconnect-to-a-subscription-7)

### Example of subscription implementation

Below you can find 2 types of implementations: [using the GraphQl Playground](https://community.bluescape.com/t/wip-graphql-subscriptions/2018#subscription-implementation-in-graphql-playground-4) to test GraphQL and inspect the subscriptions, and [using a script](https://community.bluescape.com/t/wip-graphql-subscriptions/2018#subscription-implementation-in-a-script-5) to capture and process the subscription events.

#### Subscription implementation in GraphQL Playground

You can access the playground via the [GraphQL Playground](https://api.apps.us.bluescape.com/v3/graphql) page. Here is an example of a subscription for events, for reporting the change in position (x,y) of Image elements, using the `commands` subscription:

```auto
subscription imageElementUpdated($workspaceId: String!) {
  commands(workspaceId: $workspaceId) {
    ... on UpdateElementCommand {
      elementId
      workspaceId

      data {
        ... on UpdateImage {
          transform {
            x
            y
          }
        }
      }
    }
  }
}

```

Set the correct values for:

- **QUERY VARIABLES** :

```auto
{
    "workspaceId": "<workspaceId>"
}

```

- and **HTTP HEADERS**

```auto
{
  "Authorization":"Bearer <SET_TOKEN>"
}

```

Click the **Play** button in the top middle section of the screen. You should see a **Listening…** message at the bottom of the right panel in the Playground. Interact with an image in the workspace to change its position.  
After moving the image, a new event is reported to the subscription, where the position (x,y) has changed:

 ![](https://us1.discourse-cdn.com/bluescape/original/1X/4b7dcd7b87f11e6c933565c5914e8d26b7528305.png)

#### Subscription implementation in a NodeJs script

The implementation in the GraphQL Playground shows us how the data for the subscription is delivered. The next step is to use a script or an implementation to take specific actions based on the data of the events that we are receiving from the subscription.

Inspect the examples below to implement a basic parser for the subscription events.

```auto
/*
  To install, add the following dependencies to your package.json:
  {
    "name": "ws-client-demo",
    "version": "1.0.0",
    "type": "module",
    "license": "MIT",
    "dependencies": {
      "graphql": "^15.5.0",
      "graphql-ws": "^4.2.1",
      "ws": "^7.4.4"
    }
  }
  
  After creating the package.json, install the dependencies:
  npm install
*/

import ws from 'ws';
import {createClient} from 'graphql-ws';
const JWT_TOKEN = '<SET_TOKEN>';

// Please note the 'wss' protocol
const WS_URL = 'wss://api.apps.us.bluescape.com/v3/graphql';
const WORKSPACE_ID = '<workspaceId>';

const observer = {
  error(e) {
    console.log('Observer.error', e);
  },
  next(eventData) {
    console.log('Observer.next');
    console.dir(eventData, {depth: null});
    // Here you can inspect and process the incoming eventData to take specific actions 
  },
  complete() {
    console.log('Observer.complete');
  }
}
function subscribe(query, variables) {
  const client = createClient({
    url: WS_URL,
    webSocketImpl: ws,
    connectionParams: () => {
      return {
        Authorization: `Bearer ${JWT_TOKEN}`
      }
    },
  });
  client.subscribe({query, variables}, observer);
}

// Set the subscription
const GRAPHQL_SUBSCRIPTION = `subscription imageChangesSubscription($workspaceId: String!) {
    commands(workspaceId: $workspaceId) {
      ... on UpdateElementCommand {
        workspaceId
        elementId
        data {
          ... on UpdateImage {
            transform {
              x
              y
            }
          }
        }
      }
    }
  }`

subscribe( GRAPHQL_SUBSCRIPTION, {
    workspaceId: WORKSPACE_ID
  });

```

When you move an image, this is the type of event you receive (the value of the id field is just an example):

```auto
 Update received:
{
  data: {
    commands: {
      workspaceId: '<workspaceId>',
      elementId: '609abX787e69f2ca25b65262',
      data: { transform: { x: 13599.666666666668, y: -8254.500000000004 } }
    }
  }
}

```

You can parse this even data and trigger an action.

### Example of use of subscriptions: check ingestion status of uploads

Another interesting case for the use of subscriptions is to monitor the ingestion status of the upload of images, documents, or videos.

The upload of assets to the workspace will go through 3 ingestion stages:

- transfering
- processing
- complete\_success

You can use the example above and replace the graphQL subscription with the one below:

```auto
subscription viewUploadAssetIngestionStateSubscription($workspaceId: String!) {
    item: commands(workspaceId: $workspaceId) {
      ... on UploadAssetCommand{
          workspaceId
        elementId
        elementType
        ingestionState      
      }
      
    }
  }

```

The `ingestionState` field displays the status of each upload as it changes over time. When the status is `complete_success` it means that the upload has been completed successfully and you can interact with the object. Before this status, you cannot access or try to modify the still uploading element (you get an error from the API execution).

Example of the events reported by the `viewUploadAssetIngestionStateSubscription` above for the upload of an image (the values of `workspaceId` and `elementId` are sample values to show they belong to the same object being uploaded):

```auto
{
  data: {
    item: {
      workspaceId: '9D5UnzlRcvk8ujOgCK-J',
      elementId: '615e12bd90f5ca11cf8d951f',
      elementType: 'Image',
      ingestionState: 'transferring'
    }
  }
}
Observer.next
{ data: { item: {} } }
Observer.next
{
  data: {
    item: {
      workspaceId: '9D5UnzlRcvk8ujOgCK-J',
      elementId: '615e12bd90f5ca11cf8d951f',
      elementType: 'Image',
      ingestionState: 'processing'
    }
  }
}
Observer.next
{
  data: {
    item: {
      workspaceId: '9D5UnzlRcvk8ujOgCK-J',
      elementId: '615e12bd90f5ca11cf8d951f',
      elementType: 'Image',
      ingestionState: 'complete_success'
    }
  }
}

```

### Example of use of subscriptions: use the cursor to reconnect to a subscription

GraphQL subscriptions are long-lasting operations that can deliver changes in real-time. GraphQL `commands` subscription provides you with live updates that happen in a workspace. For example:

```auto
subscription($workspaceId: String!) {
  commands(workspaceId: $workspaceId) {
    ... on CreateElementCommand {
      element {
        id
        type: __typename
      }
    }
  }
}

```

GraphQL subscriptions deliver changes as long as the underlying connection is active. If the connection is terminated, the client must reconnect by re-sending the subscription operation. In this case, if changes happened to elements or to the workspace in between disconnect and reconnect events, the client will not receive these changes. To avoid loss of data your client can use cursors. GraphQL subscription **cursors** are identifiers that exist on every command, similar to the concept of an event unique ID. Then, it is a good practice to include the `cursor` field in the subscription.  
Your client can subscribe and receive GraphQL subscription commands with cursors. See the following example:

```auto
subscription($workspaceId: String!) {
  commands(workspaceId: $workspaceId) {
    cursor
    ... on CreateElementCommand {
      element {
        id
        type: __typename
      }
    }
  }
}

```

If your subscription was interrupted and you want to get all the events since the last available cursor, then provide the last known cursor value to a subscription like in the example below. This subscription also keeps receiving new events. It is like saying: “create a subscription, listing all the events since `lastKnownCursor` and all the new ones”.

```auto
subscription($workspaceId: String!, $lastKnownCursor: ID!) {
  commands(workspaceId: $workspaceId, cursor: $lastKnownCursor) {
    cursor
    ... on CreateElementCommand {
      element {
        id
        type: __typename
      }
    }
  }
}

```

Use these variables:

```auto
{
    "workspaceId": "<workspaceId>",
    "lastKnownCursor": "<last_known_cursor_value>"

}

```

The subscription lists all the events since the value of `lastKnownCursor`, and your client can process them. All the missed events are in the correct sequence.

 

> # Where to Next?
> 
> - [Create Rich Text in a Workspace](https://community.bluescape.com/t/wip-create-rich-text-in-a-workspaced/2019)
> - [Bluescape API Guides](https://community.bluescape.com/t/bluescape-api-guides-landing-page/2020)
> - [Bluescape API Overview](https://community.bluescape.com/t/wip-bluescape-api-overview/2021/2)
> - [Latest Developer topics](https://community.bluescape.com/c/developer/14)
> 
> **Not what you were looking for? Reply below or [Search](https://community.bluescape.com/search) the community and discover more Bluescape.**
