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

Introduce type for Unix timestamps in JSON #6883

Merged
merged 6 commits into from
Dec 12, 2023
Merged

Conversation

pstibrany
Copy link
Member

What this PR does

This PR shows how we could replace int64 fields in our JSON structs that we use for storing Unix timestamps with typed field.

Benefit is stronger typing and fewer ad-hoc conversions between units.

In this PR I've modified tenant deletion marks only to use this format, but there are other fields (deletion marker, no compact marker, bucket index) where we could use this.

Which issue(s) this PR fixes or relates to

Inspired by changes in #6848.

Checklist

  • Tests updated.
  • [na] Documentation added.
  • [na] CHANGELOG.md updated - the order of entries should be [CHANGE], [FEATURE], [ENHANCEMENT], [BUGFIX].
  • [na] about-versioning.md updated with experimental features.

Signed-off-by: Peter Štibraný <pstibrany@gmail.com>
Signed-off-by: Peter Štibraný <pstibrany@gmail.com>
Copy link
Contributor

@dimitarvdimitrov dimitarvdimitrov left a comment

Choose a reason for hiding this comment

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

nicely done, left only a single question

pkg/util/time.go Outdated
}
switch {
case i == 0:
*t = JSONSecondsTimestamp(time.Time{})
Copy link
Contributor

Choose a reason for hiding this comment

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

isn't i==0 equivalent to time.Unix(0, 0)?

Copy link
Member Author

Choose a reason for hiding this comment

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

Unfortunately not.

  • time.Unix(0, 0) is 1970-01-01 00:00:00 +0000 UTC.
  • time.Time{} is 0001-01-01 00:00:00 +0000 UTC

Copy link
Contributor

Choose a reason for hiding this comment

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

so if the json doc contains "time": 0 we treat this as 0001-01-01, but it could have been intended as 1970-01-01 (which is also valid)

Copy link
Contributor

Choose a reason for hiding this comment

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

and also now the code changes what it receives

0001-01-01 --unmarshal--> 0 --marshal--> 1970-01-01

it started with one date, but ended up with another

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, you're correct and your examples are valid. Given the special nature of both values, I don't think this is a showstopper though.

pkg/util/time.go Outdated Show resolved Hide resolved
Signed-off-by: Peter Štibraný <pstibrany@gmail.com>
@pstibrany
Copy link
Member Author

pstibrany commented Dec 11, 2023

Negative of this approach is that omitempty no longer works on the field. That can only be solved my making the field a pointer (omitempty only works with numbers, bools, pointers, nil-interface, arrays, slices, maps and strings. Not custom type 😞).

That's disappointing.

I've marked this PR as draft for this reason.

@pstibrany pstibrany marked this pull request as draft December 11, 2023 12:07
Signed-off-by: Peter Štibraný <pstibrany@gmail.com>
@pstibrany
Copy link
Member Author

I've updated the PR, now the type is just:

type UnixSeconds int64

This works with omitempty, doesn't need custom serialization and avoids special 0 values mapping.

Signed-off-by: Peter Štibraný <pstibrany@gmail.com>
@pstibrany pstibrany marked this pull request as ready for review December 12, 2023 09:51
Copy link
Contributor

@dimitarvdimitrov dimitarvdimitrov left a comment

Choose a reason for hiding this comment

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

nice, LGTM

t.Run(tc.json, func(t *testing.T) {
out, err := json.Marshal(tc.obj)
require.NoError(t, err)
require.Equal(t, tc.json, string(out))
Copy link
Contributor

Choose a reason for hiding this comment

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

there's require.JSONEq which is less flaky

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks, that's useful.

Signed-off-by: Peter Štibraný <pstibrany@gmail.com>
@pstibrany pstibrany enabled auto-merge (squash) December 12, 2023 14:18
@pstibrany pstibrany merged commit ea234b2 into main Dec 12, 2023
28 checks passed
@pstibrany pstibrany deleted the json-seconds-timestamp branch December 12, 2023 14:31
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