netlify / netlify-faunadb-example

Using FaunaDB with netlify functions
https://www.netlify.com/blog/2018/07/09/building-serverless-crud-apps-with-netlify-functions--faunadb/
385 stars 121 forks source link

Follow AWS Lambda best practices #15

Closed joshwcomeau closed 4 years ago

joshwcomeau commented 4 years ago

I recently tried using faunadb inside Netlify Functions, and I noticed about 25% of the time, the functions were returning a 502 with this error:

12:36:29 PM: 2020-02-13T11:36:29.083Z   00e2d3c8-39f5-48e4-b5c2-4341629d4ef9    ERROR   FetchError: request to https://db.fauna.com/ failed, reason: socket hang up
    at ClientRequest.<anonymous> (/var/task/node_modules/node-fetch/lib/index.js:1455:11)
    at ClientRequest.emit (events.js:223:5)
    at TLSSocket.socketOnEnd (_http_client.js:440:9)
    at TLSSocket.emit (events.js:228:7)
    at endReadableNT (_stream_readable.js:1185:12)
    at processTicksAndRejections (internal/process/task_queues.js:81:21) {
  message: 'request to https://db.fauna.com/ failed, reason: socket hang up',
  type: 'system',
  errno: 'ECONNRESET',
  code: 'ECONNRESET'
}

I found this relevant issue, which links to this article around how to use FaunaDB in AWS Lambda functions. The short version is: the calls to instantiate the connection should be done inside the handler, instead of outside, to prevent the environment from reusing a connection that has closed.

As an example, here's how the first function should change, to avoid the issue I was running into:

/* Import faunaDB sdk */
const faunadb = require('faunadb')

-/* configure faunaDB Client with our secret */
-const q = faunadb.query
-const client = new faunadb.Client({
-  secret: process.env.FAUNADB_SERVER_SECRET
-})

/* export our lambda function as named "handler" export */
exports.handler = async (event, context) => {
+  /* configure faunaDB Client with our secret */
+  const q = faunadb.query
+  const client = new faunadb.Client({
+    secret: process.env.FAUNADB_SERVER_SECRET
+  })
+
  /* parse the string body into a useable JS object */
  const data = JSON.parse(event.body)
  console.log('Function `todo-create` invoked', data)
  const todoItem = {
    data: data
  }
  /* construct the fauna query */
  return client.query(q.Create(q.Ref('classes/todos'), todoItem))
    .then((response) => {
      console.log('success', response)
      /* Success! return the response with statusCode 200 */
      return {
        statusCode: 200,
        body: JSON.stringify(response)
      }
    }).catch((error) => {
      console.log('error', error)
      /* Error! return the error with statusCode 400 */
      return {
        statusCode: 400,
        body: JSON.stringify(error)
      }
    })
}

I expect that this will be an issue for just about anyone that tries following this example, and I was pretty close to just giving up and rolling a Node server when I found the issue 😅so it'd be awesome if you could update the functions in the example!

DavidWells commented 4 years ago

Thanks for the report! This has been fixed!

wiesson commented 4 years ago

I just wanted to point out that the examples have not yet been fixed. I just fixed a website with ~25% data loss.