forked from apache/helix
-
Notifications
You must be signed in to change notification settings - Fork 12
Planned-maintenance budget exemption for auto Maintenance Mode #175
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
Merged
Merged
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
fe18dec
Planned-maintenance budget exemption for auto Maintenance Mode
LZD-PratyushBhatt bd9025f
Route plannedMaintenance batch via Command dispatch
LZD-PratyushBhatt 754f85a
Apply PR feedback: simpler offline filter, inline sentinels, explicit…
LZD-PratyushBhatt a171476
plannedMaintenance batch: partial accept, matching stoppable contract
LZD-PratyushBhatt 2af726b
Trim PLANNED_MAINTENANCE_METADATA from change-detection snapshots
LZD-PratyushBhatt 942cbd6
Rename to INSTANCE_OPERATION_MAINTENANCE_*, drop audit metadata, vali…
LZD-PratyushBhatt 41c4db6
Fix filter-asymmetry comment: only EVACUATE differs, no SWAP_OUT
LZD-PratyushBhatt e100205
Drop EVACUATE asymmetry note from stage comments
LZD-PratyushBhatt f39176f
Address PR feedback: percentage range, single-endpoint error split, D…
LZD-PratyushBhatt File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -81,6 +81,20 @@ public enum ClusterConfigProperty { | |
| MAX_OFFLINE_INSTANCES_ALLOWED, | ||
| NUM_OFFLINE_INSTANCES_FOR_AUTO_EXIT, // For auto-exiting maintenance mode | ||
|
|
||
| // Instance-operation maintenance budget. Instances carrying a valid | ||
| // INSTANCE_OPERATION_MAINTENANCE_UNTIL_MS marker on their InstanceConfig are excluded | ||
| // from the MAX_OFFLINE_INSTANCES_ALLOWED count while the marker has not expired. | ||
| // | ||
| // The two fields below define the cap on simultaneous markers. They are mutually | ||
| // exclusive: setters reject writing one while the other is already set. -1 means the | ||
| // cap is not configured. | ||
| INSTANCE_OPERATION_MAINTENANCE_BUDGET, | ||
| INSTANCE_OPERATION_MAINTENANCE_BUDGET_PERCENTAGE, | ||
| // Fallback TTL (in millis) applied by the instance-operation maintenance write path | ||
| // when the caller omits expiresAtMillis. When unset (-1), callers must always supply an | ||
| // explicit expiresAtMillis; otherwise the write is rejected. | ||
| DEFAULT_INSTANCE_OPERATION_MAINTENANCE_DURATION_MS, | ||
|
|
||
| TARGET_EXTERNALVIEW_ENABLED, | ||
| @Deprecated // ERROR_OR_RECOVERY_PARTITION_THRESHOLD_FOR_LOAD_BALANCE will take | ||
| // precedence if it is set | ||
|
|
@@ -579,6 +593,88 @@ public int getMaxOfflineInstancesAllowed() { | |
| return _record.getIntField(ClusterConfigProperty.MAX_OFFLINE_INSTANCES_ALLOWED.name(), -1); | ||
| } | ||
|
|
||
| /** | ||
| * Set the absolute cap on the number of instances that may simultaneously carry an | ||
| * INSTANCE_OPERATION_MAINTENANCE_UNTIL_MS marker. Pass {@code -1} to clear; the field is | ||
| * mutually exclusive with {@link #setInstanceOperationMaintenanceBudgetPercentage(int)} | ||
| * and the setter throws when the other form is already set. | ||
| */ | ||
| public void setInstanceOperationMaintenanceBudget(int instanceOperationMaintenanceBudget) | ||
| throws HelixException { | ||
| if (instanceOperationMaintenanceBudget >= 0 | ||
| && getInstanceOperationMaintenanceBudgetPercentage() >= 0) { | ||
| throw new HelixException("INSTANCE_OPERATION_MAINTENANCE_BUDGET and " | ||
| + "INSTANCE_OPERATION_MAINTENANCE_BUDGET_PERCENTAGE are mutually exclusive; " | ||
| + "clear the percentage form before setting the absolute form."); | ||
| } | ||
| _record.setIntField(ClusterConfigProperty.INSTANCE_OPERATION_MAINTENANCE_BUDGET.name(), | ||
| instanceOperationMaintenanceBudget); | ||
| } | ||
|
|
||
| /** | ||
| * @return the configured absolute cap on instance-operation maintenance markers, or | ||
| * {@code -1} when not set. | ||
| */ | ||
| public int getInstanceOperationMaintenanceBudget() { | ||
| return _record.getIntField( | ||
| ClusterConfigProperty.INSTANCE_OPERATION_MAINTENANCE_BUDGET.name(), -1); | ||
| } | ||
|
|
||
| /** | ||
| * Set the percentage of cluster instances that may simultaneously carry an | ||
| * INSTANCE_OPERATION_MAINTENANCE_UNTIL_MS marker. Valid range is {@code [0, 100]}; pass | ||
| * {@code -1} to clear. The field is mutually exclusive with | ||
| * {@link #setInstanceOperationMaintenanceBudget(int)} and the setter throws when the | ||
| * other form is already set or the value is outside the valid range. | ||
| */ | ||
| public void setInstanceOperationMaintenanceBudgetPercentage( | ||
| int instanceOperationMaintenanceBudgetPercentage) throws HelixException { | ||
| if (instanceOperationMaintenanceBudgetPercentage < -1 | ||
| || instanceOperationMaintenanceBudgetPercentage > 100) { | ||
| throw new HelixException( | ||
| "INSTANCE_OPERATION_MAINTENANCE_BUDGET_PERCENTAGE must be in the range [0, 100] " | ||
| + "or -1 to clear, got " + instanceOperationMaintenanceBudgetPercentage); | ||
| } | ||
| if (instanceOperationMaintenanceBudgetPercentage >= 0 | ||
| && getInstanceOperationMaintenanceBudget() >= 0) { | ||
| throw new HelixException("INSTANCE_OPERATION_MAINTENANCE_BUDGET_PERCENTAGE and " | ||
| + "INSTANCE_OPERATION_MAINTENANCE_BUDGET are mutually exclusive; clear the " | ||
| + "absolute form before setting the percentage form."); | ||
| } | ||
| _record.setIntField( | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add validation to ensure % is between 0 and 100 here before writing.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
| ClusterConfigProperty.INSTANCE_OPERATION_MAINTENANCE_BUDGET_PERCENTAGE.name(), | ||
| instanceOperationMaintenanceBudgetPercentage); | ||
| } | ||
|
|
||
| /** | ||
| * @return the configured percentage cap on instance-operation maintenance markers, or | ||
| * {@code -1} when not set. | ||
| */ | ||
| public int getInstanceOperationMaintenanceBudgetPercentage() { | ||
| return _record.getIntField( | ||
| ClusterConfigProperty.INSTANCE_OPERATION_MAINTENANCE_BUDGET_PERCENTAGE.name(), -1); | ||
| } | ||
|
|
||
| /** | ||
| * Set the fallback duration (millis) applied by the instance-operation maintenance write | ||
| * path when the caller omits expiresAtMillis. Pass {@code -1L} to clear; when cleared, | ||
| * writes that omit expiresAtMillis are rejected. | ||
| */ | ||
| public void setDefaultInstanceOperationMaintenanceDurationMs( | ||
| long defaultInstanceOperationMaintenanceDurationMs) { | ||
| _record.setLongField( | ||
| ClusterConfigProperty.DEFAULT_INSTANCE_OPERATION_MAINTENANCE_DURATION_MS.name(), | ||
| defaultInstanceOperationMaintenanceDurationMs); | ||
| } | ||
|
|
||
| /** | ||
| * @return the configured fallback duration in millis, or {@code -1L} when not set. | ||
| */ | ||
| public long getDefaultInstanceOperationMaintenanceDurationMs() { | ||
| return _record.getLongField( | ||
| ClusterConfigProperty.DEFAULT_INSTANCE_OPERATION_MAINTENANCE_DURATION_MS.name(), -1L); | ||
| } | ||
|
|
||
| /** | ||
| * Sets the number of offline instances for auto-exit threshold so that MaintenanceRecoveryStage | ||
| * could use this number to determine whether the cluster could auto-exit maintenance mode. | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
69 changes: 69 additions & 0 deletions
69
...che/helix/controller/changedetector/trimmer/TestInstanceOperationMaintenanceTrimming.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
| package org.apache.helix.controller.changedetector.trimmer; | ||
|
|
||
| /* | ||
| * Licensed to the Apache Software Foundation (ASF) under one | ||
| * or more contributor license agreements. See the NOTICE file | ||
| * distributed with this work for additional information | ||
| * regarding copyright ownership. The ASF licenses this file | ||
| * to you under the Apache License, Version 2.0 (the | ||
| * "License"); you may not use this file except in compliance | ||
| * with the License. You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, | ||
| * software distributed under the License is distributed on an | ||
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| * KIND, either express or implied. See the License for the | ||
| * specific language governing permissions and limitations | ||
| * under the License. | ||
| */ | ||
|
|
||
| import org.apache.helix.model.ClusterConfig; | ||
| import org.apache.helix.model.ClusterConfig.ClusterConfigProperty; | ||
| import org.apache.helix.model.InstanceConfig; | ||
| import org.apache.helix.model.InstanceConfig.InstanceConfigProperty; | ||
| import org.testng.Assert; | ||
| import org.testng.annotations.Test; | ||
|
|
||
| /** | ||
| * Locks in the contract that instance-operation maintenance fields are non-topology and | ||
| * therefore trimmed before change-detection compares old vs new InstanceConfig/ClusterConfig | ||
| * snapshots. Marker writes must not trigger spurious rebalance pipeline runs. | ||
| */ | ||
| public class TestInstanceOperationMaintenanceTrimming { | ||
|
|
||
| @Test | ||
| public void testInstanceConfigMaintenanceUntilMsIsTrimmed() { | ||
| InstanceConfig original = new InstanceConfig("h1"); | ||
| original.setHostName("host"); | ||
| original.setPort("1234"); | ||
| original.setInstanceOperationMaintenanceUntilMs(System.currentTimeMillis() + 60_000L); | ||
|
|
||
| InstanceConfig trimmed = InstanceConfigTrimmer.getInstance().trimProperty(original); | ||
|
|
||
| Assert.assertFalse(trimmed.getRecord().getSimpleFields().containsKey( | ||
| InstanceConfigProperty.INSTANCE_OPERATION_MAINTENANCE_UNTIL_MS.name()), | ||
| "INSTANCE_OPERATION_MAINTENANCE_UNTIL_MS must be trimmed from change-detection " | ||
| + "snapshots so marker writes do not trigger rebalance"); | ||
| Assert.assertTrue(trimmed.getRecord().getSimpleFields() | ||
| .containsKey(InstanceConfigProperty.HELIX_HOST.name()), | ||
| "Sanity: topology-relevant fields are still preserved through the trimmer"); | ||
| } | ||
|
|
||
| @Test | ||
| public void testClusterConfigInstanceOperationMaintenanceFieldsAreTrimmed() throws Exception { | ||
| ClusterConfig original = new ClusterConfig("c"); | ||
| original.setInstanceOperationMaintenanceBudget(20); | ||
| original.setDefaultInstanceOperationMaintenanceDurationMs(3_600_000L); | ||
|
|
||
| ClusterConfig trimmed = ClusterConfigTrimmer.getInstance().trimProperty(original); | ||
|
|
||
| Assert.assertFalse(trimmed.getRecord().getSimpleFields().containsKey( | ||
| ClusterConfigProperty.INSTANCE_OPERATION_MAINTENANCE_BUDGET.name())); | ||
| Assert.assertFalse(trimmed.getRecord().getSimpleFields().containsKey( | ||
| ClusterConfigProperty.INSTANCE_OPERATION_MAINTENANCE_BUDGET_PERCENTAGE.name())); | ||
| Assert.assertFalse(trimmed.getRecord().getSimpleFields().containsKey( | ||
| ClusterConfigProperty.DEFAULT_INSTANCE_OPERATION_MAINTENANCE_DURATION_MS.name())); | ||
| } | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Base is different from baseline, doesn't have evacuation here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pre existing from long back, will revisit in a different PR