Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using custom Error types for consistency and brevity in error status codes #5

Open
djfarrelly opened this issue Oct 9, 2018 · 4 comments
Labels
enhancement New feature or request

Comments

@djfarrelly
Copy link

Copied from bufferapp/micro-rpc#2

Purpose

Inspired by Apollo server's way to throw errors, I was thinking it might be a little nicer than the current createError pattern.

Proposal

Instead of creating the error and optionally pass an error code, we have specific errors that consumers can import which might make things consistent.

const {
  rpc,
  method,
  ParameterError,  // or UserInputError like Apollo
  ForbiddenError,
  FatalError,
} = require('@bufferapp/micro-rpc');

module.exports = rpc(
  method('getUser', async ({ _id }) => {
    if (!accessToken || isValidAccessToken(accessToken)) {
      throw new ForbiddenError()
      // response => 403 { message: 'Forbidden' }
    }
    if (!_id) {
      throw new ParameterError(`_id required`)
      // response => 400 { message: '_id required' }
    }
    if (!isValidID(_id)) {
      throw new ParameterError('Invalid _id parameter')
      // response => 400 { message: 'Invalid _id parameter' }
    }
    try {
      const user = db.
    } catch (err) {
      throw new FatalError(`Database error finding user ${_id}`)
      // response => 500 { message: '_id required' }
    }
  })
)

These errors would already have the err.statusCode set.

This also could help us remove this library's dependency on micro or we could use this pattern to create a new micro-less rpc library since we're using Express under the hood.

@djfarrelly
Copy link
Author

I've seen in a new branch by @msanroman we often duplicate a ton of code in each RPC handler:

 if (!accountId) {
    throw createError({
      message: 'accountId must be specified',
      code: REQUIRED_PARAMETER_MISSING,
    })
  }

Which could be shortened by 3 lines of code and make it be much easier to read!

if (!accountId) {
  throw MissingParameterError('accountId')
}

If we wanted to add another separate library or some utils with this library, we could do things like this:

// Potential rpc library util function
const requireParameters = (obj) => {
  for (let key of obj) {
    if (!obj[key]) throw MissingParameterError(key)
  }
}
// Example rpc handler in a service:
const getChannelsForProduct = async ({ accountId, product }) => {
  requireParameters({ accountId, product }) // will throw if one is undefined
  // do business logic
}

cc @philippemiguet, @esclapes, @CoxyBoris

@djfarrelly djfarrelly changed the title Using custom Error types for consistency in error status codes Using custom Error types for consistency and brevity in error status codes May 14, 2019
@djfarrelly djfarrelly added the enhancement New feature or request label May 14, 2019
@CoxyBoris
Copy link

That's a really great idea @djfarrelly ! 🙌

I wonder if this pattern could be used across rpc & http or functions in code , we often need to verify missing parameters and throw errors.

@msanroman
Copy link
Member

I love it! 👍

@esclapes
Copy link
Contributor

I agree this would be a great improvement. I specially like the idea of allowing consumers of an RPC server to use the exported types to be able to understand errors better.

When thinking about defining new error types, I would suggest we take inspiration from (or even depend on) verror which offers quite a nice interface to chain errors.

Our apps usually have a pattern of:

Front -> public RPC server -> internal RPC services

So buffer-rpc server would be used twice in that chain. Having a nice way to include the underlying cause can be very useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants