-
Notifications
You must be signed in to change notification settings - Fork 21
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
Include milliseconds when serializing ActiveSupport::TimeWithZone to JSON #99
base: main
Are you sure you want to change the base?
Conversation
Rails 4.1 introduced a time_precision configuration that defaults to 3, but this invocation of iso8601 doesn't include any sub-second precision. See ActiveSupport.time_precision or config.active_support.time_precision in: https://guides.rubyonrails.org/configuring.html#configuring-active-support
What versions of Rails are we supporting with this library? The gem spec denotes any version of Rails: Line 21 in 6737805
|
If we're especially concerned about supporting Rails 4.0 or older, we could add a guard to protect against calling this method at runtime if it doesn't exist. |
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.
This seems pretty straightforward and helpful.
The build matrix goes back to Rails 5.2 and is passing, so I'd assume that's the limit of support. Ruby 2.7 and Rails 5.2 |
@@ -3,7 +3,7 @@ | |||
class ActiveSupport::TimeWithZone | |||
# We want dates to be a) in UTC and b) in ISO8601 always | |||
def as_json(options = {}) | |||
utc.iso8601 | |||
utc.iso8601(ActiveSupport.time_precision) |
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.
An alternate implementation could be this, which I'm leaning toward.
def as_json(options = nil)
if utc?
super
else
utc.as_json(options)
end
end
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.
Here's the latest Rails implementation of TimeWithZone#as_json
for reference, which we could mimic as well.
def as_json(options = nil)
if ActiveSupport::JSON::Encoding.use_standard_json_time_format
xmlschema(ActiveSupport::JSON::Encoding.time_precision)
else
%(#{time.strftime("%Y/%m/%d %H:%M:%S")} #{formatted_offset(false)})
end
end
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.
What I'm wondering about is, what was this little patch meant to accomplish? Forcing the timezone or the serialization format?
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.
Also, is there any reason now that we can't just rely on Rails' behavior?
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.
Blocking the merge until @zorab47 and I can connect offline.
@brettfishman and I connected to discuss this change. I will first test out this functionality in a release candidate before merging it into the main branch. |
Earlier versions of Rails didn't use ISO8601, but it has become the standard encoding for Rails versions supported by this gem.
The default `rake release` applies tags with a "v" (e.g. v4.1.0)
This reverts commit 50e73ea.
What versions? I'm wondering if this should be represented by logic that switches behavior based on version? But maybe not... This needs a test. |
@soulcutter recent here means Rails 4.1 and newer; milliseconds were introduced in rails/rails#9128 in 2013. It isn't explicitly stated in Stitches, but the build matrix only tests against Rails 5.2 and newer right now. That leads me to assume only 5.2 and newer are supported. |
One potential issue is that our existing guidelines in the eng-wiki forbid this, and there are programmatic checks in some parts of the system at least to forbid this. I would suggest if moving forward that it be done in the following steps:
That sounds like a lot, I deeply feel how painful that would be, but I think that would be the safe way to do this. |
Hi, Micah, I just wanted to acknowledge the care you put into making sure this is the right solution for our problem. I'd also like to respond some specific points you make.
There is an interesting, strange thing here. Many services already do send millisecond precision for these timestamps. No idea why or what the difference is.
You are completely correct that times (especially fractions of a second) will often be out of sync across various systems. However, the messages emitted by one system would usually have monotonically increasing timestamps. (This is ignoring an enormous number of other factors, obvs, but those cases are usually negligible.) So it wouldn't be for naught. In other words, I agree with you, but wanted to add this.
Thanks again for carefully articulating this. I agree with what you've stated here. |
Problem
Stitches overrides the
to_json
method on ActiveSupport::TimeWithZone objects but doesn't include sub-second precision even though that is the default in recent versions of Rails.In many Stitch Fix apps, timestamps with timezone information is being serialized without millisecond precision which impacts messages sent through our messaging infrastructure. Specifically, the recent call-out was for shipment events being sent within the same second, but received out of order without a way of sorting the events (Slack).
The override of
to_json
also impacts the encoding of timestamps likecreated_at
andupdated_at
returned in other contexts (JSON in messages).Solution
Rails 4.1 introduced a time_precision configuration that defaults to 3, but this invocation of iso8601 doesn't include any sub-second precision.
PR: rails/rails#9128
See ActiveSupport.time_precision or config.active_support.time_precision in: https://guides.rubyonrails.org/configuring.html#configuring-active-support