• Stars
    star
    107
  • Rank 323,587 (Top 7 %)
  • Language
    TypeScript
  • License
    MIT License
  • Created over 5 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Serverless GraphQL subscriptions

Apollo serverless demo

This project uses fanout-graphql-tools to demonstrate how to implement GraphQL subscriptions when Apollo Server is deployed on AWS Lambda. WebSocket connection management is delegated to Fanout Cloud such that Apollo does not require long-lived execution. There is no change to the wire protocol; Fanout is invisible to the GraphQL client.

There is a public deployment here: https://apollo.fanoutapp.com/

Usage

The demo is a basic GraphQL service with no frontend, although if the service is accessed from a browser then the GraphQL Playground will be loaded for easy testing. The service exposes an API for working with text notes. Below are some example operations to try.

Subscribing to new notes:

subscription {
  noteAddedToCollection(collection:"shopping") {
    id,
    content,
    collection,
  }
}

Adding a note:

mutation {
  addNote(note:{
    content:"buy bread",
    collection:"shopping",
  }) {
    id,
    content,
    collection,
  }
}

If you load the playground in two browser tabs, start a subscription in one and make a mutation from the other, then you'll see an update arrive over the subscription, like this:

{
  "data": {
    "noteAddedToCollection": {
      "id": "7bba1ad0-4816-47c4-9989-0465e8a5c6dd",
      "content": "buy bread",
      "collection": "shopping"
    }
  }
}

Here's an example of listening for updates using wscat:

$ wscat -s graphql-ws -c wss://apollo.fanoutapp.com/
connected (press CTRL+C to quit)
> {"type":"connection_init","payload":{}}
< {"type":"connection_ack"}
> {"id":"1","type":"start","payload":{"variables":{},"extensions":{},
"operationName":null,"query":"subscription { noteAddedToCollection(
collection: \"shopping\") { id content collection }}"}}
< {"id":"1","payload":{"data":{"noteAddedToCollection":{"id":
"f85157b8-abe5-4f5a-bb36-aa1b529674c2","content":"buy bread","collection":
"shopping"}}},"type":"data"}

How it works

At a high level:

  • Fanout Cloud manages the WebSocket connections.
  • Lambda (with API Gateway) runs the Apollo server, which is where the application logic lives.
  • DynamoDB is used to store GraphQL subscription state.

All WebSocket messages from the client are enveloped in an HTTP request and forwarded to the Apollo server. Apollo sends control messages in HTTP responses to associate WebSocket connections with Fanout publish/subscribe channels. Whenever Apollo needs to publish data to clients, it makes an HTTP request to Fanout Cloud with the payload, which will get injected into the appropriate WebSocket connections. It's important to note that it's the Apollo server that sets up the Fanout subscriptions, and the client has no awareness of this. For more about Fanout, see the docs.

The application keeps track of active GraphQL subscriptions by storing information about them in DynamoDB. When a mutation operation is performed, the database is checked for subscriptions that would need to be notified as a result. For each subscription that should receive an event, its Apollo resolver is executed, and the resulting filtered payload (if any) is sent to Fanout Cloud for client delivery.

Running locally

You can run the GraphQL Server locally by running:

npm start

This will run ./api/index.ts configured for in-memory storage.

Example:

$ npm start

> fanout-apollo-demo@ start /home/justin/dev/apollo-serverless-demo
> ts-node api/index

πŸš€ Server ready at http://localhost:57410/graphql
πŸš€ Subscriptions ready at ws://localhost:57410/

Deploying to ZEIT Now

Install the CLI:

npm install -g now

Deploy to the cloud:

now

Deploying to AWS

You can deploy the app to AWS and have it run on AWS Lambda, API Gateway, and DynamoDB for storage.

The specific AWS resources required are encoded in this source code repository using TypeScript and objects from the @pulumi npm modules. This is a pattern called Infrastructure as Code, and is useful because it lets us apply the same software development methodologies and change controls to our cloud resources as we do to our application source code.

You'll need an AWS Account. This repository will depend on the AWS_PROFILE environment variable being set. This value should correspond to an entry in your ~/.aws/credentials file, from which AWS SDKs will pull your account's access key and secret. For more on all this, see AWS User Guide - Named Profiles.

The following steps illustrate how to apply the configuration in this repository to 'the cloud'. If you encounter any issues in your development environment, please file an issue at https://github.com/fanout/apollo-serverless-demo.

  1. Ensure you have proper AWS credentials for our AWS accounts, add them to an aws-cli named profile, and ensure the AWS_PROFILE environment variable is set to the profile you want to use
