Photo by Chris Kristiansen (https://unsplash.com/@chriskristiansen)
Table of Contents
In this post we are going to take the hashing function we implemented in the previous post and move it to the Graphcool functions.
Functions need to be defined in the Graphcool service definition file (graphcool.yml
). Graphcool supports the following function types that can be invoked either as webhooks or as managed functions:
**operationBefore**
/**operationAfter**
)For this to work, you need to specify the operation on a model for which the function should be invoked. For example: Link.update
, Link.delete
or Link.create
. An example for when this type could be used is if we wanted to implement a feature that prevents certain users from creating more than X number of links. We could use the operationBefore
on Link.create
and run a function that checks how many links the user already created and either throw an error or allow the creation to happen.
Subscription requires a subscription query that determines when the function should be triggered (e.g. when an object is created, updated or deleted). The backing function is then executed after the mutation happens. An example of this could be if we wanted to send a welcome email each time a new user signs-up.
Resolvers are the most powerful types as they allow you to come up with a new mutation and/or query definition. We will use resolvers in one of the upcoming post where we will create a mutation for signing up and logging in users as well as a query that returns a logged in user.
To be honest, we could probably use all of the options above to implement our hashing function. In short, here’s how we’d do it:
We could use either of these two options. We would need to modify the CreateLinkMutation
in CreateShortLink.js
to remove the $hash
variable as well as make the hash field optional in the schema. Next, we’d move the createHash
function to the backend to either update the created link with a hash (if we use operationAfter
) or create a hash and return it for the mutation to complete if we use operationBefore
.
Just like we the above option, we need to remove the $hash
variable from CreateLinkMutation
and write a subscription query that fires when new Link is created — we already have that query, so we could update it like this:
subscription NewLinkCreatedSubscription {Link(filter: { mutation_in: [CREATED] })node {id}}}
In the handler function, we’d get the data returned from the subscription (id
), next we’d get the count of all links, create a hash and finally update the existing Link with this mutation:
mutation UpdateLinkWithHash($id: String!, $hash: String!) {updateLink(id: $id, hash: $hash) {id}}
With a resolver, we would extend our existing API with a new mutation called createHashMutation
. The function that would be executed when this mutation is called would go through similar things as if we’d use a subscription. Function would get the number of created links, generate a hash and then return that generated hash. Then, we could call our existing CreateLinkMutation and pass in the hash we from the createHashMutation
.
Since we will use a resolver for authenticating users later, let’s use a subscription to implement this — option 2 it is!
Follow the steps below to create a subscription and move the hashing function to the backend.
graphcool/src
folder in your project rootcreateShortLink.graphql
file with the following subscription that fires each time a link is created and returns its id:
subscription {Link(filter: { mutation_in: [CREATED] }) {node {id}}}
3. Add createShortLink.js
file that fires off each time a new link is created.
4. Install the dependencies for subscription function by running the following command from the graphcool
folder where package.json
file is:
$ npm install graphcool-lib --save
5. Update the graphcool.yml
to reference the graphql and js file we created:
functions:createShortLink:type: subscriptionquery: src/createShortLink.graphqlhandler:code: src/createShortLink.js
6. Deploy the changes and create the subscription:
$ graphcool deploy...
Subscription Functions
createShortLink+ A new subscription with the name `createShortLink` is created.
A couple of small things before we try out the subscription:
createHash
function, $hash
variable from the mutation and GET_LINK_COUNT_QUERY
from CreateShortLink.js
. Below is the updated file:2. Make the hash
field in types.graphql
optional, by removing the exclamation mark:
type Link @model {id: ID! @isUniquehash: Stringurl: String!description: String}
Run the graphcool deploy
again to update the type and we are ready to test this out!
Fire up the web site (yarn start
) if you don’t have it running already and try to create a new link — everything should work exactly like before, the only difference is that the hashing function is now being invoked as part of a subscription on the Link. To really make sure that this works, you can run graphcool logs
to get the invocation logs from your function(s). It looks like this:
If there’s an error, you will also get error details in here. Second option for looking at the logs and function invocations is to go to the http://graph.cool , click on the Functions and then on the createShortLink
function to get all the logs.
Function overview on Graph.cool
Another helpful command for testing the functions is the graphcool invoke-local
command from the CLI. Instead of going through our web site to create new links, we can directly send a JSON payload to the function like this:
$ graphcool invoke-local --function createShortLink --json event.json
Where event.json
can look like this:
{"data": {"Link": {"node": {"id": "LINK_ID"}}}}
This way you can test your function for bunch of scenarios that might be hard to test through the web site — e.g. invalid payloads, non-existent link IDs, etc.
In the next post of the series we will work on getting some short URL stats — number of clicks. In order to do that, we will have to come up with a handler for links. For example: if we generate hash “ABC123”, we will need to write some code that’s going to execute when user visits “http://localhost:3000/ABC123” and translate that hash to an actual link and redirect the user to it. Once we have the handler we can start collecting click stats.
Any feedback on these series is more than welcome! You can also follow me on Twitter and GitHub. If you liked this and want to get notified when other parts are ready, you should subscribe to my newsletter!