Protocol Buffers - Google's data interchange format (grpc依赖)
https://developers.google.com/protocol-buffers/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
139 lines
4.7 KiB
139 lines
4.7 KiB
# Minimum Required Edition |
|
|
|
**Author:** [@mcy](https://github.com/mcy) |
|
|
|
**Approved:** 2022-11-15 |
|
|
|
A versioning mechanism for descriptors that ensures old runtimes do not load |
|
descriptors that are "too new." |
|
|
|
## Background |
|
|
|
Suppose we decide to add a novel definition like |
|
|
|
``` |
|
const int32 MY_CONSTANT = 42; |
|
``` |
|
|
|
to the Protobuf language. This would entail a descriptor change to track the |
|
values of constants, but they would not be loaded properly by older runtimes. |
|
This document describes an addition to `descriptor.proto` that prevents this |
|
version mismatch issue. |
|
|
|
[Protobuf Editions](what-are-protobuf-editions.md) intends to add the concept of |
|
an edition to Protobuf, which will be an approximately-annually incrementing |
|
value. Because of their annual nature, and because runtimes need to be updated |
|
to handle new features they implement regardless, we can use them as a poison |
|
pill for old runtimes that try to load descriptors that are "too new." |
|
|
|
## Overview |
|
|
|
We propose adding a new field to `FileDescriptorProto`: |
|
|
|
``` |
|
optional string minimum_required_edition = ...; |
|
``` |
|
|
|
This field would exist alongside the `edition` field, and would have the |
|
following semantics: |
|
|
|
Every Protobuf runtime implementation must specify the newest edition whose |
|
constructs it can handle (at a particular rev of that implementation). If that |
|
edition is less than `minimum_required_edition`, loading the descriptor must |
|
fail. |
|
|
|
"Less than" is defined per the edition total order given in |
|
[Life of an Edition](life-of-an-edition.md). To restate it, it is the following |
|
algorithm: |
|
|
|
``` |
|
def edition_less_than(a, b): |
|
parts_a = a.split(".") |
|
parts_b = b.split(".") |
|
for i in range(0, min(len(parts_a), len(parts_b))): |
|
if int(parts_a[i]) < int(parts_b[i]): return True |
|
return len(a) < len(b) |
|
``` |
|
|
|
`protoc` should keep track of which constructions require which minimum edition. |
|
For example, if constants are introduced in edition 2025, but they are not |
|
present in a file, `protoc` should not require that runtimes understand |
|
constants by picking a lower edition, like 2023 (assuming no other construct |
|
requires a higher edition). |
|
|
|
In particular, the following changes should keep the minimum edition constant, |
|
with all other things unchanged: |
|
|
|
* An upgrade of the proto compiler. |
|
* Upgrading the specified edition of a file via Prototiller. |
|
|
|
### Bootstrapping Concerns |
|
|
|
"Epochs for `descriptor.proto`" (not available externally) describes a potential |
|
issue with bootstrapping. It is not the case here: minimum edition is only |
|
incremented once a particular file uses a new feature. Since `descriptor.proto` |
|
and other schemas used by `protoc` and the backends would not use new features |
|
immediately, introducing a new feature does not immediately stop the compiler |
|
from being able to compile itself. |
|
|
|
### Concerns for Schema Producers |
|
|
|
Schema producers should consider changes to their schemas that increase the |
|
minimum required edition to be breaking changes, since it will stop compiled |
|
descriptors from being loaded at runtime. |
|
|
|
## Recommendation |
|
|
|
We recommend adding the aforementioned minimum required edition field, along |
|
with the semantics it entails. This logic should be implemented entirely in the |
|
protoc frontend. |
|
|
|
## Alternatives |
|
|
|
### Use a Non-Editions Version Number |
|
|
|
Rather than using the editions value, use some other version number. This number |
|
would be incremented rarely (3-5 year horizon). This is the approach proposed |
|
in "Epochs for `descriptor.proto`." |
|
|
|
#### Pros |
|
|
|
* Does not re-use the editions value for a semantically-different meaning; the |
|
edition remains being "just" a key into a table of features defaults. |
|
|
|
#### Cons |
|
|
|
* Introduces another version number to Protobuf that increments at its own |
|
cadence. |
|
* Could potentially be confused with the edition value, even though they serve |
|
distinct purposes. |
|
|
|
### Minimum Required Edition Should Not Be Minimal |
|
|
|
The proto compiler should not guarantee that the minimum required edition is as |
|
small as it could possibly be. |
|
|
|
#### Pros |
|
|
|
* Reduces implementation burden. |
|
|
|
#### Cons |
|
|
|
* This introduces situations where an upgrade of the proto compiler, or an |
|
innocuous change to a schema, can lead the the minimum required edition |
|
being incremented. This is a problem for schema producers. |
|
|
|
### Do Nothing |
|
|
|
#### Pros |
|
|
|
* Reduces churn in runtimes, since they do not need to implement new handling |
|
for new *editions* (as contrasted to just *features)* regularly. |
|
* Avoids a situation where old software cannot load new descriptors at |
|
runtime. |
|
|
|
#### Cons |
|
|
|
* Commits us to never changing the descriptor wire format in |
|
backwards-incompatible ways, which has far-reaching effects on evolution. |
|
These consequences are discussed in "Epochs for `descriptor.proto`."
|
|
|