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

Raise Dalli::UnmarshalError on ArgumentError "dump format error (user class)" #1008

Conversation

olleolleolle
Copy link
Contributor

@olleolleolle olleolleolle commented Aug 8, 2024

This PR makes Rails recognize the unmarshalling error and can deal with it normally.

Before this change, such an ArgumentError would bubble up and raise in Rails.

Details

In Marshal, a "user class" is a class which extends a "core class" (String, Hash...).

When a "user class" is dumped by Marshal.dump, it becomes a binary string. Marshal.load, expects that the inheritance of this class looks the same as it did when the binary string was created.

If the classes do not match, due to some change in the code, an ArgumentError is raised. (The specific ArgumentError is raised in marshal.c.)

Marshal's concept of "user class" is explained in: "Caching With MessagePack" by Chris Salzberg at RubyKaigi 2022

Context for Rails

This Rails commit, which is in Rails 7.1, rails/rails@a6be798, expects Dalli to reraise such errors, so that Rails can decide to regenerate that cache entry.

Between 7.0 and 7.1 Rails changed the inheritance hierarchy in its String-extending classes OutputBuffer and SafeBuffer, which triggered this error in production for me.

Further

In #1009 I made the regular expression-making code a little easier to read, using Regexp.union.

But, later, in #1011, I made a wider change, reraising Dalli::UnmarshalError for all errors raised during serializer.load. It's a simplification of the code, of the solution, but takes more steps than this tiny change.


EDIT: I posted a feature request in bugs.ruby-lang.org for having error classes for these ArgumentError instances, instead. (Perhaps they can become 1 error, (class UnmarshalingError < ArgumentError), or something.)

This makes Rails recognize the unmarshalling error and deals with it
normally.
@olleolleolle olleolleolle force-pushed the add-argument-error-handling-for-user-class branch from 3b565e3 to 148ef59 Compare August 8, 2024 08:26
Copy link

@kaspth kaspth left a comment

Choose a reason for hiding this comment

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

Can confirm there was a bunch of refactoring done on the SafeBuffer and OutputBuffer (iirc to leverage Ruby's native String#<<). I'm surprised the error ended up being thrown in production now because of those changes, but this fix looks good to me!

@petergoldstein
Copy link
Owner

@olleolleolle As #1011 has been merged, I'm assuming this can be closed, correct?

@olleolleolle
Copy link
Contributor Author

Thanks, and confirming, yes! Closing.

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.

3 participants