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

Strip ActiveJob keys to prevent recursion #386

Closed
wants to merge 1 commit into from
Closed

Conversation

mattrobenolt
Copy link
Contributor

Once an ActiveJob is queued, ActiveRecord references get serialized into
some internal reserved keys, such as _aj_globalid.

The problem is, if this job in turn gets queued back into ActiveJob with
these magic reserved keys, ActiveJob will throw up and error. We want to
capture these and mutate the keys so we can sanely report it.

Fixes GH-384

Once an ActiveJob is queued, ActiveRecord references get serialized into
some internal reserved keys, such as _aj_globalid.

The problem is, if this job in turn gets queued back into ActiveJob with
these magic reserved keys, ActiveJob will throw up and error. We want to
capture these and mutate the keys so we can sanely report it.

Fixes GH-384
@seanlinsley
Copy link
Contributor

From #384:

I'm having issues with Raven reporting errors that happen inside of ActiveJob jobs when Raven is configured to send events in the background.

It seems like the better option is to disable background Raven event sending when inside of any given background worker (ActiveJob, Resque, Sidekiq, etc.)

Especially when the only other option is to special-case the removal of ActiveJob keys.

@seanlinsley
Copy link
Contributor

As far as the implementation in this PR, shouldn't this code be abstracted out to ActiveJob, since it's not Sidekiq that's causing the bug?

# e.g.: _aj_globalid -> _globalid
if key[0..3] == '_aj_'
key = key[3..-1]
end
Copy link
Contributor

Choose a reason for hiding this comment

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

Wouldn't it be better to remove the keys entirely? If the ActiveJob job to send this event to Sentry fails, the metadata will be overridden if it's re-queued, so at the very least it's not reliable data.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I wasn't sure if it'd be safe to strip them entirely or not. That was my initial thought, but decided it'd probably be better to err on the side of preserving as much data as possible.

Copy link
Contributor

Choose a reason for hiding this comment

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

@seanlinsley's right, this is internal private state that's likely wrong/unreliable anyway. We should just drop them.

@mattrobenolt
Copy link
Contributor Author

It seems like the better option is to disable background Raven event sending when inside of any given background worker (ActiveJob, Resque, Sidekiq, etc.)

This is probably true. I'll have to dig around and figure out how that works.

As far as the implementation in this PR, shouldn't this code be abstracted out to ActiveJob, since it's not Sidekiq that's causing the bug?

I dug into the active_job.rb, but it didn't seem to be stemming from there. I'll poke at it some more and see if I can come up with something.

I'm pretty new to ruby, and trying to get familiar with these things. :)

@nateberkopec
Copy link
Contributor

As far as the implementation in this PR, shouldn't this code be abstracted out to ActiveJob, since it's not Sidekiq that's causing the bug?

I think I disagree. The bug is that we're creating an object in a forbidden way. That's our problem.

end
end

def filter_context_hash(key, value)
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there any way we can access the RESERVED_KEYS constant directly here? (I think that's what it's called)

Copy link
Contributor

Choose a reason for hiding this comment

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

That'll dedup the knowledge of what a "forbidden" key is.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So I err'd on the side of being liberal and catching _aj_ prefix rather than duping the list in here and worrying about maintaining that.

Copy link
Contributor

Choose a reason for hiding this comment

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

I suppose the only truly maintainable solution in the long term would be to rescue SerializationErrors. Hm.

@nateberkopec
Copy link
Contributor

I think we're on the right track, but it should live in active_job.rb

@lleger
Copy link

lleger commented Dec 2, 2015

This looks great. Looking forward to deploying this in our app so we can send in the background again. Any idea when you're planning to have this merged and released?

@nateberkopec
Copy link
Contributor

As far as the implementation in this PR, shouldn't this code be abstracted out to ActiveJob, since it's not Sidekiq that's causing the bug?

It took me a little while to understand this, but the reason this code is in the Sidekiq integration is because we don't load the ActiveJob integration when using Activejob with Sidekiq. This is because the Sidekiq integration gives us better access to the Sidekiq context hash, which sometimes provides some nice extra data on where/how the error occurred.

So, this is bug happens when all of these conditions are met:

  • Using Sidekiq
  • Using ActiveJob
  • Using Raven-Ruby with an async config
  • Your exception involved an object with a globalid.

This bug doesn't happen with the ActiveJob integration because we're much more stingy with the data we pass along in that integration. The object with the globalid is never serialized. With Sidekiq, we just pass everything (like we should - more data is best when debugging).

@nateberkopec
Copy link
Contributor

Decided I couldn't think of a better solution, so better to merge a fix. Had to update for style: a96d47b

@mattrobenolt
Copy link
Contributor Author

:) thx homie

@lleger
Copy link

lleger commented Dec 30, 2015

Confirmed with the test app I created for the issue that this fix worked. What is the release ETA for this version of the gem? Would like to update and get it running on my apps. Thanks again guys! 👏

@nateberkopec
Copy link
Contributor

@lleger As soon as we figure out #422

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.

4 participants