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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

serde: support variant #17537

Merged
merged 1 commit into from
Apr 9, 2024
Merged

serde: support variant #17537

merged 1 commit into from
Apr 9, 2024

Conversation

rockwotj
Copy link
Contributor

@rockwotj rockwotj commented Apr 1, 2024

I have an upcoming change to add a variant for a serde transforms
struct, so I am in advance sending out this change to support variant in
serde.

Variants are tricky w.r.t. compatibility, they are forward compatible if new
discriminants are appended to the variant.

Concretely that means that you can only read old versions of a variant if new
options are appended. Writing a new variant option should happen with a
feature barrier, so that an older reader will never read a newly written
variant.

This works by creating a compile time lookup table of variant index ->
a lambda that creates the variant for the type at the given index. Then
we do a runtime dispatch to the static function based on the index of
the function (with a bounds check).

The stuff you can do with templates are 馃く

Related: #17370

Backports Required

  • none - not a bug fix
  • none - this is a backport
  • none - issue does not exist in previous branches
  • none - papercut/not impactful enough to backport
  • v23.3.x
  • v23.2.x

Release Notes

  • none

@rockwotj rockwotj force-pushed the variant_serde branch 3 times, most recently from 609723f to 255c264 Compare April 2, 2024 00:44
@rockwotj rockwotj self-assigned this Apr 2, 2024
@andijcr
Copy link
Contributor

andijcr commented Apr 2, 2024

I like the implementation; maybe this could accept only some sort of blessed variant, like (just an idea) a trait to specialize

// header
namespace serde {
template<typename>
constexpr static auto is_blessed_variant = false;
}

// when declaring the variant
namespace serde{
template <>
constexpr static auto is_blessed_variant<std::variant<model::offset, model::revision_id>> = true;
}

or a wrapper carrier type, like

namespace serde{
template<typename ...Ts>
 struct variant {
    std::variant<Ts...> data;
 };

but both options carry some burden on the user

src/v/serde/rw/variant.h Outdated Show resolved Hide resolved
src/v/serde/rw/variant.h Outdated Show resolved Hide resolved
@rockwotj rockwotj force-pushed the variant_serde branch 2 times, most recently from fc98d8a to df56fbd Compare April 3, 2024 01:09
@rockwotj
Copy link
Contributor Author

rockwotj commented Apr 3, 2024

Force pushes: review feedback

@rockwotj
Copy link
Contributor Author

rockwotj commented Apr 3, 2024

I like the implementation; maybe this could accept only some sort of blessed variant, like (just an idea) a trait to specialize

I created a transparent wrapper - I believe this works as expected, but would love a second pair of eyes, because this feels a bit like magic at this point... 馃槅

@rockwotj rockwotj requested a review from andijcr April 3, 2024 01:10
@rockwotj rockwotj requested review from BenPope and a team as code owners April 3, 2024 02:32
@rockwotj rockwotj requested review from rpdevmp and removed request for a team April 3, 2024 02:32
@rockwotj
Copy link
Contributor Author

rockwotj commented Apr 3, 2024

Force push: assert that std::variant doesn't work with serde but serde::variant does

andijcr
andijcr previously approved these changes Apr 3, 2024
Copy link
Contributor

@andijcr andijcr left a comment

Choose a reason for hiding this comment

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

lgtm, left some nonblocking comments

I'd wait for a second approval since this involves serde

src/v/serde/rw/variant.h Outdated Show resolved Hide resolved
src/v/serde/rw/variant.h Outdated Show resolved Hide resolved
src/v/serde/test/serde_test.cc Show resolved Hide resolved
Copy link
Member

@BenPope BenPope left a comment

Choose a reason for hiding this comment

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

Very cool

src/v/serde/rw/variant.h Outdated Show resolved Hide resolved
src/v/serde/rw/variant.h Outdated Show resolved Hide resolved
@rockwotj
Copy link
Contributor Author

rockwotj commented Apr 3, 2024

Force push: added more tests showing compatibility and addressing other review feedback. Thanks!

@rockwotj
Copy link
Contributor Author

rockwotj commented Apr 3, 2024

Force push: fix noexcept

BenPope
BenPope previously approved these changes Apr 3, 2024
Copy link
Member

@BenPope BenPope left a comment

Choose a reason for hiding this comment

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

Neat

src/v/serde/rw/variant.h Outdated Show resolved Hide resolved
src/v/serde/rw/variant.h Outdated Show resolved Hide resolved
@rockwotj
Copy link
Contributor Author

rockwotj commented Apr 3, 2024

Force pushes: Review feedback about noexcept

};

SEASTAR_THREAD_TEST_CASE(variant) {
using my_variant = serde::variant<ss::sstring, int, bool, my_enum, int>;
Copy link
Member

Choose a reason for hiding this comment

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

how about a test case that uses std::monostate?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

std::monostate is not supported by serde, should I add support for it?

src/v/serde/test/serde_test.cc Show resolved Hide resolved
src/v/serde/rw/variant.h Outdated Show resolved Hide resolved
@rockwotj
Copy link
Contributor Author

rockwotj commented Apr 5, 2024

ping here, the stacked PR for this is ready. I can either drop this and manually implement this pattern using custom serde or go forward with this approach. I am ambivalent

@rpdevmp rpdevmp removed their request for review April 9, 2024 01:56
dotnwat
dotnwat previously approved these changes Apr 9, 2024
I have an upcoming change to add a variant for a serde transforms
struct, so I am in advance sending out this change to support variant in
serde.

Backwards compat: See the comment on serde::variant, but any
additions/changes to the types in the variant are not backwards or
forward compatible, so we need to handle this in some wrapper struct.

This works by creating a compile time lookup table of variant index ->
a lambda that creates the variant for the type at the given index. Then
we do a runtime dispatch to the static function based on the index of
the function (with a bounds check).

The stuff you can do with templates are 馃く

Signed-off-by: Tyler Rockwood <rockwood@redpanda.com>
@rockwotj
Copy link
Contributor Author

rockwotj commented Apr 9, 2024

Force pushes: more strict backwards compat

@vbotbuildovich
Copy link
Collaborator

new failures in https://buildkite.com/redpanda/redpanda/builds/47573#018ec3ef-e147-4825-9d82-03192ed6b89b:

"rptest.tests.cloud_retention_test.CloudRetentionTimelyGCTest.test_retention_with_node_failures.cloud_storage_type=CloudStorageType.ABS"

@rockwotj rockwotj merged commit 465118e into redpanda-data:dev Apr 9, 2024
14 of 17 checks passed
@rockwotj rockwotj deleted the variant_serde branch April 9, 2024 22:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants