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

add component and params to Error on visibility timeout #14

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

pklingem
Copy link
Member

@pklingem pklingem commented Aug 29, 2017

image

image

According to MDN the error object is intended to have properties set on it, that the properties match what airbrake uses is a nice side-effect.

index.js Outdated
handleTimeout = compose(partial(done, [ new Error(timeoutErr.error) ]), tap(logTimeout))
timeout = setTimeout(handleTimeout, visibilityTimeout * 1000),
finish = compose(tap(partial(clearTimeout, [ timeout ])), done)
const done = once(callback)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit-pick: leftover extra spaces

index.js Outdated
const handleTimeout = () => {
const error = new Error(timeoutErr.error)
const params = mergeAll([ options, { type, payload }, timeoutErr ])
error.params = params
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Combine this with the previous line?

@dbertram
Copy link
Contributor

This lgtm, but can/should we set this up for all errors in processJob instead of only for timeout errors?

The new code plus the final .catch(finish) in processJob could be refactored to use a common addErrorContext (or whatever you want to call it) that sets error.params and error.component. Then any error thrown during process job would include the job payload, type, etc.

What do you think?

@pklingem
Copy link
Member Author

good points, all. Addressing.

@pklingem
Copy link
Member Author

@dbertram updated, had to introduce another synonym for done 🤦‍♂️ .

const handleTimeout = () => {
const error = new Error(timeoutErr.error)
addErrorContext(error)
timeoutLogger(params)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think there's a params in scope at this point...which is probably my fault for suggesting you combine those two lines earlier where iirc, you had a separate const params = ....

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I'm not seeing any params anywhere. Do we have linting for this library?

addErrorContext(error)
timeoutLogger(params)
complete(error)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not saying it's any clearer, but is it worth making this a pipe?

const logTimeout = partial(timeoutLogger, [ params ])
const handleTimeout = pipe(
  always(new Error(timeoutErr.error)),
  addErrorContext,
  tap(logTimeout),
  complete
)

@flintinatux
Copy link
Contributor

👀

Copy link
Contributor

@flintinatux flintinatux left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pklingem @dbertram: I've made some minor comments below, but I'd also like to address my main concern with this approach. The processJob function originally just selected a handler function for a job type, lifted it into a Promise chain, and then ran it. Now about 90% of that function is for handling timeouts, and is exceptionally imperative, despite the abundance of ramda involved. So I think we need a different approach.

I'd be more amenable to an approach that let us take advantage of the Promise chain, like this:

const assign = flip(Object.assign)

const reject = bind(Promise.reject, Promise)

const wrapError = params =>
  pipe(
    unless(is(Error), Error),
    assign({
      component: 'squiss-jobs'
      params
    }),
    reject
  )

const handleJob = ({ type, payload }) =>
  handlerFor(type)(payload)

const processJob = (params, done) =>
  timeout(visibilityTimeout * 1000, handleJob, params)
    .then(nAry(0, done))
    .catch(wrapError(params))
    .catch(done)

const timeout = (delay, f, params) => 
  new Promise((resolve, reject) => {
    setTimeout(() =>
      reject(new Error('visibility timeout exceeded'))
    , delay)

    Promise.resolve(params)
      .then(f)
      .then(resolve)
      .catch(reject)
  })

The only mutable function above is assign, and everything else is nice and functional, and hopefully more readable. And I'm sure I missed a few bits, but that's the gist of it.

const addErrorContext = error => {
error.params = mergeAll([ options, { type, payload }, timeoutErr ])
error.component = 'squiss-jobs'
return error
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is mutable, and can sometimes be called twice on the same error, which is kinda 👃 .

const handleTimeout = () => {
const error = new Error(timeoutErr.error)
addErrorContext(error)
timeoutLogger(params)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I'm not seeing any params anywhere. Do we have linting for this library?

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

Successfully merging this pull request may close these issues.

None yet

3 participants