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

Add proto config for all filters #193

Merged
merged 3 commits into from
Feb 20, 2021
Merged

Add proto config for all filters #193

merged 3 commits into from
Feb 20, 2021

Conversation

iffyio
Copy link
Collaborator

@iffyio iffyio commented Feb 15, 2021

work on #10

@@ -0,0 +1,15 @@
syntax = "proto2";
Copy link
Member

Choose a reason for hiding this comment

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

This should be proto3.

I'm not sure you can even use proto2 in grpc? 🤔 (apparently you can)

I'm guessing you did this because you can then use "optional" ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I started out with proto3 yeah it was in order to use optional. For the protoc compiler to generate optional types with proto3 it required --experimental_allow_proto3_optional to be passed in, but when I passed that into prost it panicked so I switched to proto2. If we would rather use proto3 we would probably need some workaround for optional things?

Copy link
Member

Choose a reason for hiding this comment

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

So what I noticed from your previous example:
https://github.com/googleforgames/quilkin/blob/main/proto/quilkin/extensions/filters/debug/v1alpha1/debug.proto

If you use the wrapper type, it will generate a Option<String> for the Google imported managed types.

If you write your own wrapper type, (if I'm remembering correctly), you get something akin to Option<Wrapper>, which has the type you want in it - which is a bit more unwieldy, since you need to go option.unwrap().value to get to the underlying value you want, but it is still possible to be used.

SO post saying the same thing:
https://stackoverflow.com/a/50099927

But also, looking at this specific example, only strategy and remove have default values - everything else is required, so and doesn't have to be optional.

On top of that, I think we can leverage proto3 defaulting to our advantage slightly here too.

For enums, the first value is the default, so if we make SUFFIX the first value (0), then we are good to go, and for bools, the default value is false, so we also don't need optional for that.

We can likely apply this to the other configs as well. WDYT?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

If you use the wrapper type, it will generate a Option for the Google imported managed types.

right, also used the google types initially, what I didn't get was how I could do my own optional types like Option. tried tracing through their protos to see if I could figure it out but got lost along the way :P

But also, looking at this specific example, only strategy and remove have default values - everything else is required, so and doesn't have to be optional.

yeah not sure why they're optional, will fix

On top of that, I think we can leverage proto3 defaulting to our advantage slightly here too.

thought about this but felt it merely complicates thing further (and protobuf is already too complicated I'm finding out), didn't like that ordering would matter like that in the config for enums and e.g if default for bools is true instead we become inconsistent would rather not go that route, especially since it doesn't solve the optional problem, would rather mark optional things as optional.

Copy link
Member

Choose a reason for hiding this comment

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

right, also used the google types initially, what I didn't get was how I could do my own optional types like Option. tried tracing through their protos to see if I could figure it out but got lost along the way :P

I traced the code - prost does handle the Google basic data types in a "special" way (it removes the wrapper and makes an Option<type> rather that Option<Wrapper> where the Wrapper has a value member, but you still get an Option for a value if you have your own wrapper.

So if we decide Strategy should be optional, you could do the following (written off the top of my head, so may have a couple of issue):

message CaptureBytes {
  enum StrategyEnum {
    Prefix = 0;
    Suffix = 1;
  }
  
  message Strategy {
     value StrategyEnum = 1;
  }

  Strategy strategy = 1;
  int32 size = 2;
  string metadata_key = 3;
  bool remove = 4;
}

And then the generated code is for the Strategy value will be optional out of prost (and other languages).

Re: protobuf defaulting - yeah, there's a tradeoff. Ordering in protobuf matters regardless - i.e. you can't change the numbers of variables set. At some point we'll have to handle protobuf defaulting of values somewhere - but I agree, for something like a bool, it would be weird that some boolean values were wrapped and other's weren't. So consistency is definitely a good thing 👍 and we should be consistent in our approach (so let's wrap all default values, makes sense to me).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

this isn't what we want either though, the above generates an option separate from the enum rather than simply option which is cumbersome with an extra layer of indirection

Copy link
Member

@markmandel markmandel Feb 19, 2021

Choose a reason for hiding this comment

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

Ideally yes, Option<StrategyEnum> would be than nicer Option<StrategyWrapper> but I think that's just the best we're going to get out of proto3 output. It's a pretty standard pattern with proto3 (hence there are standard Google wrappers for basic values).

It's a bit cumbersome on the Rust side, but it's not blocking to use. Also, we're taking that prost model and converting it into the Serde hand written model almost immediately in the code - so 99% of the time we won't be interacting with the prost generated much throughout when implementing features in a Filter -- so not seeing it as a large concern.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

updated ptal!

Copy link
Member

@markmandel markmandel left a comment

Choose a reason for hiding this comment

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

Just one question about spacing. But that's all I have. I'll make it approved, so you can merge when ready.

}

StrategyValue strategy = 1;
uint32 size = 2;
Copy link
Member

Choose a reason for hiding this comment

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

Today I learned uint32 is a proto3 data type!

src/extensions/filters/mod.rs Show resolved Hide resolved
@iffyio iffyio merged commit d5bf22a into main Feb 20, 2021
@iffyio iffyio deleted the iu/filter-proto-configs branch February 20, 2021 13:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants