-
Notifications
You must be signed in to change notification settings - Fork 331
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
Content type (de)serialization #152
Content type (de)serialization #152
Conversation
@@ -52,10 +53,11 @@ def do_work(delivery_info, metadata, msg, handler) | |||
metrics.increment("work.#{self.class.name}.started") | |||
Timeout.timeout(@timeout_after, Timeout::Error) do | |||
metrics.timing("work.#{self.class.name}.time") do | |||
deserialized_msg = ContentType[@content_type || metadata[:content_type]].deserialize(msg) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's no docs on this method indicating metadata will always be present and it's not private so you might need to handle the metadata == nil
case.
Separately I think there are cases where you would want to prefer the worker's content type over the message's and cases for the inverse. Might be worth refactoring that bit of logic into a method that respects a new preference set on the worker indicating which order to prefer.
This is a nifty idea. We've done something similar but with base worker classes that delegate from |
I agree! it looks elegant and in the spirit of the existing api. |
Ok made some changes that it short circuits if no content types are registered. This halves the overhead, but at the cost of some elegance. Beforerequire 'benchmark'
require 'sneakers/content_type'
msg = "foo"
itr = 10_000_000
def dummy(something)
something
end
Benchmark.bmbm do |x|
x.report("content_type lookup:") { itr.times { dummy(Sneakers::ContentType[nil].serialize(msg)) } }
x.report("no lookup:") { itr.times { dummy(msg) } }
end
Afterrequire 'benchmark'
require 'sneakers/content_type'
msg = "foo"
itr = 10_000_000
def dummy(something)
something
end
Benchmark.bmbm do |x|
x.report("content_type lookup:") { itr.times { dummy(Sneakers::ContentType.serialize(msg, nil)) } }
x.report("no lookup:") { itr.times { dummy(msg) } }
end
|
Its a difference of 0.185μs, do we care about performance that much? We are basically optimising away 2 method dispatches ... |
re @justin-yesware I prefer the simplicity of:
In my experience I do want to spend some time making sure that my producers are formatting messages in a somewhat sane way, and wrapping some tests around that stuff rather than having to have the worker work to hard to work out what it is getting. Having said that I don't feel overly strongly about the issue and am happy to add some option to flip the priority if we can think of a good name for it. |
I don't feel strongly about it, just wanted to call it out. What you've done is the hard part so it should be easy to extend it if that use case ever comes up. |
@jondot, @justin-yesware how do we feel about this now? Is this good enough or would you like me to explore some more ways of making it simpler to optionally include the feature... If you guys are happy, shall I squash my commits? |
Overall this looks great. Looking forward to picking this up next time we're writing json/thrift messages. One question about the default values in the |
TBH re It might be useful to add a guard condition like:
I am not sure if we should do some validation on the serializer/deserializer:
|
Those are all very good points. I asked because the method declaration has |
Maybe it could include a couple shortcuts for some common ones: ContentType.register_json
ContentType.register_xml |
Hey @jondot I noticed this PR has been rotting for a while, how do you feel about it? I am happy to do some more work on it or give up ? |
ping . . . . |
Hi @errm thanks for the wakeup call, I find that Github email notifications suck.. I must solve that some day. |
@errm I'm still very happy with this work!, let's get it merged. I'm working on a new documentation website, instead of the Wiki. Just so I know how to document this, what are the implicit things that happen here? For example, if I don't specify content_type at all - does it use json by default? (looks like it..?) |
@jondot Sounds great, give me a ping if you wan't me to help/read anything documentation wise. As far as what should happen implicitly - nothing. It's covered here: spec/sneakers/content_type_spec.rb:33. Basically internally the hash of ContentTypes is defaulted to a passthrough content type that has If you want to make use of this, it is required to explicitly register a content type, thus: Sneakers::ContentType.register(
content_type: 'application/json',
deserializer: ->(payload) { JSON.parse(payload) },
serializer: ->(payload) { JSON.dump(payload) },
) Are you still supporting ruby 2.0.x if not we can loose a lot of the cruft from |
72f94d7
to
e2a4cb6
Compare
registered yet.
I was not really happy that trying to short circuit and save a few method calls when the feature is not in use only to impact on the feature itself. This makes the whole thing a little more efficient by switching to attr_reader and imposes a constant cost whichever execution path is followed.
Short circuiting with a guard condition like this does not seem to impose any significant cost to the happy path.
e2a4cb6
to
a3b73be
Compare
ping ... rebased this again |
@jondot @gabrieljoelc do we have a consensus that this feature is worth including (worth the overhead, primarily)? I'm somewhat on the fence. |
@errm thank you for keeping this up-to-date. |
@michaelklishin do you have some specifics about your concerns? |
@gabrieljoelc I haven't noticed that the difference is for 10M iterations. So I guess this is good to go if we are willing to have this feature. @gabrieljoelc @jondot should I merge? |
@michaelklishin are you thinking that this should be in a separate extension library? |
@gabrieljoelc this can be part of Sneakers proper. |
@gabrieljoelc @jondot so, should we merge this? |
I approved it.
…On Mon, Mar 6, 2017, 2:36 PM Michael Klishin ***@***.***> wrote:
@gabrieljoelc <https://github.com/gabrieljoelc> @jondot
<https://github.com/jondot> so, should we merge this?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#152 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAJBiQrxgwONahvgtva2bIZPyQtsc9ebks5rjHxwgaJpZM4FvF67>
.
|
This is finally in. |
Ok so this is my second bash at one of the ideas mooted in #126.
This allows ContentTypes to be configured like so:
Then when messages arrive with the given content type metadata set the payload should be deserialized neatly.
Its also possible to add
content_type: 'whatever/thing'
to the worker options, in order that every message will be deserialized using the given type, irrespective of what the message metadata purports.The publishing methods now also use the serializers when
content_type
is present in the options.If nothing is registered everything just falls back to a noop pair of (de)serializers that just pass through the message unchanged, so this shouldn't break anyones existing applications.