<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Matt Krick on Medium]]></title>
        <description><![CDATA[Stories by Matt Krick on Medium]]></description>
        <link>https://medium.com/@mattkrick?source=rss-ca93f36ae1ea------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/2*d-DTcx0_p7zpE685_VvTzA.jpeg</url>
            <title>Stories by Matt Krick on Medium</title>
            <link>https://medium.com/@mattkrick?source=rss-ca93f36ae1ea------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 07 Jun 2026 09:17:53 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@mattkrick/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Upgrading our React app to GraphQL Relay Hooks]]></title>
            <link>https://mattkrick.medium.com/upgrading-our-react-app-to-graphql-relay-hooks-2e0fe88bacd4?source=rss-ca93f36ae1ea------2</link>
            <guid isPermaLink="false">https://medium.com/p/2e0fe88bacd4</guid>
            <category><![CDATA[relay]]></category>
            <category><![CDATA[typescript]]></category>
            <category><![CDATA[graphql]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[react]]></category>
            <dc:creator><![CDATA[Matt Krick]]></dc:creator>
            <pubDate>Fri, 27 Aug 2021 19:22:19 GMT</pubDate>
            <atom:updated>2021-08-27T19:22:19.077Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/679/1*RG2n787iuQVANYUwQrp3qw.png" /><figcaption>React Relay GraphQL — Name a better trio</figcaption></figure><p>We’ve been on a forked version of Relay v8 for a couple years. While the new versions had some neat features, nothing really compelled us to upgrade until now. Relay v11 (the one with hooks) is the biggest release since Relay Modern &amp; it’s amazing. Aside from hooks, it lets us use React’s Suspense API instead of the render props pattern, allows for fine-grain control of query invalidation, and provides patterns for avoiding waterfall queries. While we’ve been able to clean up a bunch of our code, there have also been a few sharp edges during the migration. Let’s explore.</p><h3>Partial Data and Client Fields</h3><p>In our app, queries only need to load once. After the initial fetch, we use subscriptions to keep the data fresh. The only problem is figuring out how to prevent Relay from disposing of the query after the component got unmounted. In previous versions, we did this by forking the QueryRenderer. In v11, it’s as easy as setting the fetch policy to store-or-network and increasing the buffer size: const store = new Store(new RecordSource(), {gcReleaseBufferSize: 25}). The only gotcha was that any clientField would always get flagged as missing. For example, we had a field handler that turned rich text into plaintext for client-side searches:</p><pre>{<br>  content @__clientField(handle: “contentText”)<br>  contentText<br>}</pre><p>In the above case, the record was flagged as missing. To determine which field caused this, I put a breakpoint in the <a href="https://github.com/facebook/relay/blob/2732db54335462573697de1077af2d7ee0b08cae/packages/relay-runtime/store/DataChecker.js#L219">DataChecker</a> to pause when a missing field was hit.</p><p>The workaround is to set the hidden clientField record. It’s kept on the parent object under the handleKey. For example, every client handler we write now starts with this preamble:</p><pre>const handler: Handler = {<br>  update(store, payload) {<br>    const {dataID, handleKey} = payload<br>    const record = store.get(dataID)!<br>    const handleKeyValue = record.getValue(handleKey)<br>    if (handleKeyValue === undefined) {<br>      record.setValue(null, handleKey)<br>    }<br>  }<br>}</pre><p>By initializing the value from undefined to null the record is retained &amp; regarded as available.</p><h3>Subscriptions &amp; Cached Queries</h3><p>There’s only one problem with trusting subscriptions to keep all the data fresh: bad internet. If a computer goes to sleep, or a cell phone goes through a tunnel, it’s safe to say the data is stale &amp; should be refetched. Connectivity logic isn’t app specific, so it should live outside the app. In our case, we use a package called <a href="https://github.com/mattkrick/trebuchet-client">Trebuchet</a> to handle connectivity. When the client loses connection with the server, Trebuchet alerts the app that it is disconnected, kills the websocket, &amp; starts a new one. Once it reconnects, it fires reconnect callbacks. In this case, we simply refresh the active queries:</p><pre>useEffect(() =&gt; {<br>    const refresh = () =&gt; {<br>      loadQuery(variablesRef.current, {fetchPolicy: &#39;network-only&#39;})<br>    }<br>    environment.transport.trebuchet.on(&#39;reconnected&#39;, refresh)<br>    return () =&gt; {<br>      environment.transport.trebuchet.off(&#39;reconnected&#39;, refresh)<br>    }<br>  }, [])</pre><p>This is <strong>SO </strong>much more elegant that what we’ve done in the past!</p><h3>Hooks</h3><p>It took me awhile to understand usePreloadedQuery, useQueryLoader, and loadQuery. These were all new concepts because the QueryRenderer is the equivalent of the new useLazyLoadQuery. That hook is discouraged because it can lead to waterfall loading just like before. In my experience, it also didn’t lend itself well to the Suspense pattern, so I decided to forgo it entirely &amp; go with useQueryLoader.</p><p>Since my app previous used QueryRenderer extensively, it was already set up to perform lazy loading queries. I created a helper hook that makes useQueryLoader operate similarly to useLazyLoadQuery:</p><pre>const [queryRef, loadQuery] = useQueryLoader&lt;TQuery&gt;(query)</pre><pre>const varRef = useRef(variables)<br>if (!areEqual(variables, varRef.current)) {<br>  varRef.current = variables<br>}</pre><pre>// refetch when variables change<br>useEffect(() =&gt; {<br>  loadQuery(variables || {}, {fetchPolicy: &#39;store-or-network&#39;})<br>}, [varRef.current])</pre><p>As you can see, loadQuery gets called immediately when the component renders. While this pattern doesn’t make the data show up any sooner today, it keeps the door open in case I want to do some optimization later down the line . If I had used useLazyLoadQuery, those future refactors would be harder.</p><p>When I combine this hook with the query refresh hook above, it makes for a great one-liner that guarantees fresh data. The only problem was partial data…</p><h3>Partial Data</h3><p>Relay now supports partial data by default, which means a component can render as long as its fragment can be completed from the local cache. <strong>This is amazing!</strong> The only problem is that it doesn’t play well with createFragmentContainer. In other words, if you replace your QueryRenderer with usePreloadedQuery, any child components that use createFragmentContainerwill not trigger suspense (as of React v17.0.2 + Relay v11.0.2). For example:</p><pre>const Child = createFragmentContainer(() =&gt; {<br>  return &lt;div&gt;props.user.pet.name&lt;/div&gt;<br>}, {<br>  user: graphql`<br>  fragment Child_user on User {<br>    pet {<br>      name<br>    }<br>  }`<br>})</pre><pre>const Parent = () =&gt; {<br>  const data = usePreloadedQuery(graphql`<br>      query ParentQuery {<br>        user {<br>          ...Child_user<br>        }<br>      }<br>    `,<br>    queryRef<br>  )<br>  return &lt;Child user={data.user}/&gt;<br>}</pre><p>In the above scenario, The data in parent is partial. Child does <em>not</em> have the required data to render, yet it still gets called! If Child instead uses useFragment, it would suspend correctly. However, the same problem would still apply to descendant components. This left me with the following options:</p><ul><li>Refactor ALL instances of createFragmentContainer to useFragment</li><li>Include ...Child_user @relay(mask: false) in the Parent so the Child won’t render early (which would also cause Parent to subscribe to ALL changes and re-render a bunch)</li><li>Refactor <em>just </em>Child to useFragment &amp; pray that it requests a field that is not already cached so it suspends</li><li>Change the fetchPolicy to network-only and admit defeat</li><li>Use UNSTABLE_renderPolicy: &#39;full&#39; with usePreloadedQuery</li></ul><p>I opted for the 5th option. renderPolicy is eventually going away, but it’s still there, and using it here buys me some time so I don’t have to immediately refactor all my createFragmentContainer components to useFragment.</p><h3>Paginated Queries</h3><p>The final hurdle was migrating to usePaginationFragment. The new API for this hook is beautiful in its simplicity; bravo to the team for simplifying what is a ridiculously difficult area! Refetch queries are now generated automatically via a refetchable directive. There were only 2 gotchas during this refactor.</p><p>First, pagination only applies to fragments, so I found myself calling usePreloadedQuery and usePaginationFragment in the same component. It felt weird to have a query &amp; fragment in the same component, but it is otherwise harmless.</p><p>Second, the refetchable fragment is on Query. Maybe I’m alone, but this was the first time I’ve ever fragmented on the Query type. Usually I fragment on Viewer, but I couldn’t figure out how to declare my User object as using the Viewer protocol.</p><h3>Entry Points</h3><p>Entry points allow you to fetch different components based on the data returned. This is a really cool concept, but honestly I don’t use it for 2 reasons.</p><p>First, React.lazy is good enough. Sure, it requires an extra round trip, but that roundtrip is for a .js, which comes from our CDN so it’s extra fast.</p><p>Second, and most importantly, we have a Progressive Web App (PWA). That means most of those async chunks are fetched from the CDN via service worker long before they’re used. Sure, the client might not use every chunk, but making the app faster only costs us a few extra gigabytes/month of throughput. At Facebook scale, the cost may be prohibitive. At our scale, it’s literally pennies.</p><h3>Conclusion</h3><p>Overall, the initial upgrade took 2 days to complete. The business case to upgrade was the following:</p><ul><li>The old version had old dependencies with known vulns</li><li>Declarative errors &amp; loading states using Data Fetching with Suspense</li><li>Attract new developers with our clean, modern codebase</li><li>The new API is simpler, so it’s easier to train new developers on the new patterns</li><li>Less code (AKA surface area for bugs) using directives like appendEdge</li><li>Easier to upgrade to a newer version when the next killer feature drops</li></ul><p>Now that the patterns are in place, we can distribute the work across our team and complete the refactor in the coming months. We won’t explicitly create issues to refactor from createFragmentContainer to useFragment. However, if one of us is already working on a component that uses the legacy API, we’ll take an extra minute to upgrade to useFragment. We call this “in the neighborhood” refactoring. We use it for massive, app-wide refactors such as migrating to Typescript or Emotion for CSS-in-JS. It’s been a great pattern to ensure that each developer can still ship user value &amp; work on challenging problems.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2e0fe88bacd4" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Nesting GitHub’s API in your GraphQL Schema]]></title>
            <link>https://levelup.gitconnected.com/nesting-githubs-api-in-your-graphql-schema-bf87b96177c9?source=rss-ca93f36ae1ea------2</link>
            <guid isPermaLink="false">https://medium.com/p/bf87b96177c9</guid>
            <category><![CDATA[nodejs]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[typescript]]></category>
            <category><![CDATA[graphql]]></category>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[Matt Krick]]></dc:creator>
            <pubDate>Fri, 07 May 2021 17:55:49 GMT</pubDate>
            <atom:updated>2021-05-10T23:43:39.493Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="Image by Aaron Ortbals" src="https://cdn-images-1.medium.com/max/1000/1*cIYUiIzjRw-nHXqrCiV2YA.png" /><figcaption>Image by Aaron Ortbals</figcaption></figure><p>GraphQL is great. Every GraphQL endpoint agrees to speak the same language of {data, errors} and that makes communication between servers easy. Now suppose two public APIs both speak GraphQL; what advantages can we leverage? Packages like <a href="https://www.graphql-tools.com/">graphql-tools</a> make it easy to merge and stitch schemas together, which allows teams to build out separate parts of their subschemas via join and union functionality. But what about 3rd party schemas that have their own authentication, rate limiting, and errors? For example, take a look at <a href="https://docs.github.com/en/graphql/overview/explorer">GitHub’s GraphQL API</a>. Wouldn’t it be great if you could nest GitHub’s endpoint in your own schema? In a single GraphQL query, you could get the user’s name from your application as well as their bio from GitHub:</p><pre># Application schema<br>query {<br>  viewer {<br>    name<br>    githubApi {<br>      # GitHub&#39;s schema<br>      query {<br>        viewer {<br>          bio<br>        }<br>      }<br>    }<br>  }<br>}</pre><p>Of course this is only the beginning. A client could update your app and GitHub without any extra backend logic. Just good ‘ol GraphQL:</p><pre>mutation ($userId: String!) {<br>  addFriend(userId: $userId) {<br>    user {<br>      name<br>      githubApi {<br>        mutation {<br>          followUser(input: {userId: $userId}) {<br>            user {<br>              bio<br>            }<br>          }<br>        }<br>      }<br>    }<br>  }<br>}</pre><p>With <a href="https://github.com/ParabolInc/nest-graphql-endpoint">nest-graphql-endpoint</a>, this is finally possible 🎉.</p><h3>The Business Case</h3><p>Building a successful SaaS today means meeting customers where they are — integrating against the tools they already use. I’ve built integrations for Slack and Atlassian, but when it came to building a GitHub integration, I noticed I was re-creating a lot of the logic that GitHub’s API already had built-in.</p><p>For example, our <a href="https://www.parabol.co/solutions/sprint-poker">planning poker meeting</a> fetches all the team’s stories from GitHub, provides a fun, immersive way to score each story, and exports the scores back out to GitHub. Without nesting GitHub’s schema, I made my own GitHubIntegration object that had a repos field. That field had a custom resolve function that fetched the repos from GitHub by using a handwritten GraphQL string. This wasn’t great for a few reasons:</p><ul><li>It’s extra code that I have to maintain</li><li>The query doesn’t expressively show front end devs which parts comes from GitHub</li><li>Without a dataloader, multiple queries can cause multiple fetches to GitHub</li><li>Even with a dataloader, multiple fetches to GitHub are unavoidable unless every query is identical (thus overfetching)</li></ul><p>What I needed was a way to batch all the fragments going to GitHub, merge them into a single network request, and then parse the response into their corresponding fragments again. Why batching? Because in the real world, queries can get pretty large &amp; often repeat themselves:</p><pre>query {<br>  viewer {<br>    githubApi {<br>      query {<br>        ...Bio<br>      }<br>    }<br>    myTasks {<br>      user {<br>        githubApi {<br>          query {<br>            ...Bio<br>            viewer {<br>              bio<br>              id<br>            }<br>          }<br>        }<br>      }<br>    }<br>  }<br>}</pre><pre>fragment Bio on _extGitHubQuery {<br>  viewer {<br>    bio<br>  }<br>}</pre><h3>How it Works: nest-graphql-endpoint</h3><p>For all of this complexity, I wanted a way to nest endpoints in my schema with just a single line of code:</p><pre>const mergedSchema = nestGitHubEndpoint({<br>  parentSchema,<br>  fieldName: &#39;githubApi&#39;,<br>  parentType: &#39;User&#39;,<br>  resolveEndpointContext: (source) =&gt; ({accessToken: source.accessToken})<br>})</pre><p>That’s it! Your User object now has a githubApi object that includes queries, mutations, and errors. resolveEndpointContext allows you to fetch and provide necessary keys to access the endpoint.</p><p>Behind the scenes, here’s how it works:</p><ol><li>It fetches the GitHub schema &amp; prefixes all the __typename fields so you can write your query without worrying about naming conflicts</li><li>It collects all the fragments inside the gitHubApi objects &amp; merges them into a single query</li><li>It prunes unused variables, variable definitions, &amp; fragments</li><li>It un-prefixes the __typename fields so GitHub understands the query</li><li>In the event of a name conflict, it will alias fields before the request is fetched</li><li>It de-aliases the response, re-applies the __typename prefix, and filters the errors by path</li></ol><p>Let’s see how it’s built.</p><h3>Building the GitHub Schema</h3><p>GitHub offers a great package called <a href="https://github.com/octokit/graphql-schema">@octokit/graphql-schema</a>. It provides a GitHub schema that is guaranteed to be up to date so I don’t need to asynchronously fetch the introspection schema. Then, I use <a href="https://www.graphql-tools.com/">graphql-tools</a>’ wrapSchemato <a href="https://github.com/mattkrick/nest-graphql-endpoint/blob/main/src/nestGraphQLEndpoint.ts#L44">rename the types with my prefix</a>. wrapSchema internally adds a proxying resolver that calls their delegateToSchema function. Since we’re handling all the fetching ourselves, we can overwrite that resolver with the default GraphQL resolver:</p><pre>(source, _, _, info) =&gt; source[info.fieldName]</pre><p>Finally, we use graphql-tools to <a href="https://github.com/mattkrick/nest-graphql-endpoint/blob/main/src/nestGraphQLEndpoint.ts#L77">merge our wrapped schema</a> into our parent schema. That gives us an object extension that looks like this:</p><pre>user {<br>  githubApi {<br>    errors {...}<br>    query {...}<br>    mutation {...}<br>  }<br>}</pre><p>Note that errors is its own field, even though it will be populated by the response of query or mutation. By design, GraphQL makes it seemingly impossible for 1 field to populate the response of another. To get around this, the errors field returns a promise &amp; exposes the resolve callback to the other operations by mutating the source. <a href="https://github.com/mattkrick/nest-graphql-endpoint/blob/main/src/nestGraphQLEndpoint.ts#L149-L165">You can call it hacky</a>, but I think it’s pretty clean 😎.</p><h3>Batching the Fragments</h3><p>Before the days of Urql, Apollo, and Relay Modern, I wrote a bad GraphQL client cache called <a href="https://github.com/mattkrick/cashay">Cashay</a>. While the project didn’t go anywhere, it taught me a bunch about the GraphQL AST. For example, traversing an AST is painful, but GraphQL has a node visitor function built-in!</p><p>Let’s suppose our query has a bunch of variables, but only some of them need to be sent to GitHub. How do we figure out which variables to prune? It’s as simple as:</p><pre>const usedVariables = new Set&lt;string&gt;()<br>graphql.visit(selectionSet, {<br>  Variable(node) {<br>    usedVariables.add(node.name.value)<br>  },<br>})</pre><p>This same pattern can be repeated for fragments, variable definitions (the chunk that looks like $foo: String!, $bar: ID), and even the __typename fields that we prefixed. Once each fragment is refactored into a standalone query, it is time to batch as many together as possible and merge them.</p><p>To accomplish the batching, we use a <a href="https://github.com/mattkrick/nest-graphql-endpoint/blob/main/src/getDataLoader.ts#L9-L11">dataloader with the caching functionality turned off</a>. Why no cache? Each request will have a query that is a little different than the others. For example, one fragment might ask for viewer {id} while the other asks for viewer {id, bio}. We <em>want</em> to merge those together, and if we cached based on the key, then they’d be kept separate.</p><p>That said, we want to <a href="https://github.com/mattkrick/nest-graphql-endpoint/blob/main/src/getDataLoader.ts#L5">reuse the same dataloader for the entire execution</a>, so we keep all the dataloaders in a WeakMap where the key is the context because a new context is created for each call to GraphQL.execute. By using a WeakMap, we are preventing a memory leak because as soon as GraphQL.execute no longer references the context, it will be garbage collected from the WeakMap, too.</p><p>Once a single tick has passed, dataloader calls its batch function with an <a href="https://github.com/mattkrick/nest-graphql-endpoint/blob/main/src/batchFn.ts#L25">array of queries &amp; variables that we can merge together</a>. First, <a href="https://github.com/mattkrick/nest-graphql-endpoint/blob/main/src/mergeGQLDocuments.ts#L108">we merge all the fields that have unique names</a>. Then, if two fields share a name, <a href="https://github.com/mattkrick/nest-graphql-endpoint/blob/main/src/mergeGQLDocuments.ts#L124">we compare all their children</a>. If the two fields are different, we <a href="https://github.com/mattkrick/nest-graphql-endpoint/blob/main/src/mergeGQLDocuments.ts#L59-L67">alias one of them</a>:</p><pre><strong># Before</strong><br>query {<br>  repository(name: &quot;parabol&quot;, owner: &quot;parabolinc&quot;) {<br>    id<br>  }<br>}<br>query {<br>  repository(name: &quot;nest&quot;, owner: &quot;mattkrick&quot;) {<br>    id<br>  }<br>}</pre><pre><strong># After</strong><br>query {<br>  repository(name: &quot;parabol&quot;, owner: &quot;parabolinc&quot;) {<br>    id<br>  }<br>  repository_2: repository(name: &quot;nest&quot;, owner: &quot;mattkrick&quot;) {<br>    id<br>  }<br>}</pre><p>This strategy allows us to batch an endless number of fragments together into one network request. We just have to keep a list of the aliases we added so the final response looks just like the <strong>#Before</strong> request.</p><h3>Handling the Response</h3><p>When GitHub responds, it might not be a GraphQL object. GitHub <a href="https://github.com/mattkrick/nest-graphql-endpoint/blob/main/src/nestGitHubEndpoint.ts#L48">could be down</a>, or the <a href="https://github.com/mattkrick/nest-graphql-endpoint/blob/main/src/nestGitHubEndpoint.ts#L37">gateway could take too long to respond</a>, or if the auth token was invalid, it might just send{message}. To handle those cases, the executor wraps the fetch with a timeout &amp; if the response doesn’t look like a GraphQLExecutionResult, it will coerce it into one.</p><p>Once we have something in the shape of {data, errors}, all that’s left to do is <a href="https://github.com/mattkrick/nest-graphql-endpoint/blob/main/src/batchFn.ts#L54-L57">create one response object for each fragment</a>. That means de-alias the fields that we renamed, re-prefix the __typename fields, and <a href="https://github.com/ParabolInc/nest-graphql-endpoint/blob/main/src/filterErrorsForDocument.ts#L4-L23">filter errors by fragment</a>. Filtering errors is easy because most errors have a path that shows where the error occurred. For example, if the path is[&#39;viewer&#39;, &#39;repository_2&#39;] , then we know the error should only appear in the 2nd fragment.</p><h3>Conclusion</h3><p>Nesting GraphQL endpoints is the next step in GraphQL’s world domination. In a future where every service uses a GraphQL schema, integrations will be a breeze to implement and require a bunch less code. Sound like fun? <a href="https://www.parabol.co/join">We’re hiring</a>. Let’s build cool stuff together.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=bf87b96177c9" width="1" height="1" alt=""><hr><p><a href="https://levelup.gitconnected.com/nesting-githubs-api-in-your-graphql-schema-bf87b96177c9">Nesting GitHub’s API in your GraphQL Schema</a> was originally published in <a href="https://levelup.gitconnected.com">Level Up Coding</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[GraphQL After 4 Years: Scaling Subscriptions]]></title>
            <link>https://mattkrick.medium.com/graphql-after-4-years-scaling-subscriptions-d6ea1a8987be?source=rss-ca93f36ae1ea------2</link>
            <guid isPermaLink="false">https://medium.com/p/d6ea1a8987be</guid>
            <category><![CDATA[nodejs]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[typescript]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[graphql]]></category>
            <dc:creator><![CDATA[Matt Krick]]></dc:creator>
            <pubDate>Mon, 02 Mar 2020 13:51:42 GMT</pubDate>
            <atom:updated>2020-03-02T13:51:42.106Z</atom:updated>
            <content:encoded><![CDATA[<h3>GraphQL Lessons After 4 Years: Scaling Subscriptions</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*in3ZlGyo9fHzqXtG5TDSlA.jpeg" /></figure><p>Scaling is relative. When Uber builds a scalable metric service, they build a <a href="https://www.m3db.io/">proprietary database</a> to resolve their queries. When Facebook scales a live feed, they build it to support millions of connected clients. This post is for the rest of us. Subscriptions in GraphQL have taken a back seat and it’s my goal to change that.</p><p>The most popular subscription client is <a href="https://github.com/apollographql/subscriptions-transport-ws/issues/729">abandonware</a> and uses an <a href="https://github.com/apollographql/subscriptions-transport-ws/issues/349">insecure</a>, inefficient protocol. That means those of us who want to build a real-time app are forced to roll our own. So if you have dreams of hitting 10,000 connected clients, but you’re also terrified that it might cause your server to catch fire, read on. We’ll walk through the GraphQL reference implementation, tear it apart to maintain a stateless execution service, and use some clever tricks to keep your response times <em>way </em>lower than any hosted GraphQL service out there.</p><h3>GraphQL Subscription Basics</h3><p>The lifecycle of a graphql query is pretty simple. The server receives a query, parses it, validates it, then resolves it. Using <a href="https://github.com/graphql/graphql-js">graphql-js </a>, a basic implementation simply calls the graphql function. A slightly more advanced implementation caches the parsed &amp; validated query AST so the server only has to worry about calling execute. Subscriptions are similar, except since we want an async iterable instead of a promise, we call subscribe instead of execute.</p><p>Behind the scenes, the subscribe <a href="https://github.com/graphql/graphql-js/blob/4150d1f51360a7981181cfec42a135394c7340f1/src/subscription/subscribe.js#L116">function</a> does only two things. First, it creates a source event stream. Then, for every source event, it maps the event to a response. It’s simpler than it seems. A source event is nothing more than what gets posted to the PubSub. That event then gets passed to the execute function and out pops the response, which you can send to the client.</p><p>There’s a good <a href="https://github.com/graphql/graphql-spec/blob/master/rfcs/Subscriptions.md">reason for two streams</a>. Imagine Alice triggers a mutation like CreateTask and we want to tell Bob about that. So, the mutation pushes the source event to the PubSub, but what should the source event include? To answer that question, we need to know what Bob had requested. Maybe Bob wants the entire Task, or maybe just <em>who </em>made the task. Heck, he may just want to know the updated total number of tasks! Since we can’t be sure until we look at Bob’s subscription (which might be on a different server) the best we can do is include the bare minimum: a taskId and the payload type to resolve the response, like CreateTaskPayload (Pro tip: sharing a payload type between mutations and subscriptions greatly simplifies your business logic, see <a href="https://hackernoon.com/the-hybrid-strategy-for-graphql-subscriptions-dd5471c45755">The Hybrid Strategy for GraphQL Subscriptions</a>).</p><p>The ability for a single event to transform into a bespoke response for each subscriber is powerful, and something GraphQL offers out of the box. The problem arises when we begin to scale — our GraphQL execution service is tightly coupled to the WebSockets and subscriptions that rely on it. In a perfect world, our GraphQL execution service would be stateless, and our subscription service would maintain the subscriptions and WebSocket connection. So let’s build it.</p><h3>Creating a Stateless Execution Service</h3><p>In a <a href="https://github.com/ParabolInc/parabol/blob/master/packages/server/graphql/executeGraphQL.ts#L16-L29">production application</a>, GraphQL queries and mutations can come in from a variety of sources. From our client app, they arrive as persisted queries. From our GraphiQL admin interface, they come in as a full string that will need to be parsed &amp; validated. If it is a webhook or superuser, it might use a private schema. If the caller is a subscription, we’ll need to pass in a rootValue and hopefully reuse the <a href="https://github.com/graphql/dataloader">dataloader</a> to reduce resolution time. No matter the business logic, <strong>there is no state preserved by the service</strong>. This is important because as we squeeze performance out of it, we only have to focus on improving throughput, not memory management. That means we can incrementally improve the service by introducing graphql-jit, deploying more instances around the globe, and using dataloaders more aggressively (see tips below).</p><h3>Creating a GraphQL Subscription Service</h3><p>With query execution solved for, all that remains is building a service that holds onto the state: the transport (WebSocket, SSE, or WebRTC) and GraphQL subscriptions. Think of a subscription like a database cursor, except in the form of an async iterable.</p><p>The life of a subscription begins with emitting an event to the PubSub (e.g. Redis, RabbitMQ) from a mutation. From there, the PubSub listener needs to look up a list of GraphQL Subscriptions and republish the event to each. It’s a PubSub inside a PubSub, and <a href="https://github.com/ParabolInc/parabol/blob/master/packages/server/utils/GraphQLRedisPubSub.ts#L16-L79">you can build one in 50 LOCs</a>. Note that while some npm packages offer this functionality, I have found them to be largely <a href="https://github.com/davidyaha/graphql-redis-subscriptions/blob/master/src/redis-pubsub.ts#L58-L59">inefficient</a> (e.g. unnecessary lookup tables) and at times <a href="https://github.com/davidyaha/graphql-redis-subscriptions/search?q=memory+leak&amp;type=Issues">leak memory</a>. <strong>In my experience, if it’s 100 LOCs or less, it’s better to build vs. buy.</strong></p><p>The second trick is to convert that <a href="https://github.com/ParabolInc/parabol/blob/master/packages/server/utils/SubscriptionIterator.ts#L10-L67">event callback handler into an async iterator</a>. If this looks a little intimidating, don’t worry. The article <a href="https://itnext.io/understand-async-iterators-665259680044">Understand Async Iterators Without Really Trying</a> teaches you how to do it in 5 minutes using a simple click listener. Why not NodeJS streams or observables? Simply because async iterators are native ECMAScript, which is why graphql-js chose to use them.</p><p>Now, instead of calling subscribe, which uses the default execute function, we call createSourceEventStream, which will <a href="https://github.com/ParabolInc/parabol/blob/master/packages/server/graphql/subscribeGraphQL.ts#L59-L65">return the source event stream</a> we just created. While the function may seem esoteric, this is <a href="https://github.com/graphql/graphql-js/blob/4150d1f51360a7981181cfec42a135394c7340f1/src/subscription/subscribe.js#L194-L197">exactly why it was built</a>. The final step is to transform the source event into a response by asynchronously calling our stateless execution service. While the <a href="https://github.com/ParabolInc/parabol/blob/master/packages/server/graphql/ResponseStream.ts">full implementation</a> is less than 50 LOCs, the gist is even shorter:</p><pre><strong>async next() {<br>  </strong><em>// wait for a new source event from the PubSub<br></em><strong><em>  </em>const sourceIter = <em>await</em> this.sourceStream.next()</strong></pre><pre><em>  // if the event is &quot;done&quot; then there&#39;s no value<br></em><strong><em>  if</em> (sourceIter.done) <em>return</em> sourceIter</strong></pre><pre><em>  // include the socketId of the user that triggered the mutation <br>  // and the dataLoaderId so we can reuse it<br></em><strong><em>  </em>const {mutatorId, dataLoaderId, rootValue} = sourceIter.value</strong></pre><pre><em>  // include everything needed to execute the query<br></em><strong><em>  </em>const {socketId, authToken, query, variables} = this.context</strong></pre><pre><em>  // ignore the listener if they triggered the mutation<br></em><strong><em>  if</em> (mutatorId === socketId) <em>return</em> this.next()</strong></pre><pre>  <strong>const result = <em>await</em> callStatelessExecuteService({<br>  query,<br>  authToken,<br>  dataLoaderId,<br>  variables,<br>  rootValue,<br>  socketId<br>  })<br>  <em>return</em> {done: false, value: result}</strong><br><strong>}</strong></pre><p>And there we have it! The ResponseStream is calling our stateless execution service instead of defaulting to an execute call. As we grow the number of stateless execution services, we can put them behind their own reverse proxy (or even use a hosted service). We can also independently scale our socket servers, which will become critical as we strive to reduce intra-team latency for our growing international user base. But before we do that, we’ll want to make sure we squeeze all the efficiency we can out of each service.</p><h3>Maximizing Efficiency</h3><h4>Tip #1: Use a DataLoader</h4><p>Getting all the efficiency out of a stateless execution service begins with the dataloader. As you determine which queries are hot, you can refactor your direct database queries to using a dataloader. This will save duplicate queries, which is extremely useful for graph-type data structures (it’s called GraphQL for a reason!). For example, if a Team requests a User that requests the Team, it’ll only request the Team once. Caching individual DB hits is <em>far</em> more powerful than something that caches the entire query, and far more beneficial for real-time results.</p><h4>Tip #2: Reuse DataLoader for Subscriptions</h4><p>If your business logic allows, you can reuse the same dataloader that your mutation used for the subscription. In practice, this can reduce your resolution time to &lt;1ms for subscription payloads. All that’s required is a <a href="https://github.com/ParabolInc/parabol/blob/master/packages/server/graphql/DataLoaderCache.ts">dictionary of dataloaders</a> with a TTL on each. Again, nothing that 50 LOCs can’t fix. To reuse the dataloader, simply publish its ID so the subscription service knows which execution service to call.</p><h4>Tip #3: Lazily Instantiate DataLoaders</h4><p>In earlier versions, before every GraphQL execution I would create an object with about 30 dataloaders in it and add that to the GraphQL context. After profiling the heap usage, I found that it was allocating/GCing ~16KB per request! So, by using a getter pattern, I refactored the <a href="https://github.com/ParabolInc/parabol/blob/master/packages/server/dataloader/RethinkDataLoader.ts#L57-L74">class to only instantiate a dataloader when used</a>. By using some Typescript trickery, I was able to maintain the same type-safe guarantees so typos are still caught before runtime.</p><h4>Tip #4: Use <a href="https://github.com/zalando-incubator/graphql-jit">graphql-jit</a></h4><p>After a GraphQL query is parsed and validated, you’re left with an AST that doesn’t have predictable return values. While this isn’t too important to the developer, it’s hugely important to the V8 JavaScript engine. graphql-jit rewrites the AST into a function that provides predictable return types, which reduces the admittedly non-trivial overhead that GraphQL uses.</p><h4>Tip #5: Don’t Monitor so Gosh-Darn Always</h4><p>Hosted GraphQL solutions that offer a monitoring “feature” do more harm than good. The overhead of these services — checking the resolution time for every single GraphQL field is <em>not</em> trivial. Have a problem that you need to narrow down? Monitor up. But once things look good, don’t accept a 20%+ increase in resolution time as a cost of doing business.</p><h4>Tip #6: Use Persisted Queries</h4><p>Replacing the full query string with a hash is both more efficient and secure. In our app, certain subscription queries were upwards of 15KB. Assuming an MTU of 1500 bytes, that means sending 10 packets to the server — a difficult task for a mobile device on the go. A single hash guarantees it fits into a single packet. Using a persisted query also means the query is trusted. No annoying “security researchers” making arbitrarily deep queries in an attempt to DOS our server. The only gotcha is that we need to know if the hash refers to a a subscription or a query/mutation to dispatch it to the correct service. To do that, you can write a <a href="https://github.com/ParabolInc/parabol/blob/master/packages/server/graphql/persistFunction.js">custom hashing function</a> that prefixes the query hash with the operation type.</p><h4>Tip #7: Use Execution Results to Update Subscription State</h4><p>Whether you use a JWT or a session ID, chances are your WebSocket has some authentication state that a GraphQL mutation may change. For example, if you have a resetPassword mutation, you’ll probably want to force all other connected clients for that user to log out. Simply check the payload type of the result, and <a href="https://github.com/ParabolInc/parabol/blob/master/packages/server/graphql/subscribeGraphQL.ts#L89-L94">handle it appropriately</a>. In practice, this allows us to guarantee the validity of the JWT for the session, which means we only have to check the JWT blacklist when the socket connects. That’s a huge performance win and addresses the #1 concern that’s always brought up in the cringeworthy, never-ending “JWT is bad” debates.</p><h4>Tip #8: Popular Doesn’t Mean Better</h4><p>What’s the difference between a Junior and Senior Developer? The Senior knows that the sexy hosted solution with the CLI that sets up your project in “3 Easy Steps” is going to be the bane of your existence in 6 months when you’re locked into its walled garden and you need to do something it doesn’t support. Hosted solutions are buggy. A small SaaS can go broke. A megacorp can sunset services with little warning (Google, anyone?). You know what’s sexy? <strong>A vanilla GraphQL server on bare metal.</strong></p><h3>Wrapping Up</h3><p>There you have it. Everything I’ve learned about GraphQL Subscriptions after 4 years of trial and error. If playing with this stuff is interesting to you, join the fun and PR some open source projects! For example, <a href="https://github.com/zalando-incubator/graphql-jit/issues/74">graphql-jit</a> needs a PR to support subscriptions. If getting paid to write open-source code is your jam and you’d like to do it from anywhere in the world (cheers from Medellín, Colombia) <a href="https://www.parabol.co/join">we’re hiring</a> folks to come build the future of remote work.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d6ea1a8987be" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Understand Async Iterators Without Really Trying]]></title>
            <link>https://itnext.io/understand-async-iterators-665259680044?source=rss-ca93f36ae1ea------2</link>
            <guid isPermaLink="false">https://medium.com/p/665259680044</guid>
            <category><![CDATA[front-end-development]]></category>
            <category><![CDATA[nodejs]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[react]]></category>
            <dc:creator><![CDATA[Matt Krick]]></dc:creator>
            <pubDate>Wed, 01 Aug 2018 20:05:13 GMT</pubDate>
            <atom:updated>2018-08-01T20:05:13.163Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ePBvJ78g2a614Rpe0qoGgg.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/photos/SB_L2cbuLQ0?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">paolo candelo</a></figcaption></figure><p>Nobody likes a callback. It’s like a modern day equivalent of a GOTO statement. But how can we replace those pesky ones like click handlers? Chances are, you’ve refactored all all the easy ones into async/await statements, but there are still those pesky holdouts like DOM events, WebSockets, event emitters, and any other stream-like object. Sure, we could turn those into Observables, but turning 1 callback into 3 doesn’t seem like much of an improvement. If I can promisify a function, why can’t I iterable-ify an event stream? The answer is the new 2018 async iterables, and since it was first proposed a few years ago, there has been a lot of old, confusing, and just plain wrong info out there. So, through the magic of trial and error, here’s how I wrote a helper to turn click handlers into for-loops.</p><h3>Starting Simple</h3><p>In programming, just like in life, lazy is usually better. So, when I build something new, I like to be as lazy as possible and delay writing code that makes me think. So, let’s just write what we want it to look like &amp; stick all the hard stuff in a black box:</p><pre><em>// I want to go from this<br></em>document.addEventListener(&#39;click&#39;, (event) =&gt; console.log(&#39;click&#39;)<br><br><em>// to this<br>const </em>clicks = <strong>streamify</strong>(document, &#39;click&#39;)<br><em>for await </em>(<em>const </em>event <em>of </em>clicks) {<br>  console.log(&#39;click&#39;)<br>}</pre><p>So far so good! Now we just need that magical streamify function to actually do something. We know it’s going to call addEventListener, which takes a handler that gets the event. So let’s fill in just the easy parts and put the hard stuff in another black box:</p><pre><em>function</em> streamify(element, listener) {<br>  <em>const </em>handler = (event) =&gt; {<strong><br>    // do magic here<br>  </strong>}<strong> </strong><br>  element.addEventListener(listener, handler)<br>}</pre><p>Progress! Now avoiding the difficult things, let’s figure how to return an “async iterator”. To be honest, I’m not really sure what that looks like, I can’t just write new AsyncIterator(), but I know async means promise and an iterator is something that returns more than 1 value, kinda like a generator, so let’s roll with that and return an endless supply of promises. Useless functions are my specialty, so that’s easy:</p><pre><strong><em>function</em>*</strong> streamify(element, listener) {<br>  <em>const </em>handler = (event) =&gt; {}<br>  element.addEventListener(listener, handler)<br>  <strong><em>while </em>(<em>true</em>) {<br>    <em>yield new </em>Promise(resolve =&gt; resolve(event))<br>  }</strong><br>}</pre><p>Now we’re hoeing where there’s taters! It looks like the handler is getting an event and the Promise is yielding an event, so now I just have to somehow move the event from the handler to the Promise. The dumbest thing I can think of is just sharing a variable, so let’s do that:</p><pre><em>function</em>* streamify(element, event) {<br><strong>  <em>let </em>nextResolve<br></strong>  <em>const </em>handler = (event) =&gt; {<br><strong>    nextResolve(event)<br></strong>  }<br>  element.addEventListener(event, handler)<br>  <em>while </em>(<em>true</em>) {<br>    <em>yield new </em>Promise(resolve =&gt; {<br><strong>      nextResolve = resolve<br></strong>    })<br>  }<br>}</pre><p>And there we have it! We have a working streamifier! When a click event comes in, it resolves with the promise we gave it. Pretty sweet! …until someone clicks <em>really</em> fast.</p><h3>Robustifying the Streamifier</h3><p>The naive solution only works for slow events. If 2 events get fired in quick succession, the 2nd call will get swallowed. We don’t want that, especially if we’re using this for something like websockets. So, what the heck, if 1 shared resolver is good, an array of them must be better! Let’s just queue the events as they come in:</p><pre><em>function</em>* streamify(element, event) {<br><strong>  <em>const </em>pushQueue = []<br></strong>  <em>const </em>handler = (event) =&gt; {<br><strong>    pushQueue.push(event)<br></strong>  }<br>  element.addEventListener(event, handler)<br>  <em>while </em>(<em>true</em>) {<br>    <em>yield new </em>Promise(resolve =&gt; {<br><strong>      <em>const </em>nextEvent = pushQueue.shift()<br></strong>      resolve(nextEvent) // error! no nextEvent<br>    })<br>  }<br>}</pre><p>Succe…er, no. This solves the push problem, but now we’re getting an error because the iterator is requesting a click event before one exists. Dang. Well, a queue worked for pushing events, why not use one for pulling in resolvers?</p><pre><em>function</em>* streamify(element, event) {<br>  <em>const </em>pushQueue = []<br><strong>  <em>const </em>pullQueue = []<br></strong>  <em>const </em>handler = (event) =&gt; {<br>    <em>const </em>nextResolve = pullQueue.shift()<br>    <em>if </em>(nextResolve) {<br>      nextResolve(event)<br>    } <em>else </em>{<br>      pushQueue.push(event)<br>    }<br><br>  }<br>  element.addEventListener(event, handler)</pre><pre>  <strong><em>const </em>pullValue = () =&gt; <em>new </em>Promise(resolve =&gt; {<br>    <em>const </em>nextEvent = pushQueue.shift()<br>    <em>if </em>(nextEvent) {<br>      resolve(nextEvent)<br>    } <em>else </em>{<br>      pullQueue.push(resolve)<br>    }<br>  })</strong><br>  <em>while </em>(<em>true</em>) {<br><strong>    <em>yield </em>pullValue()<br></strong>  }<br>}</pre><p>Wooo! it works! Now I can click as fast as I want forever! …but what if I only want to listen to the first couple? Natively, I would call removeEventListener, but the handler function is hidden away in our sweet new wrapper. How can I remove it when the stream ends? Well, I’ll start simple &amp; just write how I want it to look:</p><pre><em>// from this<br>let </em>clickCount = 0<br><em>if </em>(clickCount++ &gt; 2) {<br><strong>  document.removeEventListener(&#39;click&#39;, handler)<br></strong>  console.log(&#39;Bye!&#39;)  <br>}<br><br><br><em>// to this<br>let </em>clickCount = 0<br><em>for await </em>(<em>const </em>event <em>of </em>clicks) {<br>  console.log(&#39;click&#39;, event)<br>  <em>if </em>(clickCount++ &gt; 2)<strong> clicks.return() </strong>// this breaks the loop<br>}<br>console.log(&#39;Bye!&#39;)</pre><p>I know the generator value has that magic return() method, but I wish i could write it myself so I could also call removeEventListener. I know that little * isn’t actually magic; it just tells the function to wrap the return value in a special object with 4 methods. So, let’s ditch the star &amp; write the generator how the engine actually reads it (plus add our little extra handler):</p><pre><strong><em>function</em></strong><em> </em>streamify(element, event) {<br>  ...<br>  <em>return </em>{<br>    [Symbol.asyncIterator] () {<br>      <em>return this<br>    </em>},<br>    next: () =&gt; ({<br>      done, // TODO how do we calculate this?<br>      value: <strong>pullValue()</strong><br>    }),<br>    <em>return</em>: () =&gt; {<br><strong>      element.removeEventListener(listener, handler)</strong><br>      <em>return </em>{done: <em>true</em>}<br>    },<br>    <em>throw</em>: (error) =&gt; ({done, value: Promise.reject(error)})<br>  }<br>}</pre><p>That may look daunting, but it’s really just a bunch of boilerplate that the * gives us for free. In the bad old days before generators, we used to have to write similar hacky things all the time. Today, that boilerplate should look pretty familiar because it’s the same stuff you see when you log Set or Map to the console.</p><p>Let’s see what we got: TheSymbol.asyncIterator() method tells the rest of the world to treat this like a generator instead of an object that just happens to have the exact same fields. Everything else returns an object with a done field and maybe a value. If done is false, we know we can expect <em>some</em> kind of value — and since this is an <em>async </em>iterator, I’m guessing that value is gonna be the same pullValue() promise we were yielding before. All that’s left to do is figure out the value of done when next() gets called. Since we know done should be true if throw or return gets called, let’s do like we did before &amp; and share the variable in the outer scope:</p><pre><em>function </em>streamify(element, event) {<br>  ...<br><strong>  <em>let </em>done = <em>false<br></em></strong><em>  return </em>{<br>    [Symbol.asyncIterator] () {<br>      <em>return this<br>    </em>},<br>    next: () =&gt; ({<strong>done</strong>, value: pullValue()}),<br>    <em>return</em>: () =&gt; {<br><strong>      done = <em>true<br></em></strong><em>      </em>element.removeEventListener(listener, handler)<br>      <em>return </em>{done}<br>    },<br>    <em>throw</em>: (error) =&gt; {<br><strong>      done = <em>true<br></em></strong><em>      return </em>{done, value: Promise.reject(error)}<br>    }<br>  }<br>}</pre><p>… and we’re done! I can now write a for-loop that iterates every time an event comes in. If I don’t like the value, I can call throw. When I’ve had enough, I can call return.</p><p>Here’s how it looks all put together:</p><pre><em>const </em>streamify = <em>function </em>(element, event) {<br>  <em>const </em>pullQueue = []<br>  <em>const </em>pushQueue = []<br>  <em>let </em>done = <em>false<br>  const </em>pushValue = <em>async </em>(args) =&gt; {<br>    <em>if </em>(pullQueue.length !== 0) {<br>      <em>const </em>resolver = pullQueue.shift()<br>      resolver(...args)<br>    } <em>else </em>{<br>      pushQueue.push(args)<br>    }<br>  }<br><br>  <em>const </em>pullValue = () =&gt; {<br>    <em>return new </em>Promise((resolve) =&gt; {<br>      <em>if </em>(pushQueue.length !== 0) {<br>        <em>const </em>args = pushQueue.shift()<br>        resolve(...args)<br>      } <em>else </em>{<br>        pullQueue.push(resolve)<br>      }<br>    })<br>  }<br><br>  <em>const </em>handler = (...args) =&gt; {<br>    pushValue(args)<br>  }<br><br>  element.addEventListener(event, handler)<br>  <em>return </em>{<br>    [Symbol.asyncIterator]() {<br>      <em>return this<br>    </em>},<br>    next: () =&gt; ({<br>      done,<br>      value: done ? <em>undefined </em>: pullValue()<br>    }),<br>    <em>return</em>: () =&gt; {<br>      done = <em>true<br>      </em>element.removeEventListener(event, handler)<br>      <em>return </em>{done}<br>    },<br>    <em>throw</em>: (error) =&gt; {<br>      done = <em>true<br>      return </em>{<br>        done,<br>        value: Promise.reject(error)<br>      }<br>    }<br>  }<br>}</pre><h3><strong>Conclusion</strong></h3><p>If you’ve scrolled all the way to the bottom to find the link to the GitHub repo, <a href="https://github.com/mattkrick/asynciterify">here it is</a>.</p><p>In 5 minutes, we’ve written a 50 LOC wrapper that goes toe-to-toe with all the competing dependency-infested packages out there. After wrapping our events, we can finally proclaim that we no longer write code with callbacks. The dream of 2012 is here! Best of all, instead of learning what an async iterable <em>is</em>, we learned <em>how to use it. </em>We didn’t have to break out the functional programming textbooks to study the definition of a Subject, Deferrable, or Disposable. Instead, we built something practical — like taking a cooking class and walking away with dinner. <em>Way</em> more fun than CS theory.</p><p>The only question that remains: just because we can, does that mean we should? From a clean code perspective, maybe! But what about performance? Promises are inherently slower than callbacks, and on top of that, we’re calling shift() a bunch on 2 queues. Running the code in Chrome 67, it’s 2x-100x+ slower than native callbacks for 100–1,000,000 events. When the code gets transpiled to ES5, that grows to 20x-1000x slower! So from a benchmarking standpoint, it’s plain awful. But in the real world, that equates to literally an extra 0.1ms to handle 10 concurrent events. Pretty fair trade for ditching the callbacks!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=665259680044" width="1" height="1" alt=""><hr><p><a href="https://itnext.io/understand-async-iterators-665259680044">Understand Async Iterators Without Really Trying</a> was originally published in <a href="https://itnext.io">ITNEXT</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[GraphQL: 3 Years in, and lessons learned]]></title>
            <link>https://medium.com/hackernoon/graphql-3-years-in-and-lessons-learned-34e8cd3fcfdd?source=rss-ca93f36ae1ea------2</link>
            <guid isPermaLink="false">https://medium.com/p/34e8cd3fcfdd</guid>
            <category><![CDATA[react]]></category>
            <category><![CDATA[graphql]]></category>
            <dc:creator><![CDATA[Matt Krick]]></dc:creator>
            <pubDate>Thu, 03 May 2018 22:18:06 GMT</pubDate>
            <atom:updated>2019-04-22T11:09:04.167Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*3JCDGY9BHciaOPTBvo9Q0g.jpeg" /></figure><p>Back in late 2016 I wrote an article called <a href="https://hackernoon.com/graphql-tips-after-a-year-in-production-419341db52e3">GraphQL: Tips after a year in production</a>. Since then, <a href="https://hackernoon.com/tagged/graphql">GraphQL</a> started offering native subscriptions, Relay got so good you could replace <a href="https://medium.com/@matt.krick/replacing-redux-with-relay-47ed085bfafe">Redux with Relay Modern</a>, and I learned a few neat tricks along the way. I’ve also made a bunch of mistakes. Looking back on my GraphQL journey, here’s what I’d change.</p><h3>1. Use a DataLoader from the get go</h3><p><a href="https://github.com/facebook/dataloader">DataLoader</a> is a small cache that is beautiful in its simplicity. Instead of caching the entirety of the GraphQL response, it caches <a href="https://hackernoon.com/tagged/database">database</a> queries to be used in resolve functions. I put off implementing it in my app for fear that it was a premature optimization. Boy was I wrong. Looking back, I should have done it a <em>lot</em> sooner. Aside from the generous performance boost, it simplified my resolve functions by standardizing how I fetch things from my database. Less code = less room for me to write bugs. The only drawback is that the cache wasn’t designed to work for subscriptions. To fix that, I wrote my own little (100 LOCs) add-on package called <a href="https://github.com/mattkrick/dataloader-warehouse">dataloader-warehouse</a>. Instead of caching data for each subscriber, it gives you the option to cache data for each publish, essentially turning an O(n) operation into O(1), which is nice.</p><h3>2. Mutation Fragments in your Subscription Payload</h3><p>If you have a real-time app (and who doesn’t? It’s 2018!) You’ve probably written a few GraphQL subscriptions to keep all the data on your page fresh without a pesky refetch. The biggest mistake I made in GraphQL is how I organized my subscriptions. I started out by building 1 subscription for each page view in my app, but that meant my back-end had to change whenever the front-end changed. Next, I tried breaking subscriptions into CRUD types for each entity, e.g. CreateTaskSubscription, UpdateTaskSubscription, DeleteTaskSubscription. That was awful for 2 reasons: I had 3x more code to maintain, and I still had to write hacks because sometimes I needed to know <em>how</em> it was updated. For example, was a single task deleted, or was a user deleted, which triggered 10 calls to DeleteTaskSubscription?</p><p>Finally, I arrived at something I call the Hybrid Strategy. It works by first breaking the mutation payload into a fragment.</p><pre>fragment UpdateTaskMutation_task on UpdateTaskPayload {<br>  task {<br>    dueDate<br>  }<br>}</pre><p>Then, using the power of GraphQL, I include that fragment in both my mutation and my subscription:</p><pre>mutation UpdateTaskMutation($task: Task!) {<br>  updateTask(task: $task) {<br>    error {<br>      message<br>    }<br>  ...UpdateTaskMutation_task<br>  }<br>}<br><br>subscription TaskSubscription {<br>  taskSubscription {<br>    __typename<br>    ...CreateTaskMutation_task<br>    ...DeleteTaskMutation_task<br>    ...UpdateTaskMutation_task<br>  }<br>}</pre><p>Because the subscription shares the mutation fragment and handler, <strong>I’m guaranteed that if the mutation works, the subscription works</strong>. To learn more, see <a href="https://hackernoon.com/the-hybrid-strategy-for-graphql-subscriptions-dd5471c45755">The Hybrid Strategy for GraphQL Subscriptions</a>.</p><h3>3. Errors in the payload</h3><p>In the code sample above, you probably noticed that I included an error object in the response for updateTask. It goes back to the timeless question, “If I succeed at failing, was I successful?”</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/292/1*BefeB5HtmnzOQQqwnnJ38A.jpeg" /></figure><p>Errors are the same way. I used to throw them, but that made it difficult to figure out if the error was something I threw or if it was something unexpected. If I threw it, I wanted to use it in a client-side error message, but if it was unexpected, I wanted a generic “Server Error” message to hide the gory details. By writing every mutation with a succeed-by-failing mentality, I can replace any thrown error with that generic message. I can also extend the returned error object to make it as helpful as possible, because nothing makes me hate an app more than hitting an error and not knowing how to fix it. To track what errors folks are seeing, you can even <a href="https://github.com/ParabolInc/action/blob/3fcf5ef90417a4cb2330884a3e9e1db587677853/src/server/utils/sendAuthRaven.js">send an alert to your exception tracker</a> whenever you return an error. I wrote a whole bunch on the topic in <a href="https://itnext.io/the-definitive-guide-to-handling-graphql-errors-e0c58b52b5e1">The Definitive Guide to Handling GraphQL Errors</a>.</p><h3>4. Simplified Folder Hierarchy</h3><p>In my original post, I advocated for breaking your queries into folders by entity type. Since then, my app has grown from medium-sized to large, and the hierarchy didn’t scale with it. Some mutation files were growing to well over 1000 LOCs, which were just a pain to look at. Now, I advocate for a flatter hierarchy of 4 folders: <a href="https://github.com/ParabolInc/action/tree/3fcf5ef90417a4cb2330884a3e9e1db587677853/src/server/graphql">1 for each of your queries, mutations, subscriptions, and types</a>. Each file contains a single query (or type) and life is a lot simpler. Sure, there are a a lot more files, but just get yourself an IDE that auto-imports as you type and you’ll never need to rummage through the folder. The only exception is for Connection and Edge types — I create those with a helper and export them from the same file as the base type.</p><h3>5. You probably want an Interface</h3><p>The boilerplate advice is to use an interface for things that are related, and a union for things that aren’t, but have common fields (whatever that means). In practice, I tried using unions plenty of times, but always refactored them to interfaces. In fact, the only unions in my entire app are my subscription payloads (since they’re the amalgam of many mutations). Since interfaces can share fields, your queries will be cleaner since you can extract shared fields before you fragment on the specific types. Additionally, as your data structures get more complicated, you can sub-class them, which becomes very useful.</p><p>For example, let’s say I have a Vehicle, which is either a Car or a Truck. Every Vehicle has an Engine, but a Car has a CarEngine and a Truck has a TruckEngine:</p><pre><em>const </em>vehicleFields = () =&gt; ({<br>  engine: {<br>    type: Engine<br>  }<br>}<br><br><em>const </em>Vehicle = <em>new </em>GraphQLInterfaceType({<br>  fields: vehicleFields<br>})<br><br><em>const </em>Car = <em>new </em>GraphQLObjectType({<br>  fields: () =&gt; ({<br>    ...vehicleFields(),<br>    engine: {<br>      type: CarEngine<br>    }<br>  })<br>})<br><br><em>const </em>Truck = <em>new </em>GraphQLObjectType({<br>  fields: () =&gt; ({<br>    ...vehicleFields(),<br>    engine: {<br>      type: TruckEngine<br>    }<br>  })<br>})</pre><p><em>Sidenote: By thunkifying my shared fields, it makes schema changes pretty painless.</em></p><p>Now, I can write my queries in a very concise manner, without the need for extra fragments. For example, if a truck engine is just a car engine with an auxiliary power unit, I can get everything I need with a single fragment, instead of having to fragment on both Engine and Truck.</p><pre>vehicle {<br>  engine {<br>    horsepower<br>  }<br>  ... on Truck {<br>    bedSize<br>    engine {<br>      APU<br>    }<br>  }<br>}</pre><p>While it doesn’t look like much here, this<em> </em>makes component fragments in<em> </em>your app much cleaner. It also means Relay-generated flow types are as accurate as possible, which saves me from myself. You may be asking yourself, if 2 types are <em>almost</em> the same, why not just use the superset and leave a few fields blank? That was my strategy to avoid interfaces, and it served me for awhile, until it didn’t. Given enough time, your types <em>will</em> evolve to the point to where you’ll need to interface them. A good rule of thumb is if you know the best path forward, spend the extra time to do it right, if you don’t, pick the fastest path. For me, that means building interfaces from the start.</p><h3>6. Use your schema to generate typings</h3><p>If you use typescript or flow, chances are you’ve found yourself building typings that look a lot like pieces of your schema. For the Relay folks, you already get <a href="https://facebook.github.io/relay/docs/en/new-in-relay-modern.html#flow-type-generation">bespoke flow types</a> for every fragment you create, but those don’t include things like enums and query input variables. For things like these, I use <a href="https://github.com/avantcredit/gql2ts">gql2ts</a> (the successor to <a href="https://github.com/joarwilk/gql2flow">gql2flow</a>) to generate types for general use. You can even use these types on your Node server, which can be pretty helpful when writing more complex resolve functions. This single source of truth is a huge benefit because now when you extend an interface, you don’t have to remember to extend your flow type, too.</p><h3>Looking forward</h3><p>With these tips, I hope you manage to avoid some of the time-consuming pitfalls that got me. GraphQL continues to be a great pleasure to use, and that’s largely because of the growing, active community around it. There are still plenty of best practices I haven’t touched on here, including schema stitching, internal schemas, using GraphQL to transport OT/CRDT changes, persisted queries, etc. If you’ve found some neat patterns yourself, or think some of mine are baloney, be sure to let me know!</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fupscri.be%2Fdde502%3Fas_embed%3Dtrue&amp;dntp=1&amp;url=https%3A%2F%2Fupscri.be%2Fhackernoon%2F&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=upscri" width="800" height="400" frameborder="0" scrolling="no"><a href="https://medium.com/media/3c851dac986ab6dbb2d1aaa91205a8eb/href">https://medium.com/media/3c851dac986ab6dbb2d1aaa91205a8eb/href</a></iframe><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=34e8cd3fcfdd" width="1" height="1" alt=""><hr><p><a href="https://medium.com/hackernoon/graphql-3-years-in-and-lessons-learned-34e8cd3fcfdd">GraphQL: 3 Years in, and lessons learned</a> was originally published in <a href="https://medium.com/hackernoon">HackerNoon.com</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The Definitive Guide to Handling GraphQL Errors]]></title>
            <link>https://itnext.io/the-definitive-guide-to-handling-graphql-errors-e0c58b52b5e1?source=rss-ca93f36ae1ea------2</link>
            <guid isPermaLink="false">https://medium.com/p/e0c58b52b5e1</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[graphql]]></category>
            <category><![CDATA[error-handling]]></category>
            <category><![CDATA[react]]></category>
            <dc:creator><![CDATA[Matt Krick]]></dc:creator>
            <pubDate>Mon, 12 Mar 2018 16:29:01 GMT</pubDate>
            <atom:updated>2018-03-15T13:34:55.925Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/925/1*zRT0atOgVLyaQa3xYlO54A@2x.jpeg" /><figcaption>Get it? Cuz they’re errors... and you throw &amp; catch ‘em …nevermind</figcaption></figure><p><a href="https://www.linkedin.com/cws/share?url=https%3A%2F%2Fitnext.io%2Fthe-definitive-guide-to-handling-graphql-errors-e0c58b52b5e1"><em>Click here to share this article on LinkedIn »</em></a></p><p>Recently, I screwed up and it resulted in a client getting a white screen when they used our app. Like most apps, we have an initial GraphQL query that fetches a ton, including a list of all your notifications. One of those notifications referenced a field that no longer existed in the database (oops!). The result? GraphQL was a champ and sent both data and errors to the client. But the client, well it completely ignored the data because it handled the response as an error. In hindsight, that was pretty dumb. It’d be like flunking a student for getting less than 100%. It just ain’t right.</p><p>GraphQL’s ability to send both data and errors is nothing short of amazing. It’s like having a talk with a real human: “Hey Matt, here are those results you wanted. I got you everything except that task field; I went to look it up, but it didn’t exist in your database.” With all this power, we could do some really cool things on the client! Unfortunately, most client code boils down to this:</p><pre>if (result.errors) throw result.errors[0]</pre><p>That’s not perfect, but if we didn’t throw an error, then the onError handler wouldn’t be called, which is how I propagated server validation errors to the UI. So, choosing between writing a flawless server and not receiving server errors, I went with the former — and it worked for almost 2 years! …until it didn’t.</p><h3>Identifying Error Types</h3><p>To make sure I fixed the root cause, I started researching all the types of errors we throw in our app and all the ways other folks handle GraphQL errors. There are a plethora of errors that a client can encounter when querying a GraphQL Server. Whether it’s a query, mutation, or subscription, they all fall into 6 types:</p><ol><li>Server problems (5xx HTTP codes, 1xxx WebSocket codes)</li><li>Client problems e.g. rate-limited, unauthorized, etc. (4xx HTTP codes)</li><li>The query is missing/malformed</li><li>The query fails GraphQL internal validation (syntax, schema logic, etc.)</li><li>The user-supplied variables or context is bad and the resolve/subscribe function intentionally throws an error (e.g. not allowed to view requested user)</li><li>An uncaught developer error occurred inside the resolve/subscribe function (e.g. poorly written database query)</li></ol><p>So, which of these errors are critical enough to ignore all the data? Numbers 1–3 for sure, since they occur before GraphQL even get called. Number 4, too, it calls GraphQL, but only receives errors in response. For 5–6, GraphQL responds with both partial data and an array of errors. Some would conflate type 5 with type 2, for example running out of query “points” (<a href="https://developer.github.com/v4/guides/resource-limitations/">like what GitHub does</a>) could constitute an HTTP 429 (too many requests). But at the end of the day, the simplest answer is the best: <strong>If GraphQL gives you a result with </strong><strong>data, even if that result contains </strong><strong>errors, it is not an error. </strong>No changing HTTP codes based on error types, no reading the errors to decide how “critical” a particular error is, and no reading the data to see if it’s usable. I don’t care if the result is {data: {foo: null}}. Data is data; any arbitrary nully logic implemented after GraphQL returns is just that: arbitrary.</p><p>Following this logic, error types 1–4 would be sent as errors to the client because there is no result.data. But what about types 5–6?</p><h3>Don’t Intentionally Throw Errors in GraphQL</h3><p>As of March 2018, neither <a href="https://github.com/apollographql/apollo-client/issues/3034">Apollo</a>-<a href="https://github.com/apollographql/apollo-client/issues/3000">Client</a> (<a href="https://github.com/apollographql/apollo-client/issues/2810">including</a><a href="https://github.com/apollographql/subscriptions-transport-ws/issues/305"> subscriptions-transport-ws</a>) nor <a href="https://github.com/facebook/relay/issues/1913">Relay</a> <a href="https://github.com/facebook/relay/issues/1816#issuecomment-304492071">Modern</a> is perfect at handling errors. Relay’s mutation API comes close with its onCompleted(result, errors) callback, but this is sorely missed for queries and subscriptions. Apollo is extra flexible with its ErrorPolicy; but neither offers best practices, so I propose my own: <strong>If the viewer should see the error, include the error as a field in the response payload.</strong> For example, if someone uses an expired invitation token and you want to tell them the token expired, your server shouldn’t throw an error during resolution. It should return its normal payload that includes the error field. It can be as simple as a string or as complicated as you desire:</p><pre><em>return </em>{<br>  error: {<br>    id: &#39;123&#39;,<br>    type: &#39;expiredToken&#39;,<br>    subType: &#39;expiredInvitationToken&#39;,<br>    message: &#39;The invitation has expired, please request a new one&#39;,<br>    title: &#39;Expired invitation&#39;,<br>    helpText: &#39;https://yoursite.co/expired-invitation-token&#39;,<br>    language: &#39;en-US&#39;<br>  }<br>}</pre><p>By including errors in your schema, life gets a lot easier:</p><ul><li>All errors are sanitized and ready for the viewer before they hit the client</li><li>You don’t need to throw a stringified object and parse it on the client</li><li>You don’t have to send the same error in 22 different languages (you know who you are)</li><li>You can send the same error as a breadcrumb to your error logging service</li><li>Most importantly, <em>your GraphQL </em><em>errors array won’t include any user-facing errors </em>which means your UI won’t ignore them!</li></ul><p>For mutations (and subscriptions), that’s an easy sell. Even easier if you follow <a href="https://hackernoon.com/the-hybrid-strategy-for-graphql-subscriptions-dd5471c45755">my hybrid approach to subscriptions</a> because your subscriptions reuse your mutation payloads. But what about queries? There exists a dichotomy in GraphQL best practices today: mutations and subscriptions return a payload full of types, but a query just returns a type. Using my blunder as an example, imagine a request where team succeeds but notifications fails:</p><pre>mainQuery {<br>  team {  #succeeds<br>    name<br>  }<br>  notifications { #fails<br>    text<br>  }<br>}</pre><p>To avoid losing partial data, we treat the whole thing as a success, but in doing so, we lose the errors! How can we get both? We can’t go back to throwing errors for the reasons listed above, but wrapping every object is a payload would be pretty ugly:</p><pre>mainQuery {<br>  teamPayload {<br>    error {<br>      message<br>    }<br>    team {<br>      name<br>    }<br>  }<br>  notificationPayload {<br>    error {<br>      message<br>    }<br>    notifications {<br>      text<br>    }<br>  }<br>}</pre><p>While it’s not ideal, this would only apply when the UI needs to know about an error. Sound familiar? It functions just like an <a href="https://reactjs.org/blog/2017/07/26/error-handling-in-react-16.html">error boundary in React</a>:</p><blockquote>The granularity of error boundaries is up to you. You may wrap top-level route components to display a “Something went wrong” message to the user, just like server-side frameworks often handle crashes. You may also wrap individual widgets in an error boundary to protect them from crashing the rest of the application.</blockquote><p>So if returning a null or empty array suffices, go right on ahead; but send the event to your exception manager to track it. If you notice a particular query piece is failing regularly, then you can wrap it using a payload to create a pseudo error boundary. While more art than science, this means I treat all GraphQL operations the same, and I don’t needlessly bloat my entire schema.</p><p>Now when it comes to trusting the client, if the client shouldn’t see it, your server shouldn’t send it, which brings us to the final handler.</p><h3>How to Hide Your Shortcomings (from the client)</h3><p>Remember the good old days when <em>all</em> errors were unintentional? Nowadays playing catch with errors is more common than, well, actually playing catch (looking at you React v17 with your crazy promise throwing internals).</p><p>After refactoring our intentionally thrown errors into a regular field in our response payload, any remaining errors must be unintentional (i.e. developer errors), which means we should cover our tracks and replace the message with something vague like: “Server Error”. In a perfect world, these would be caught, sanitized, and returned as an error property in the response, but you’ll never catch ’em all (so you can stop wrapping every single statement in a try/catch). We still send the real error to our logging service so we can fix it before anyone knows its broken, but the client should never see it because the error might include sensitive things like our <a href="https://github.com/ParabolInc/action/tree/master/src/server/graphql/queries">actual database queries that we use in production</a>. Along with the vague message, it is worthwhile to keep the error’spath, since that will help us determine where the error occurred. Again, simple is best: <strong>For every error in </strong><strong>errors, send a generic message and path to the client alongside the partial data.</strong></p><p>Once that result is on the client, it will be handled as a successful request. You could even ignore the errors and be fine (and if it’s a query, you might have to!). However, if you wanted to make use of it, you could still reference it anywhere the errors array is available. Putting it all together, here’s how it looks in Relay Modern:</p><pre><em>// Called for error types 1-4 (5xx, 4xx, missing/invalid query)<br>const </em>onError = (err) =&gt; {<br>  <em>this</em>.setState({err})<br>}<br><br><em>const </em>onCompleted = (result, errs) =&gt; {<br>  <em>// Called for error type 6 (eg unexpected missing DB field)<br>  const </em>err = errs.find(({path}) =&gt; path.includes(&#39;approve&#39;));<br>  <em>if </em>(err) {<br>    onError(err.message);<br>  }<br>  <br>  <em>// called for error type 5 (eg expired auth token)<br>  const </em>{approve: {error: {message}}} = result;<br>  onError(message);<br>}<br><br>commitMutation(env, {mutation, onCompleted, onError})</pre><p>Remember, this works perfectly for mutations, but queries and subscriptions swallow errors unless they’re thrown, which means if you want it in your UI, you better put it in your schema!</p><h3>Conclusion</h3><p>tl;dr</p><ul><li>If GraphQL gives you results.data, it is not an error, so don’t throw it on the client.</li><li>If the viewer should see the error, return the error as a field in the response payload. If it’s a query, make a response payload.</li><li>Replace any remaining GraphQL errors with a generic message, but don’t throw it on the client and don’t expect the UI to always be able to handle it.</li></ul><p>Whether it’s for a query, mutation, or subscription, we identified 6 distinct types of errors that a request can encounter when returning<em> </em>a GraphQL response. We came up with<em> </em>a strategy to guarantee that partial data is never ignored by the client. Finally, we ensured that the viewer always sees the errors we want them to see (and nothing more!). We also managed to avoid the deep, dark rabbit hole of throwing custom errors like GraphQLConnectionError that seem so popular despite their shortcomings. How do you handle errors? Is this already common knowledge and I’m just late to the party? Let me know.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e0c58b52b5e1" width="1" height="1" alt=""><hr><p><a href="https://itnext.io/the-definitive-guide-to-handling-graphql-errors-e0c58b52b5e1">The Definitive Guide to Handling GraphQL Errors</a> was originally published in <a href="https://itnext.io">ITNEXT</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Replacing Redux with Relay]]></title>
            <link>https://mattkrick.medium.com/replacing-redux-with-relay-47ed085bfafe?source=rss-ca93f36ae1ea------2</link>
            <guid isPermaLink="false">https://medium.com/p/47ed085bfafe</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[graphql]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[redux]]></category>
            <dc:creator><![CDATA[Matt Krick]]></dc:creator>
            <pubDate>Tue, 27 Feb 2018 15:01:01 GMT</pubDate>
            <atom:updated>2018-02-27T15:03:57.294Z</atom:updated>
            <content:encoded><![CDATA[<p>It’s been almost 2 years since I wrote <a href="https://medium.com/@matt.krick/replacing-relay-with-redux-2990c81aa807">Replacing Relay with Redux</a>. Since then, Relay added subscriptions, a build-time compiler, a sensible mutations API, and a game-changing client schema. That puts me in an awkward position. On the one hand, we JavaScript developers get a bad wrap for declaring technology as antiquated the moment something new comes along; but on the other hand, COOL NEW TECH! So with that said, Redux is out and Relay is in. I’m serious. Stop laughing.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*pXv4CbfozQON-Bwsd66tFQ.png" /><figcaption>Credit to <a href="https://speakerdeck.com/keithpitt/react-plus-relay-plus-graphql-is-the-future">Keith Pitt</a></figcaption></figure><h3>The Business Case</h3><p>Too much boilerplate, team members never documenting their action creator APIs, the ebbing battle of connecting to smart containers vs. dumb components, code-splitting reducers, memoizing selectors, merging local and domain state, async actions, accidental mutability. If you’ve ever written a moderately complex Redux app, you know the struggle is real. If you’re just starting out and wonder why it’s so complicated, you’ve probably just been told to hush or given some sage hippie advice like</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ktpE_RFq28yqHuJ48xLQVA.jpeg" /></figure><p>Thankfully, the community has rallied together to invent some pretty neat workarounds. Need async functionality? Plop a generator in your middleware and call it a <a href="https://github.com/redux-saga/redux-saga">saga</a>. Need to memoize? Use <a href="https://github.com/reactjs/reselect">reselect</a>. Need to eliminate boilerplate? Pick your favorite action creator package that turns 20 simple lines into 10 confusing ones. Heck, I even jumped on the bandwagon and wrote <a href="https://medium.com/@matt.krick/introducing-redux-operations-332ab56e468b">a store enhancer so you had a GraphQL-esque documented API in your devtools</a>. At the end of the day, Redux worked and the code shipped; but I’d be lying if I said I wasn’t tempted to turn React’s new Context API into my <a href="https://github.com/didierfranc/react-stateful">own simple state store</a>. Thankfully, as of v1.5.0, Relay is shipping with a client schema, and my code is looking a lot cleaner.</p><h3>Using the Client Schema</h3><p>As of today, the client schema is “undocumented”, which is a facebook alias for “freakin sweet”. Getting it running is simple:</p><p><strong>Write the schema.</strong> While you can’t create new types exclusively for the client (yet?) you can use types you created in your server schema. For this example, imagine contentFilter is an input that filters out tasks that don’t include the supplied contentText:</p><pre>extend type Team {<br>  contentFilter: String<br>}<br><br>extend type Task {<br>  contentText: String<br>}</pre><p>This is where the real magic is. If I were using Redux, I’d create a TeamReducer and TaskReducer. Then, since I enjoy splitting code &amp; splitting headaches, I’d asynchronously add those reducers to the store when the dependent components mounted. With Relay, I request these fields <a href="https://github.com/ParabolInc/action/blob/becec361923272c95e8ccaadaac460357307f4ff/src/universal/modules/teamDashboard/components/AgendaList/AgendaList.js#L303">just like any other field</a> in my fragment. No extra connect(), no runtime errors because the fragment is compiled at build time, no “dumb component” debate, and the code spliting comes free with the compiled query.</p><p><strong>Compile the schema</strong>. Adding the client schema is as easy as adding an arg:</p><pre>relay-compiler --schema serverSchema.graphql --client-schema clientSchema.graphql</pre><p><strong>Mutate!</strong> Do I use deep freeze or immutable.js? Maybe I just trust that my team will use Object.assign correctly for each reducer? Nah, forget it. Thankfully, Relay has it handled with that sweet commitLocalUpdate:</p><pre>reactRelay.commitLocalUpdate(environment, (store) =&gt; {<br>  store.get(teamId).setValue(e.target.value, &#39;contentFilter&#39;);<br>});</pre><p>That’s right, the same API you know &amp; love for server mutations is used for local updates. Boilerplate be damned!</p><h3>Memoizing</h3><p>If something is calculated from state, does it become state, too? MobX might call it “computed” state. Redux just says “who cares, memoize it”. But how can you handle that with Relay? In our real-world example above, I need to take a draft-js object, turn it into a string of plaintext, and match against a regex. Now, turning 50 draft-js objects into strings on every keystroke isn’t exactly cheap, so it’d be nice to memoize. I could memoize it at the component level by keeping it in state, which is essentially what reselect does, and that works perfectly well! …but what if I could memoize at the app level? <em>With this one</em> <em>weird trick</em>, I can combine my client schema with a custom handlerProvider.</p><p><strong>Write the handler</strong>. For any field containing a draft-js stringified object, I want to parse it, extract the text, and set a peer contentText field to the result:</p><pre><em>const </em>ContentTextHandler = {<br>  update(store, payload) {<br>    <em>const </em>record = store.get(payload.dataID);<br>    <em>const </em>content = record.getValue(payload.fieldKey);<br>    <em>const </em>{blocks} = JSON.parse(content);<br>    <em>const </em>fullText = blocks.map(({text}) =&gt; text).join(&#39;\n&#39;);<br>    record.setValue(fullText, &#39;contentText&#39;);<br>  }<br>};</pre><p><strong>Provide the handler</strong>. Relay has a default handler (so <em>that’s</em> how they do the magical stuff with connections!). By extending it, the world is your oyster:</p><pre><em>const </em>handlerProvider = (handle) =&gt; {<br>  <em>switch </em>(handle) {<br>    <em>case </em>&#39;connection&#39;: <em>return </em>ConnectionHandler;<br>    <em>case </em>&#39;viewer&#39;: <em>return </em>ViewerHandler;<br><strong>    <em>case </em>&#39;contentText&#39;: <em>return </em>ContentTextHandler;<br></strong>    <em>default</em>: <em>throw new </em>Error(`Unknown handle ${handle}`);<br>  }<br>};</pre><p>For more info, <a href="https://facebook.github.io/relay/docs/en/relay-environment.html#adding-a-handlerprovider">read the docs</a></p><p><strong>Trigger the handler</strong>. There’s a secret __clientField directive that Relay provides so you can do magical things. By including it in the query, you can recompute state whenever the query is run.</p><pre>fragment on Task {<br>  content @__clientField(handle: &quot;contentText&quot;)<br>  contentText <br>}</pre><p>Now, whenever a query comes in, Relay looks for that handler and generates the plaintext for that decorated field. Pretty sweet! (Note that you’ll still want to call ContentTextHandler.update in your mutations/subscriptions, this only runs on queries.)</p><h3>Conclusions</h3><p>And just like that, you can avoid reducer boilerplate hell, use GraphQL to document your local API, get code splitting for free, memoize at the application level, and be the envy of all your friends when you tell them your domain and local state share a single source of truth. Got any other neat patterns for Relay? Let me know in the comments.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=47ed085bfafe" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The Hybrid Strategy for GraphQL Subscriptions]]></title>
            <link>https://medium.com/hackernoon/the-hybrid-strategy-for-graphql-subscriptions-dd5471c45755?source=rss-ca93f36ae1ea------2</link>
            <guid isPermaLink="false">https://medium.com/p/dd5471c45755</guid>
            <category><![CDATA[subscription]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[graphql]]></category>
            <category><![CDATA[graphql-subscriptions]]></category>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[Matt Krick]]></dc:creator>
            <pubDate>Tue, 09 Jan 2018 21:01:23 GMT</pubDate>
            <atom:updated>2019-04-22T11:10:14.131Z</atom:updated>
            <content:encoded><![CDATA[<p>Subscriptions are really hard. That’s what makes them fun. It’s been a few months since <a href="https://hackernoon.com/tagged/graphql">GraphQL</a> &amp; Relay have supported them, and still examples are sparse. The worst part? The ones that do exist use patterns that will give you a headache if you try to implement them in your largescale app. Trust me.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*MdAeQ-ExTXTHsPpiJRnfRg.jpeg" /></figure><p>After a whole lot of trial and error, I finally came across a pattern that scales linearly with your app. Hopefully, it’ll keep you from suffering as you embark on real-timeifying your app.</p><h4>Some Background</h4><p>The holy grail is a page where every piece of domain state updates in real-time, the code is maintainable, and there is no overfetching. That’s as true today as it has been since the first AJAX request. After all, pseudo-real-time apps have been around for decades. You send an AJAX every 5 seconds for everything on the screen and you’re there. The problem is that when it really counts, 5 seconds is too long, and when activity is sparse, 5 seconds is too short. Subscriptions fixed this because instead of dry humping the server ad infinitum, the server tells you what’s changed.</p><p>Meteor was the first framework to really leverage this using what’s called a LiveQuery. It tailed the <a href="https://hackernoon.com/tagged/mongodb">MongoDB</a> Oplog and pushed the changes to subscribed clients. RethinkDB later perfected this by building a natively reactive database. Both strategies are good, but suffer from 2 problems:</p><p>First, the overfetching: If you care about the content of a Todo and someone changes the priority, you’re still handling the whole gosh darn document. Sure you <em>could</em> pluck individual fields before you send to the client, but then that subscription cannot be reused across the app, and from there it’s overfetching the whole way down.</p><p>Second, and most importantly, they’re limited by how the data is stored. If you care about a Team<strong> </strong>as well as the number of Todos they are have, you either need to denormalize that count onto the Team<strong> </strong>table, or you need to also subscribe to a Todo<strong> </strong>count and patch the 2 together. Back-end changes to accommodate the front-end? That’s a code smell.</p><h4>Enter GraphQL</h4><p>GraphQL changed all this with their newfangled data-transform pipelines. It can even be used for a <strong>LiveQuery</strong> like those mentioned above, although I don’t recommend it (to learn why, I highly recommend the <a href="https://youtu.be/BSw05rJaCpA?t=19m30s">awesome talk from GraphQL Summit</a>). With GraphQL, a subscription is no longer limited by how it is stored in a database because each subscription triggers a client-defined query. The only problem left to solve is how to segment subscriptions. After talking to a lot of folks, reading a lot of code, and trying a lot of stupid things, I learned there are 3 ways to segment subscriptions: <strong>per-query, per-entity, and per-mutation</strong>. Let’s look at each.</p><h4>Per-query Subscriptions</h4><p>The siren of the bunch. You just got the thumbs up to make a piece of your app reactive so you build a subscription around a single component. If any data in that component’s query changes, your subscription will let you know with a single beautiful payload. Unfortunately, your marketing team then changes the layout of the page and you quickly learn that as your components change, your server must change. Updating 10 mutations and your subscriptions because a new&lt;Footer/&gt; got added is lame, so you hunt on for a better pattern.</p><h4>Per-Entity Subscriptions</h4><p>This type of subscription is the most popular. From PubSub textbooks to GraphQL example repos, you see it everywhere. It’s pretty simple: if you have a mutation that modifies a Team with ID of 123, then you publish a message to Team.123 in perfect Topic.Channel fashion. Simple, right? Well, until you call an AddTeam mutation. If you publish to channel Team.124, no one will be listening yet, so you’ll need to post it to parent channel, such as Team.userId. Another channel just for listening to teams you get added to? Not great, but not terrible.</p><p>Next, assume that you have a RemoveFromCompany mutation that removes you from every Team and for every team, removes each Todo item. The poor client listening on theTeam and Todo channels is going to receive 1 message for each Todo, Team, and company; That’s m*n + m + 1 messages! A client handling 100 updates in quick succession may drop below 60fps, but again, not terrible. A smart batching strategy can easily mitigate this.</p><p>Third, and here’s where it gets fun, is that per-entity subscriptions inherently overfetch. Imagine a ChangeTeamName mutation. You only change a single field, but the subscription returns the entire Team object because you share it with other mutations. Sure, some of those fields may be expensive to fetch, but what’s a little overfetching if it means the code is maintainable…</p><p>Unfortunately, maintainability is a nightmare, which brings us to the real reason why per-entity subscriptions are bad news: they transfer <em>state</em>, not the <em>event</em>. For example, if I pop a toast when a Todo gets removed, will RemoveFromCompany trigger 100 toasts? If a user got added to a team, are they brand new, or did they reactivate? Who added them? Was it you from your cellphone while you’re looking at the same page on your computer? At the end of the day, I came to the harsh realization that I needed more than just state. I needed the event.</p><p>Before realizing what the problem was, I solved this by bifurcating state and event into separate Team and Event channels. I told myself the Team channel would handle updates to the Team object, and the Event channel would handle any toasts or one-off messages. As the app grew and business logic changed, I realized the Event payload often contained the entire Team object and I didn’t even need the Team channel! In fact, the Event payload was almost identical to the payload of the mutation that triggered it, yet here I was working tirelessly to squash bugs to keep the 3 separate queries and handlers returning the same result. Like an idiot.</p><h4>Per-mutation subscriptions</h4><p>A subscription is a mutation you didn’t know you wanted. With that in mind, it makes perfect sense to subscribe to a mutation. Imagine a subscription payload that looks identical to the mutation payload, sharing a single handler and query fragment. When business logic changes, you go to the single source of truth to update.</p><p>Unfortunately, where per-query subscriptions fail because they require constant changes to the back-end, per-mutation subscriptions fail because they require constant changes to the front-end. Imagine if you had a single channel for each mutation, like ChangeTeamName.123. Any component that used the team.name field would also have to subscribe to it. Looks like another dead-end for maintainability.</p><p>Secondly, we’re still overfetching. The mutation payload likely provides more data than the component needs. For example, the RemoveFromCompany payload might include teams, but your TodoList component only cares about the Todos that got removed. Do you chose to overfetch, or do you write a second handler?</p><h4>Hybrid Subscriptions</h4><p>If you already have subscriptions, you probably implement some sort of hybrid without realizing it. Either you have separate ADD/REMOVE/UPDATE subscriptions and subscribe to all 3 simultaneously on the client, or your subscription payload is a union of an added item, removed item, or updated item, or you just fetch the whole item regardless of the type (which gets tricky for deleted items!). Regardless, both per-entity and per-mutation subscriptions lack maintainability and suffer from overfetching, but in opposing ways. Back in the days of fixed-payload subscriptions, we had to pick one. Thankfully, this is where GraphQL saves the day. We can take the best parts of per-entity and per-mutation strategies and create a new type of hybrid subscription that has never been possible, <em>until now</em>…</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*d3qKRB_FjkRhaw-U7EiRjw.png" /></figure><p>… just kidding! Paywalls suck, Medium.</p><h4>How to implement Hybrid Subscriptions</h4><p>Let’s start with the server. In the ChangeTeamName mutation, we return a ChangeTeamNamePayload like team { name }. We know publishing to a channel like ChangeTeamName.123 will make life hard for the front-end developers, so instead, we publish to Team.123. Why use entity-based channels? Because it’s the perfect compromise. If we published everything to a single channel, then we’d be sending the user every message, even the ones don’t don’t affect her current view. She probably doesn’t care about an updated Todo item if she isn’t currently looking at her list of todos! Conversely, it’s cruel to make a &lt;Team/&gt; component rely on an ever-changing list of mutations that affect the team; but &lt;Team/&gt; and &lt;TodoList/&gt; components that both subscribe to a Team subscription? Yeah, that’s manageable.</p><p>Next, the only thing to add to your call to publish is the mutation name: publish(Team.123, {team, type: ChangeTeamNamePayload}). The subscription payload is simply a <a href="https://github.com/ParabolInc/action/blob/002996f0fbbb646fde7e5ca673e25a734f871d52/src/server/graphql/graphQLSubscriptionType.js">union that resolves the concrete type</a> based on this type. It’s so easy it’s like the Betty Crocker of real-time apps.</p><p>Since mutations and subscriptions return the same object type, they can share handlers. Since subscriptions do the grouping on the server, components don’t have to. All that’s left to fix is the overfetching.</p><p>To solve this, I break each mutation query up into <a href="https://github.com/ParabolInc/action/blob/002996f0fbbb646fde7e5ca673e25a734f871d52/src/universal/mutations/AddTeamMutation.js#L9-L32">standalone fragments</a>. For example,</p><pre>fragment ChangeTeamNameMutation_team on ChangeTeamNamePayload {<br>  team {<br>    name<br>  }<br>}<br>ChangeTeamNameMutation {<br>  ...ChangeTeamNameMutation_team<br>}<br>TeamSubscription {<br>  ...ChangeTeamNameMutation_team<br>  ...ChangeTeamColorMutation_team<br>}</pre><p>As seen, in the subscription I include every fragment with a _team suffix. Not too hard, but a codemod could make it even easier (*hint hint*). Writing per-channel fragments and handlers makes great sense because 1 mutation calls many subscription channels, and 1 subscription is triggered by many mutations. Since GraphQL lets you fragment on type, this isn’t a problem. Even for mutations that can return widely varying payloads (ie a ToggleTeam mutation that either adds or removes) you can still employ unions and interfaces. Even better, it means if all your business logic lives in the same handler. Need to pop a toast to the mutator, quietly update the state on the mutator’s other devices, and announce a separate message to the rest of the team? No sweat. Here’s <a href="https://github.com/ParabolInc/action/blob/002996f0fbbb646fde7e5ca673e25a734f871d52/src/universal/subscriptions/TeamSubscription.js#L12-L33">what it looks like in production</a>.</p><h4>Conclusion</h4><p>Hope this inspires you to add some real-time functionality to your app! Thanks to GraphQL, I’m able to write subscriptions that use the same queries and handlers as my mutations, which means they’re maintainable, have drastically reduced overfetching, and best yet, the pattern scales modularly so you can make your app reactive 1 mutation at a time, which should make your boss happy. Working on something similar? Reach out!</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fupscri.be%2Fdde502%3Fas_embed%3Dtrue&amp;dntp=1&amp;url=https%3A%2F%2Fupscri.be%2Fhackernoon%2F&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=upscri" width="800" height="400" frameborder="0" scrolling="no"><a href="https://medium.com/media/3c851dac986ab6dbb2d1aaa91205a8eb/href">https://medium.com/media/3c851dac986ab6dbb2d1aaa91205a8eb/href</a></iframe><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=dd5471c45755" width="1" height="1" alt=""><hr><p><a href="https://medium.com/hackernoon/the-hybrid-strategy-for-graphql-subscriptions-dd5471c45755">The Hybrid Strategy for GraphQL Subscriptions</a> was originally published in <a href="https://medium.com/hackernoon">HackerNoon.com</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Evented Subscriptions in Relay Modern]]></title>
            <link>https://mattkrick.medium.com/evented-subscriptions-in-relay-modern-9e04b14a82d8?source=rss-ca93f36ae1ea------2</link>
            <guid isPermaLink="false">https://medium.com/p/9e04b14a82d8</guid>
            <category><![CDATA[react]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[graphql]]></category>
            <dc:creator><![CDATA[Matt Krick]]></dc:creator>
            <pubDate>Tue, 11 Jul 2017 22:28:52 GMT</pubDate>
            <atom:updated>2017-07-12T22:19:39.936Z</atom:updated>
            <content:encoded><![CDATA[<p>I finally added Relay Modern to my production build and I gotta say… I dig it. When Relay Classic was first released, <a href="https://medium.com/@matt.krick/replacing-relay-with-redux-2990c81aa807">I poked a lot of fun at it</a> and even made my own client cache (with redux &amp; subscriptions). The new version beautifully shuts me up. It’s 5x smaller, has a vastly improved mutations API, reduces runtime complexity (thanks to babel + no diffing), is decoupled from React, and best of all: it has subscriptions.</p><p>Unfortunately, being a new library, there are a lot of questions left for the community to solve:</p><ul><li>How do I pass the environment down my render tree?</li><li>How do I switch between environments?</li><li>When do I unsubscribe?</li><li>Where do I trigger a subscription?</li><li>What caching strategy should I use?</li></ul><p>…And that’s just the front end! What about the server?</p><ul><li>How do I filter out the message for the person who made the mutation?</li><li>Where do I authenticate the subscription requests?</li><li>What if I need to kick someone off a subscription?</li></ul><p>Well, here it goes.</p><h3>The Front End</h3><h4>Enviroment</h4><p>When you read the Relay <a href="https://github.com/relayjs/relay-examples/tree/master/todo-modern">example</a>, you see an environment variable that gets passed into a QueryRenderer, and it’s all good. But how does it go through nested routes? Passed via props? Good Lord no; it’s a prop, not a peace pipe. We could just create a singleton, but that’s only 1 step better than attaching it to window. The answer, elegantly solved by Redux’s <a href="https://github.com/reactjs/react-redux/blob/master/src/components/Provider.js">Provider</a>, is context. Just make yourself a <a href="https://github.com/ParabolInc/action/blob/aa2080d389c4d44318d05c64466526fb6c9afc16/src/universal/components/AtmosphereProvider/AtmosphereProvider.js">Provider</a> &amp; any child that wants it can grab it. But context isn’t great for stateless components, so you’ll probably want to make a <a href="https://github.com/ParabolInc/action/blob/aa2080d389c4d44318d05c64466526fb6c9afc16/src/universal/decorators/withAtmosphere/withAtmosphere.js">withAtmosphere HOC</a> that puts it in the props for you. Why do I call it Atmosphere?</p><h4>Creating the Atmosphere</h4><p>My app uses http to fetch results until the user hits a component that needs a websocket, <a href="https://github.com/ParabolInc/action/blob/aa2080d389c4d44318d05c64466526fb6c9afc16/src/universal/decorators/socketWithPresence/socketWithPresence.js#L56">and then it switches</a>. When I no longer need the websocket, it <a href="https://github.com/ParabolInc/action/blob/aa2080d389c4d44318d05c64466526fb6c9afc16/src/universal/decorators/socketWithPresence/socketWithPresence.js#L61">switches back to http</a>. Some routes can even use http or websockets, depending on where they come from. In other words, the environment used by a QueryRenderer is non-deterministic and I need something that handles it all. Naturally, the atmosphere encompasses all environments, so that’s what I called it.</p><p>To set the Atmosphere, I first made a class that stored all the environments &amp; could return the current one with something like atmosphere.get(). This was easy enough, but each environment had its own store so some things got refetched and I ended up calling withAtmosphere all over the place.</p><p>The cleaner alternative was to <a href="https://github.com/ParabolInc/action/blob/aa2080d389c4d44318d05c64466526fb6c9afc16/src/client/Atmosphere.js#L7">extend </a><a href="https://github.com/ParabolInc/action/blob/aa2080d389c4d44318d05c64466526fb6c9afc16/src/client/Atmosphere.js#L7">Environment</a>. This gave me 2 benefits: I could get at it from any fragment container viaprops.relay.environment and my networks shared a store (albeit at the cost of unsafely using the internal <a href="https://github.com/ParabolInc/action/blob/aa2080d389c4d44318d05c64466526fb6c9afc16/src/client/Atmosphere.js#L43">_network</a>, but I like to live dangerously). Now, upgrading to a socket fetch is as easy as environment.setSocket(). I can even hardwire my <a href="https://github.com/ParabolInc/action/blob/aa2080d389c4d44318d05c64466526fb6c9afc16/src/client/Atmosphere.js#L46-L76">fetchQuery</a> functions as methods inside the atmosphere. That way if my http authorization header changes, I don’t need to create a whole new environment, i just environment.setAuth().</p><h4>Unsubscribing</h4><p>Way back when, in the days of Relay Classic, there was something called a clientMutationId. It was a simple ID that accompanied a mutation on its journey through request &amp; response. While it’s no longer needed for mutations, the concept works beautifully for subscriptions. Each subscription request <a href="https://github.com/ParabolInc/action/blob/aa2080d389c4d44318d05c64466526fb6c9afc16/src/client/Atmosphere.js#L97-L101">sends along</a> an opId (name borrowed from <a href="https://github.com/apollographql/subscriptions-transport-ws">Apollo</a>). Then, when it’s time to unsubscribe, the client just <a href="https://github.com/ParabolInc/action/blob/aa2080d389c4d44318d05c64466526fb6c9afc16/src/client/Atmosphere.js#L127">sends the </a><a href="https://github.com/ParabolInc/action/blob/aa2080d389c4d44318d05c64466526fb6c9afc16/src/client/Atmosphere.js#L127">opId</a> that it keeps in its Atmosphere. Finally, if we <a href="https://github.com/ParabolInc/action/blob/aa2080d389c4d44318d05c64466526fb6c9afc16/src/client/Atmosphere.js#L104-L114">put the </a><a href="https://github.com/ParabolInc/action/blob/aa2080d389c4d44318d05c64466526fb6c9afc16/src/client/Atmosphere.js#L104-L114">requestSubscription</a> in Atmosphere, then we can completely abstract away the opId in favor of returning a simple unsubscribe function that gets passed to our components. In Facebook land, this could be used to unsub from a newsfeed story after a user scrolls past it. But how do we start the subscription without reverting our sexy functional components back to boring Component classes?</p><h4>Where to Subscribe</h4><p>Just like Redux’s famous connect(mapStateToProps), subscribing when a component mounts can be as easy as <a href="https://github.com/ParabolInc/action/blob/aa2080d389c4d44318d05c64466526fb6c9afc16/src/universal/modules/teamDashboard/components/SlackIntegrations/SlackIntegrations.js#L163">withSubscriptions(subscription)</a>. But what if you want multiple subscriptions? Unfortunately, <a href="https://facebook.github.io/graphql/#sec-Single-root-field">GraphQL spec 5.1.3.1</a> (yes, I’m fun at parties) clearly states that only 1 subscription is allowed per operation. This is a bummer because most queries need at least 3 accompanying subscriptions (added, removed, updated) to keep it fresh. Again, borrowing from Redux’s compose function, we can <a href="https://github.com/ParabolInc/action/blob/aa2080d389c4d44318d05c64466526fb6c9afc16/src/universal/subscriptions/SlackChannel.js#L27-L45">gather up all of our unsubscribe functions</a> and execute when the time comes.</p><p>Personally, I don’t like to unsubscribe on unmounts. The reason is simple: imagine an app with 100 todo items. That’s an expensive query. Now imagine the client navigates away and then back again. You’ll have to refetch the query because the data went stale as soon as the subscription ended. If you wanted to turn it into an inequality, it’d be something like this:</p><p>NumMessagesAfterUnmount * AvgMessageSize &lt; P(ReturnVisit) * QueryCost</p><p>If the client leaves the page &amp; receives 10 1KB messages, it’ll cost you 10KB. If there’s a 20% probability that they return to the page and issue a new 100KB query, then the expected value is 20KB. That means if you kept the subscription alive you’d save twice the data! You could even use page analytics to determine the exact probability of a return visit and tweak accordingly. At least, in theory…</p><h4>Caching Data</h4><p>A big difference between Relay Classic &amp; Modern is that Modern always fetches the query when a component mounts. That means the above strategy won’t work out of the box. To circumvent this, there is the suggested strategy… and then there’s my strategy.</p><p>The <a href="https://facebook.github.io/relay/docs/network-layer.html">Facebook folks recommend</a> that you apply a cache at the network layer. In other words, in your fetchQuery function, before you call fetch, you check your cache for the outgoing request. If it’s there, you return the cached result. If it’s not, fetch and cache the result so you’ll be ready next time. They even make it super easy by <a href="https://github.com/facebook/relay/blob/master/packages/relay-runtime/network/RelayQueryResponseCache.js">giving you a cache</a> with a global time-to-live (TTL). If you want fine-grained TTL, you could trivially implement your own.</p><p>Unfortunately, both options are hogwash for one reason: If you query for those 100 todo items, and then your subscription sends in that 101st, your cached query is now invalid because it still has 100 items.</p><p><a href="https://github.com/ParabolInc/action/blob/aa2080d389c4d44318d05c64466526fb6c9afc16/src/universal/components/QueryRenderer/QueryRenderer.js#L139-L145">My solution is simple</a>: don’t remove the data from the Relay store until you’re ready. This could be when you <a href="https://github.com/ParabolInc/action/blob/aa2080d389c4d44318d05c64466526fb6c9afc16/src/client/Atmosphere.js#L120-L124">unsubscribe from the subscription</a> that kept the query fresh, or it <a href="https://github.com/ParabolInc/action/blob/aa2080d389c4d44318d05c64466526fb6c9afc16/src/universal/components/QueryRenderer/QueryRenderer.js#L62-L69">could be your own TTL</a>.</p><p>By default, when QueryRenderer mounts, it <a href="https://github.com/ParabolInc/action/blob/aa2080d389c4d44318d05c64466526fb6c9afc16/src/universal/components/QueryRenderer/QueryRenderer.js#L58">asks the server for data</a>. When that data arrives, it tells the store it <a href="https://github.com/ParabolInc/action/blob/aa2080d389c4d44318d05c64466526fb6c9afc16/src/universal/components/QueryRenderer/QueryRenderer.js#L215">cares about that data</a>. When it unmounts, it tells the store it <a href="https://github.com/ParabolInc/action/blob/aa2080d389c4d44318d05c64466526fb6c9afc16/src/universal/components/QueryRenderer/QueryRenderer.js#L147">no longer cares</a>. If <a href="https://github.com/facebook/relay/blob/master/packages/relay-runtime/store/RelayMarkSweepStore.js#L177-L197">nothing else</a> cares about that data node, it gets garbage collected. To fix this, I wrote a custom QueryRenderer that tries to <a href="https://github.com/ParabolInc/action/blob/aa2080d389c4d44318d05c64466526fb6c9afc16/src/universal/components/QueryRenderer/QueryRenderer.js#L48-L53">resolve the response</a> from the store before going to the network. Then, if you <a href="https://github.com/ParabolInc/action/blob/aa2080d389c4d44318d05c64466526fb6c9afc16/src/universal/components/QueryRenderer/QueryRenderer.js#L130-L138">specify a subscription or TTL</a>, it keeps caring about that data until the sub ends or TTL expires. In other words…</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/690/1*qLR6mQa3Kg1yezNo8yp5sA.jpeg" /><figcaption>So stoked for season 3…</figcaption></figure><p><strong>Pro tip</strong>: This strategy doesn’t work if your mutation delivers a partial record. For example, if you query a connection where each edge has a cursor, and then your mutation doesn’t provide a cursor, it’ll always think the query is incomplete. Ask me how I know. To debug this, stick a break point on <a href="https://github.com/facebook/relay/blob/master/packages/relay-runtime/store/RelayAsyncLoader.js#L156">RelayAsyncLoader#_handleMissing</a> to see what field is missing.</p><h4>The Back End</h4><h4>Broadcast</h4><p>Socket.io has a useful function called broadcast where it sends a message to everyone but the sender. How can we mimic that functionality so calling a mutation doesn’t result in a mutation response + an identical subscription payload? The solution is to place the socketId in the GraphQL context.</p><p>For example, at the <a href="https://github.com/ParabolInc/action/blob/aa2080d389c4d44318d05c64466526fb6c9afc16/src/server/graphql/mutations/addSlackChannel.js#L85">end of your mutation</a>, include the mutator’s socketId in the payload that goes to the pubsub. Then, in your GraphQL <a href="https://github.com/ParabolInc/action/blob/aa2080d389c4d44318d05c64466526fb6c9afc16/src/server/graphql/subscriptions/slackChannelAdded.js#L19">subscribe</a> function, compare that mutatorId to the subscriber’s socketId. This works because the pubsub payload doesn’t have to follow your schema and when it gets returned from subscribe, GraphQL will filter out the extra field.</p><pre>// addTodoMutation.js<br>getPubSub().publish(`todoAdded.${teamId}`, {newTodo, mutatorId})</pre><pre>// todoAddedSubscription.js<br>const filterFn = (<em>value</em>) =&gt; <em>value</em>.mutatorId !== <em>socketId</em>;<br>return makeSubscribeAsyncIter(channelName, filterFn);</pre><p>Sidenote: if you’re wondering why my pubsub is in a thunk, see <a href="https://hackernoon.com/graphql-tips-after-a-year-in-production-419341db52e3">GraphQL: Tips after a year in production</a>.</p><h4>Authentication</h4><p>Without locking down the subscription above, any attacker with knowledge of a team’s ID could listen for new todo items. That’s why the subscribe function, just like the resolve function for single payloads, is the best place for authentication. Before initializing the async iterator, while the request is still cheap, I shut down any funky requests. Then, for validation that depends on the incoming payload, I have the filterFn. Note that I don’t always have to return the pubsub payload. That payload could be the data necessary to trigger a user-specific query. That’s the power of evented subs!</p><h4>Kicking folks off a subscription</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/500/1*AYN2RdgdxYoYdETmP_fY0Q.jpeg" /></figure><p>Sometimes, you need to remotely kick someone off a subscription.</p><p>Thankfully, that’s as easy as calling <a href="https://github.com/ParabolInc/action/blob/aa2080d389c4d44318d05c64466526fb6c9afc16/src/server/socketHandlers/scRelaySubscribeHandler.js#L20">asyncIterator.return()</a>. For that to make sense, I recommend reading an <a href="https://jakearchibald.com/2017/async-iterators-and-generators/">article</a> <a href="http://2ality.com/2016/10/asynchronous-iteration.html">on</a> <a href="https://www.bignerdranch.com/blog/asyncing-feeling-about-javascript-generators/">Async</a> <a href="https://github.com/tc39/proposal-async-iteration">Iterators</a> &amp; playing around with them until they stop feeling like magic. It’ll take a few hours. When you call return(), your awaited iterating loop will resolve and you can <a href="https://github.com/ParabolInc/action/blob/aa2080d389c4d44318d05c64466526fb6c9afc16/src/server/socketHandlers/scRelaySubscribeHandler.js#L30">tell the client</a> that the subscription has ended. <em>This </em>is where that onCompleted <a href="https://github.com/ParabolInc/action/blob/aa2080d389c4d44318d05c64466526fb6c9afc16/src/client/Atmosphere.js#L89-L94">callback for Relay comes in</a>. Now you can pop a grumpy modal when people use potty words.</p><h3>Conclusion</h3><p>And with that, we’ve covered all the pitfalls of getting Relay set up for efficient subscriptions. There are still plenty of interesting problems to tackle, like extracting GraphQL to a stateless microservice, avoiding waterfall query requests using React Router v4, and talking to multiple endpoints (like GitHub’s new GraphQL API). If that sounds like fun to you, you’re weird</p><p>…and I want to work with you. We’re hiring a <a href="https://www.parabol.co/join">Senior Full-stack dev &amp; Summer Intern</a>. You’ll be employee #5 at a company that’s in Alchemist, one of the <a href="http://seedrankings.com/">top accelerators</a> in the world. We’re backed by some of the best investors from across the country, including SV Angel and even <a href="https://slackhq.com/introducing-7-new-slack-fund-companies-4b1ab9fd7a8a">Slack</a>, so we gotta be good, right? If you’re happy just playing with this stuff in your free time, get a little side hustle going by checking out our <a href="https://github.com/ParabolInc/action/projects/1">open issues</a>, submitting a PR, and grabbing a piece of the company with our <a href="https://focus.parabol.co/equity-for-effort-v2-0-7ca93e0a3968">Equity 4 Effort</a> program.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9e04b14a82d8" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Unit test your DB with GraphQL and Jest]]></title>
            <link>https://focus.parabol.co/unit-test-your-db-with-graphql-and-jest-d88722b4551e?source=rss-ca93f36ae1ea------2</link>
            <guid isPermaLink="false">https://medium.com/p/d88722b4551e</guid>
            <category><![CDATA[nodejs]]></category>
            <category><![CDATA[graphql]]></category>
            <category><![CDATA[jest]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[react]]></category>
            <dc:creator><![CDATA[Matt Krick]]></dc:creator>
            <pubDate>Wed, 08 Mar 2017 14:48:32 GMT</pubDate>
            <atom:updated>2017-03-08T14:48:32.969Z</atom:updated>
            <content:encoded><![CDATA[<p>Recently, I built out billing and invoicing functionality for our small, open-source SaaS app (look out world, we got ourselves a business model!). The added functionality expanded the codebase by something like 45% and errors crept in like gophers to a carrot patch. Now, we’re already pretty good about reactively handling errors. We use <a href="https://github.com/ngokevin/redux-raven-middleware">redux-middleware</a> to send the error &amp; redux state to Sentry, which grabs our sourcemaps &amp; pings us on our Slack channel. But with billing, I want to catch the error <em>before</em> it happens… because refunds are embarrassing. Unfortunately, unit testing a database has always been a pain. After all, a unit test is meant for a small, stateless function, and there’s nothing stateless about a database.</p><h4>Why unit testing a DB sucks</h4><p>Let’s name all the ways that unit testing can be a real pain in the DB:</p><ul><li>All your tests share the same database (goodbye concurrent testing!)</li><li>Compared to in-memory arrays, it’s dead slow</li><li>1 mutation can change many fields on many tables, meaning 50+ individual assertions is not uncommon</li><li>Asserting UserX is on TeamY is hard when both have non-deterministic unique IDs</li><li>Achieving the right pre-test state of the DB is a lengthy, painful, error-prone process that often takes longer than writing the business logic itself</li></ul><p>Seems like quite a mountain to climb! Let’s dig in.</p><h4>The Premise</h4><p>There are enough 101’s in the world, let’s do something that actually occurs in the wild. Let’s say we’ve got a mutation that updates a customer’s credit card number. We receive a card token (because there’s no way I want the added burden of safely handling your actual credit card), send it to Stripe, get back the last 4 digits, and update it in our DB. Seems simple enough! Unfortunately, getting the database (and Stripe) to a state that can handle this scenario is painful. We have to create a User. We need that user to have an Organization with a valid credit card. That Organization needs to be a valid Stripe Customer and have a valid Stripe Subscription. Oh yeah, and we need this test to be lighting fast, because we’ve got a lot more.</p><h3>Setting up the database</h3><p>First, we’ll need a database just for testing. If you’re like me, you already have a <a href="https://github.com/ParabolInc/action/tree/ed5844830df734d83b6a954c6b1b8e5ebcf7ce78/src/server/database/migrations">series of database migrations</a> set up so you can safely update and rollback your DB in production. If not, you probably have <em>some</em> kind of function that you can call to create a bunch of tables and indexes. Simply make sure the database used is a function of an environment variable (eg NODE_ENV=&quot;test&quot;) and run it.</p><p>Second, we’ll want to speed up the database by <a href="https://github.com/ParabolInc/action/blob/ed5844830df734d83b6a954c6b1b8e5ebcf7ce78/src/server/__tests__/setup/softenDurability.js">softening the write durability</a>. While having a hard durability (making sure the doc was written to disk) is ideal for production, a soft durability (<em>assuming</em> the doc got written to disk) is much faster. Since this is only needed when you initially set up your test database, I run it directly after the migration. Combined, the migration and softening is like a webpack DLL: you only need to run it once when you install the repo or make a major change.</p><p>Finally, we’ll need to teardown the database and remove the records. Using an afterAll function in Jest won’t work because it’s run after all the tests in a <em>file</em> complete, so you might be wiping out rows of data that another test still needs. Instead, we want to trigger something after <em>all</em> the tests complete. It’s a little unintuitive, but you’ll need to <a href="https://github.com/ParabolInc/action/blob/ed5844830df734d83b6a954c6b1b8e5ebcf7ce78/src/server/__tests__/teardown/teardown.js">write a script</a> and reference it in your Jest config’s testResultsProcessor. In that teardown, I like to drain the DB connection pool so the process exits clean and every so often I empty out all the records — do this too much and it becomes added overhead, never do it and you’ve got a huge DB on your test machine, so I settle on about once every 100 runs.</p><h3>Designing the test</h3><p>A GraphQL mutation is the perfectly sized chunk for unit tests. Sure, you’ll still want to mock the occasional function in your mutations, but starting with the mutation as a whole is a great start. If you notice the test suite is getting too unruly, it’s a good cue to ask yourself if your mutation itself is too big.</p><p>If you’ve read my <a href="https://hackernoon.com/graphql-tips-after-a-year-in-production-419341db52e3#.ukln9e79p">tips on using GraphQL in production</a>, then you know about the <strong>Auth, Validation, Resolution</strong> pattern for GraphQL mutations. Similarly, I break each unit test into <strong>Setup, Test, </strong>and <strong>Verify </strong>stages (props to <a href="https://medium.com/u/d996bc07862b">Jordan Husney</a> for the idea).</p><h4>The Setup stage</h4><p>Setup is used to get the database to a useful pre-test state. In this example, it means creating a user and organization. Now, there are 2 ways for us to create a user and organization: we could use our pre-existing business logic (presumably <strong>createUser</strong> and <strong>createOrg</strong> mutations) or we could directly insert some rows into the database. The former is DRY, but since it depends on other mutations, it turns into a slow integration test rather than a fast unit test. So, I opt for the latter. To DRY it up, I use an app-specific <a href="https://github.com/ParabolInc/action/blob/ed5844830df734d83b6a954c6b1b8e5ebcf7ce78/src/server/__tests__/setup/MockDB.js">MockDB</a> I built which gives me a nice clean API:</p><pre>const mockDB = new MockDB(); <br>const {user, organization} = await mockDB<br>  .newUser()<br>  .newOrganization({creditCard})</pre><p>The MockDB is nothing fancy: each method call pushes a new document with default values into an in-memory array. If I need to add more fields or override the default values (like I do with creditCard above) I just pass them in. Then, when you stick await in front of it, it magically batch-inserts the in-memory arrays to my database all at once, making for the quickest setup imaginable.</p><h4>The Test stage</h4><p>The Test stage is simply preparing the variables from the Setup stage, calling the GraphQL mutation, and awaiting the result to mutate your DB. In this case, await addBilling.resolve(...). It’s rare if this is more than couple lines.</p><h4>The verify stage</h4><p>This is where we rip the data from the database and run our assertions on it. That means we need to grab the Organization and make sure it looks exactly right. We could do this by cherry picking a couple fields like creditCard and updatedAt, but in reality we’re gonna update about 20 fields across 3 tables, which is enough cherry picking to make a pie.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*YXZhEEUrX-rdLzT-5yrBCA.jpeg" /><figcaption>Look at all those ooey gooey assertions just oozing out the sides of our unit test.</figcaption></figure><p>Instead, let’s use Jest’s snapshot feature. It’s like a JSON deep equals, but it generates and maintains the expected value for you (why folks never explain it like this &amp; opt for a cute polaroid analogy is beyond me).</p><p>So what do we want to snapshot? The Organization doc, any User in that organization, and eventually our Stripe account (yeah, I made a manual mock of Stripe, but let’s save that for another time):</p><pre>const queriesToSnapshot = {<br>  organization: db.table(&#39;Organization&#39;).get(orgId),<br>  user: db.table(&#39;User&#39;).getAll(orgId, {index: &#39;orgId&#39;})<br>}<br>const keys = Object.keys(queriesToSnapshot);<br>const values = Object.values(queriesToSnapshot);<br>const docs = await Promise.all(values);<br>const snapshot = docs.map((<em>doc</em>, <em>idx</em>) =&gt; {<br>  return dynamicSerializer.toStatic(<em>doc</em>, fieldsToSerialize[<em>idx</em>])<br>})</pre><p>By creating an object full of promises like queriesToSnapshot, we can fetch all the documents concurrently. That means Setup, Test, and Verify each only call <strong>await </strong>once, keeping our tests screaming fast. Then, we string together all the results into one big JSON so we only run 1 snapshot per DB. But what exactly is that dynamicSerializer?</p><h4>The Dynamic Serializer</h4><p>Every time this test is run, it will generate new unique values for things like userId. This is necessary because our tests are going to run in parallel and we don’t want 2 primary keys to collide when the documents are inserted. However, random keys make snapshot testing impossible. Furthermore, it is not enough to just remove those fields. For example, my user document has an orgId foreign key that I want to match to its primary key on Organization.</p><p>We could solve this by mocking our random key generator in each test and very carefully stringing together a chain of mockReturnValueOnce, but then our tests get bloaty and brittle. Instead, I solved this the same way webpack did with numbered modules: create a cache of all unique keys, and then replace them with an incrementing integer. But there’s another constraint — what if I have more than 1 database in the same test? For example, if my stripeCustomerId serializes to 5 in my DB, I want it to serialize to 5 in my mock of Stripe. Thankfully, that’s all handled for me in a package called <a href="http://github.com/mattkrick/dynamic-serializer">dynamic-serializer</a>, which manages a dynamic value dictionary for the entire test. And just like that, I have deterministic unique IDs!</p><h3>Conclusion</h3><p>On my vintage 2013 Macbook Air, a single unit test involving 3 tables takes about 30ms — pretty darn reasonable. Each test is also about 20 LOCs, which makes it easy to grok when I inevitably break my tests and have to revisit my tests in the coming month. More importantly, by testing my actual queries against a real database output, I uncovered a handful of bugs and edge cases that would have otherwise gone unnoticed. If you want to see more, feel free to <a href="https://github.com/ParabolInc/action">dig into the code</a>. If you hate what you see, drop me a line in the comments below.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d88722b4551e" width="1" height="1" alt=""><hr><p><a href="https://focus.parabol.co/unit-test-your-db-with-graphql-and-jest-d88722b4551e">Unit test your DB with GraphQL and Jest</a> was originally published in <a href="https://focus.parabol.co">Parabol Focus</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>