Obafunso Ridwan

Usage

To begin, you would need a cache/in memory store such as Redis, or Memcached installed on your machine or alternatively using NodeJS Internal Caching (node-cache). If you want to quickly get up and running without installing Redis or Memcached on your machine. I highly recommend using managed cloud services like RedisLabs or Memcachier. No worries, they both have free plan with 25MB storage with no credit card required.

Node Cache 💪

  const express = require('express')
  const { Suya } = require('suya')

  const app = express()

  const Cache = new Suya({
    engine: {
      name: 'node-cache',
    },
  })

  // This is a middleware to cache forever.
  // Methods supported: GET
  let cacheForever = Cache.forever()

  // This is a middleware to cache for a specific seconds.
  // Methods supported: GET
  let cacheWithDuration = Cache.duration(50)

  // This is a middleware to reset cache on mutation.
  // Methods supported: POST, PUT, PATCH, DELETE
  let resetCacheOnMutate = Cache.resetOnMutate({
    indicator: {
      success: true,
    },
  })

  let mockDB = () => {
    let users = [
      {
        id: 1,
        name: 'John Smith',
        email: '[email protected]',
      },
      {
        id: 2,
        name: 'James Noah',
        email: '[email protected]',
      },
    ]

    // mocking response time to be between 100ms - 600ms
    let randResponseTime = Math.floor(Math.random() * 6 + 1) * 100

    return new Promise((resolve, reject) => {
      return setTimeout(() => {
        resolve(users)
      }, randResponseTime)
    })
  }

  app.get('/users/forever', cacheForever, async (req, res, next) => {
    let users = await mockDB()

    res.status(200).json({
      success: true,
      data: {
        users,
      },
      code: 200,
    })
  })

  app.put('/users/forever', resetCacheOnMutate, async (req, res, next) => {
    let users = await mockDB()

    // res.status(400).json({
    //   // once the indicator set on .resetOnMutate({}) middleware doesn't match
    //   // like so, the data remain cached.
    //   success: false,
    //   error: {
    //     message: 'Email address is required!',
    //   },
    //   code: 400,
    // })

    res.status(200).json({
      // once the indicator set on .resetOnMutate({}) middleware match like so,
      // the cached data would get cleared it out.
      success: true,
      data: {
        users,
      },
      code: 200,
    })
  })

  app.get('/users/duration', cacheWithDuration, async (req, res, next) => {
    let users = await mockDB()

    res.status(200).json({
      success: true,
      data: {
        users,
      },
      code: 200,
    })
  })

  app.put('/users/duration', resetCacheOnMutate, async (req, res, next) => {
    let users = await mockDB()

    // res.status(400).json({
    //   // once the indicator set on .resetOnMutate({}) middleware doesn't match
    //   // like so, the data remain cached.
    //   success: false,
    //   error: {
    //     message: 'Email address is required!',
    //   },
    //   code: 400,
    // })

    res.status(200).json({
      // once the indicator set on .resetOnMutate({}) middleware match like so,
      // the cached data would get cleared it out.
      success: true,
      data: {
        users,
      },
      code: 200,
    })
  })

  const server = app.listen(2000, () =>
    console.log('Server running at http://127.0.0.1:2000')
  )

  process.on('unhandledRejection', (err, promise) => {
    console.log(`Error: ${err.message}`)

    // close the server
    server.close(async () => {
      // close connection
      await Cache.close()

      process.exit(1)
    })
  })

Redis 👊

  const express = require('express')
  const { Suya } = require('suya')

  const app = express()

  const Cache = new Suya({
    engine: {
      name: 'redis',
      configs: {
        redis: {
          // node-redis configs options.
          // https://github.com/NodeRedis/node-redis#options-object-properties
          options: {
            host: '127.0.0.1', // Redis host
            port: 6379, // Redis port
            password: '[pass]', // Redis password
            family: 4, // 4 (IPv4) or 6 (IPv6)
            db: 0, // Redis database
          },
        },
      },
      // whether suya should/shouldn't log to console
      logging: true,
    },
  })

  // This is a middleware to cache forever.
  // Methods supported: GET
  let cacheForever = Cache.forever()

  // This is a middleware to cache for a specific seconds.
  // Methods supported: GET
  let cacheWithDuration = Cache.duration(50)

  // This is a middleware to reset cache on mutation.
  // Methods supported: POST, PUT, PATCH, DELETE
  let resetCacheOnMutate = Cache.resetOnMutate({
    indicator: {
      success: true,
    },
  })

  let mockDB = () => {
    let users = [
      {
        id: 1,
        name: 'John Smith',
        email: '[email protected]',
      },
      {
        id: 2,
        name: 'James Noah',
        email: '[email protected]',
      },
    ]

    // mocking response time to be between 100ms - 600ms
    let randResponseTime = Math.floor(Math.random() * 6 + 1) * 100

    return new Promise((resolve, reject) => {
      return setTimeout(() => {
        resolve(users)
      }, randResponseTime)
    })
  }

  app.get('/users/forever', cacheForever, async (req, res, next) => {
    let users = await mockDB()

    res.status(200).json({
      success: true,
      data: {
        users,
      },
      code: 200,
    })
  })

  app.put('/users/forever', resetCacheOnMutate, async (req, res, next) => {
    let users = await mockDB()

    // res.status(400).json({
    //   // once the indicator set on .resetOnMutate({}) middleware doesn't match
    //   // like so, the data remain cached.
    //   success: false,
    //   error: {
    //     message: 'Email address is required!',
    //   },
    //   code: 400,
    // })

    res.status(200).json({
      // once the indicator set on .resetOnMutate({}) middleware match like so,
      // the cached data would get cleared it out.
      success: true,
      data: {
        users,
      },
      code: 200,
    })
  })

  app.get('/users/duration', cacheWithDuration, async (req, res, next) => {
    let users = await mockDB()

    res.status(200).json({
      success: true,
      data: {
        users,
      },
      code: 200,
    })
  })

  app.put('/users/duration', resetCacheOnMutate, async (req, res, next) => {
    let users = await mockDB()

    // res.status(400).json({
    //   // once the indicator set on .resetOnMutate({}) middleware doesn't match
    //   // like so, the data remain cached.
    //   success: false,
    //   error: {
    //     message: 'Email address is required!',
    //   },
    //   code: 400,
    // })

    res.status(200).json({
      // once the indicator set on .resetOnMutate({}) middleware match like so,
      // the cached data would get cleared it out.
      success: true,
      data: {
        users,
      },
      code: 200,
    })
  })

  const server = app.listen(2000, () =>
    console.log('Server running at http://127.0.0.1:2000')
  )

  process.on('unhandledRejection', (err, promise) => {
    console.log(`Error: ${err.message}`)

    // close the server
    server.close(async () => {
      // close connection
      await Cache.close()

      process.exit(1)
    })
  })

Memcached 👌

  const express = require('express')
  const { Suya } = require('suya')

  const app = express()

  const Cache = new Suya({
    engine: {
      name: 'memcached',
      configs: {
        memcached: {
          // server string format e.g
          // single server        - user:pass@server1:11211
          // multiple servers     - user:pass@server1:11211,user:pass@server2:11211
          server: 'johndoe:[email protected]:11211', // local memcached server
          // memjs configs options - https://github.com/memcachier/memjs
          // some memjs options are overridden by suya. supported options are
          // {
          //   retries: 2,
          //   retry_delay: 0.2,
          //   failoverTime: 60,
          // }
          options: {
            retries: 2,
            retry_delay: 0.2,
            failoverTime: 60,
          },
        },
      },
      // whether suya should/shouldn't log to console
      logging: true,
    },
  })

  // This is a middleware to cache forever.
  // Methods supported: GET
  let cacheForever = Cache.forever()

  // This is a middleware to cache for a specific seconds.
  // Methods supported: GET
  let cacheWithDuration = Cache.duration(50)

  // This is a middleware to reset cache on mutation.
  // Methods supported: POST, PUT, PATCH, DELETE
  let resetCacheOnMutate = Cache.resetOnMutate({
    indicator: {
      success: true,
    },
  })

  let mockDB = () => {
    let users = [
      {
        id: 1,
        name: 'John Smith',
        email: '[email protected]',
      },
      {
        id: 2,
        name: 'James Noah',
        email: '[email protected]',
      },
    ]

    // mocking response time to be between 100ms - 600ms
    let randResponseTime = Math.floor(Math.random() * 6 + 1) * 100

    return new Promise((resolve, reject) => {
      return setTimeout(() => {
        resolve(users)
      }, randResponseTime)
    })
  }

  app.get('/users/forever', cacheForever, async (req, res, next) => {
    let users = await mockDB()

    res.status(200).json({
      success: true,
      data: {
        users,
      },
      code: 200,
    })
  })

  app.put('/users/forever', resetCacheOnMutate, async (req, res, next) => {
    let users = await mockDB()

    // res.status(400).json({
    //   // once the indicator set on .resetOnMutate({}) middleware doesn't match
    //   // like so, the data remain cached.
    //   success: false,
    //   error: {
    //     message: 'Email address is required!',
    //   },
    //   code: 400,
    // })

    res.status(200).json({
      // once the indicator set on .resetOnMutate({}) middleware match like so,
      // the cached data would get cleared it out.
      success: true,
      data: {
        users,
      },
      code: 200,
    })
  })

  app.get('/users/duration', cacheWithDuration, async (req, res, next) => {
    let users = await mockDB()

    res.status(200).json({
      success: true,
      data: {
        users,
      },
      code: 200,
    })
  })

  app.put('/users/duration', resetCacheOnMutate, async (req, res, next) => {
    let users = await mockDB()

    // res.status(400).json({
    //   // once the indicator set on .resetOnMutate({}) middleware doesn't match
    //   // like so, the data remain cached.
    //   success: false,
    //   error: {
    //     message: 'Email address is required!',
    //   },
    //   code: 400,
    // })

    res.status(200).json({
      // once the indicator set on .resetOnMutate({}) middleware match like so,
      // the cached data would get cleared it out.
      success: true,
      data: {
        users,
      },
      code: 200,
    })
  })

  const server = app.listen(2000, () =>
    console.log('Server running at http://127.0.0.1:2000')
  )

  process.on('unhandledRejection', (err, promise) => {
    console.log(`Error: ${err.message}`)

    // close the server
    server.close(async () => {
      // close connection
      await Cache.close()

      process.exit(1)
    })
  })

⏮️ API | Error Handling ⏭️