export AWS_PROFILE=yourprofile
  1. Install pulumi following instructions at https://pulumi.io/quickstart/

  2. Clone this repository and cd into the top-level directory

  3. npm install

  4. pulumi up and follow the CLI instructions.

More Repositories

1

django-eventstream

Server-Sent Events for Django
Python
650
star
2

zurl

HTTP and WebSocket client worker with ZeroMQ interface
C++
388
star
3

pollymer

General-purpose AJAX/long-polling library
JavaScript
133
star
4

reconnecting-eventsource

A small decorator for the JavaScript EventSource API that automatically reconnects
TypeScript
95
star
5

websockhop

Network resilient WebSocket wrapper
JavaScript
83
star
6

webhookinbox

Receive HTTP callbacks and see the data in realtime
Python
80
star
7

python-faas-grip

FaaS GRIP library for Python
Python
67
star
8

django-grip

Django GRIP library
Python
66
star
9

condure

HTTP/WebSocket connection manager
Rust
63
star
10

js-grip

JavaScript GRIP library
TypeScript
47
star
11

kafka-sse-example

Expose Kafka messages via HTTP streaming API
Python
38
star
12

fanout-graphql-tools

GraphQL subscriptions using Fanout/Pushpin
TypeScript
32
star
13

node-faas-grip

FaaS GRIP library for Node.js
JavaScript
32
star
14

pygripcontrol

Python GRIP library
Python
31
star
15

serverless-websocket

"serverless" WebSocket example
Python
30
star
16

editor

Collaborative text editor using operational transformations
JavaScript
30
star
17

docker-pushpin

Dockerfile
26
star
18

go-gripcontrol

A GRIP library for Go.
Go
23
star
19

php-gripcontrol

A GRIP library for PHP.
PHP
20
star
20

pushpin-c1m

One million push connections on one server
PHP
20
star
21

leaderboard

Leaderboard example
JavaScript
20
star
22

express-grip

Express GRIP library
TypeScript
17
star
23

js-eventstream

Server-Sent Events for JavaScript
TypeScript
12
star
24

flychat

Serverless chat demo
JavaScript
12
star
25

tigase-zmq

Tigase ZeroMQ Gateway
Java
11
star
26

laravel-fanout

Fanout.io library for Laravel.
PHP
11
star
27

js-pubcontrol

JavaScript EPCP library
TypeScript
10
star
28

laravel-grip

A GRIP library for Laravel.
PHP
9
star
29

express-eventstream

Server-Sent Events for Express
JavaScript
8
star
30

pypubcontrol

Python EPCP library
Python
7
star
31

ruby-gripcontrol

A GRIP library for Ruby.
Ruby
7
star
32

qfiber

C++ coroutines library with channels
C++
7
star
33

todomvc-liveresource-react

JavaScript
6
star
34

headline

Python
6
star
35

js-serve-grip

Grip library for Express and Next.js
TypeScript
5
star
36

node-fanoutpub

Node.js FPP library
JavaScript
5
star
37

livecounter

Live counter API
Python
5
star
38

scaledemo

Python
4
star
39

audiostream

Stream live audio
Python
3
star
40

pyfanout

Fanout.io library for Python
Python
3
star
41

engine.io-as-websocket

Wraps Engine.IO to make it usable with the same API as WebSocket
JavaScript
3
star
42

php-pubcontrol

EPCP library for PHP
PHP
3
star
43

php-grip

Grip library for PHP
PHP
3
star
44

go-pubcontrol

Go EPCP library
Go
3
star
45

pysmartfeed

Python Smart Feed library
Python
3
star
46

rails-grip

Ruby on Rails GRIP library
Ruby
2
star
47

java-gripcontrol

A GRIP library for Java.
Java
2
star
48

java-fanout

Fanout.io library for Java.
Java
2
star
49

xmpp-ftw-fanout

XMPP-FTW Fanout plugin
JavaScript
2
star
50

go-fanout

Fanout.io library for Go.
Go
2
star
51

django-fanout

Fanout.io library for Django
Python
2
star
52

chat-demo-android

A chat demo using Fanout's APIs through event source
Java
2
star
53

vercel-websocket

JavaScript
2
star
54

django-liveresource

LiveResource library for Python/Django
Python
1
star
55

chat-demo-ios

An eventsource based chat app built to demo functionalities for Fanout
Swift
1
star
56

reliable-stream

Python
1
star
57

test-api

Minimal realtime API example
Python
1
star
58

demo

JavaScript
1
star