Status
Current state: "Under Discussion"
Discussion thread: here
JIRA: KAFKA-15922
Please keep the discussion on the mailing list rather than commenting on the wiki (wiki discussions get unwieldy fast).
Motivation
Apache Kafka is a very actively developed project. Each new release adds several new features. Most of these features are too big to be done as a single large pull request. This creaates a dilemma: we want to get in the feature, but in the time between the first git commit and the last git commit, the feature will be in a partially completed state. While in this state, we may make incompatible changes to RPCs or metadata records.
What we would like to do is make it easier to develop new features, while shielding end-users from disruption. So we are introducing the concept of an "unstable feature."
An unstable feature:
- Exists in the code, and can be tested by JUnit and JMH tests
- Is hidden from end-users.
- Makes no compatibility guarantees: it can be changed or removed by developers at any time.
Public Interfaces
New Configuration
There will be a new internal configuration named unstable.features.enable
which will default to false. This configuration will only be possible to set for JUnit tests. It will not be possible to set this configuration to true when running a broker or controller as a standalone process.
This configuration will enable all unstable features, including:
- Unstable RPC versions
- Unstable MetadataVersions
- Unstable versions of other KIP-584 features
The following internal configurations will be removed:
- unstable.api.versions.enable
- unstable.feature.versions.enable
The new configuration will basically be equivalent to setting both of these previous configurations to true.
Proposed Changes
RPC Changes
Optionally, request RPCs may include this line:
"latestVersionUnstable": true,
This indicates that the latest version of the RPC is considered to be unstable. It will not be used unless unstable.features.enable
is set to true.
An unstable RPC version can be changed at any time, until it becomes stable.
Metadata Version Changes
In the MetadataVersion.java class, there will be an enum named LATEST_PRODUCTION which points to the latest stable metadata version. All MetadataVersions that come after this will be considered unstable.
Unstable MetadataVersions can be changed or deleted at any time. There is no need to "preserve" unstable MetadataVersions that were used in the past but that were later deleted or folded into a different MV: a lack of stability means there are no guarantees.
Clusters can be created with unstable MVs, but only in JUnit tests. As specified above, the broker and controller, when running as standalone processes, cannot use unstable features, including unstable MetadataVersions.
Brokers and controllers will not advertise support for unstable MVs (unless unstable.features.enable
is set), and command-line tools will not mention their existence.
Note that there are still cases where the MetadataVersion maps directly to an RPC version. For example, the broker still uses MV to determine which FetchRequest version to use for replication. In this case, it is an error for a stable MetadataVersion to map to an unstable RPC version. This error will quickly be caught by testing.
When parsing MetadataVersion strings, we will always assume that we are being given a stable MV unless otherwise specified. For example, if 3.7-IV4 is unstable, and we are given the string "3.7", we will map the string to 3.7-IV3. On the other hand, if we are given the string "3.7-IV4", we must parse it as 3.7-IV4 (there is no other option.)
This also implies that if there are no stable MVs for a release, parsing will fail. For example, if 3.8-IV0 is unstable, we will not be able to parse the string "3.8". But we will be able to parse "3.8-IV0" as intended.
Prior to a release, all MetadataVersions for that release must be stable.
Other KIP-584 Features
Similar to MetadataVersion, other KIP-584 features may choose to hide themselves unless unstable.features.enable
is set to true. While hidden, they will not be advertised by stable brokers and controllers, or accessible to users.
Compatibility, Deprecation, and Migration Plan
For the most part, this KIP codifies what we have already been doing. The main change is that we currently have both an "unstable.api.versions.enable" configuration, and an "unstable.feature.versions.enable" configuration which do a subset of what the proposed "unstable.features.enable" configuration described here does. However, since these configurations are internal, and were never documented or exposed to end-users, removing them is not an issue.
Rejected Alternatives
Develop in Branches
Doing all feature development in branches would alleviate the concerns here about dealing with partially completed features in trunk, without the need for unstable features.
However, moving feature development work into branches is difficult. While working in a branch, you are not exposed to how your new feature will interact with other features that are being developed concurrently. This creates a blind spot that will have to be remedied when the feature is ready to merge. (Or, if you choose to periodically merge trunk into your branch, it creates a continuous stream of merge work.) More generally, merging a big feature to trunk tends to create a big diff, which people would rather not review. For these reasons, we tend to reserve feature branches for truly huge features, not everyday ones.
Back Out Partially Completed Features Before Releases
If you assume that trunk is just always unstable, but completed releases are stable, you can make the system work by backing out all the half-completed stuff after the release branch has been created. While we have done a lot of this in the past, it is both labor-intensive and error-prone. And it also heavily discourages people from deploying from trunk, which seems unfortunate.
Having a system for managing unstable features removes this burden from the release manager, since unstable stuff can exist in the code without being exposed to end-users. It allows the developers of features, who are best positioned to know when a feature is stable, to mark it as such in the code itself.
While the release manager will no doubt want to check on the status of features, this KIP will lift a lot of the burden of doing large numbers of git revert operations and branch cleanups.