3 ms·
I think the key words here are "distributed system". Just because HEAD has the new enum used everywhere doesn't mean all the deployed code everywhere can handl
by Tyr42 6y ago
I think the key words here are "distributed system". Just because HEAD has the new enum used everywhere doesn't mean all the deployed code everywhere can handle the new enum value.
Imagine you have two servers communicating with
enum Packet {
Ping,
Pong,
}
Where the semantics are that if you receive a ping, you say pong, and if you see pong, you say ping.
Suppose we deploy this out to several servers, with code built on 2020-7-12. Now on 2020-07-13 you commit to head a new enum value `Stats`, which returns a new kind of reply.
If you send outgoing requests in the same 2020-07-13 build, you're going to have a bad time, as your fleet is going to start at 100% 2020-07-12 and switch over to 100% 2020-07-13, but during that switch you'll have some 50% 50% split. If a new server sends a request to an old one, you'll have a crash.
Instead you have to add receivers in 2020-07-13, but not use it yet. Roll it out, make sure it's past how far you might roll back, then you can deploy a 2020-07-20 build which makes calls using the new enum.
If you skip that step, you're going to have a bad time. Maybe you want to instead have a default case handler instead of crashing, but that means each of your enums has to know about "UNKNOWN" and you're deserialization error has to be future proof.
- woah 6y agoAny time you break an API that accepts serialized data it's going to crash if you try to use it with something that is on a different version of the API. How is this any different with enums than it would be with changing a string to a float, or anything else?
- zenhack 6y agoRelated, capnproto has a corresponding feature (which it calls unions), but being a dsl for defining _protocols_, you obviously have to deal with the possibility of introducing new variants as the protocol evolves. I wrote the Haskell implementation. It maps unions to variants (what Rust calls enums), BUT it always generates an extra 'unkown' variant, which gets used whenever the variant is one not recognized by the generated code. In this case the value proposition of variants/enums, including exhaustiveness checking, is still really useful -- it can not only deal with the possibility of more variants added in the future, it forces you to handle that possibility, which imo is the best of both worlds. But yes, in general, when modeling data that comes from the outside world, you need to about overfitting. Vaguely related: https://lexi-lambda.github.io/blog/2020/01/19/no-dynamic-type-systems-are-not-inherently-more-open/ https://lexi-lambda.github.io/blog/2020/01/19/no-dynamic-typ...