Skip to content

Commit 689d628

Browse files
authored
move phase-after steps to have the previous phase's phase in its key (elastic#4387)
Previously, phase X's `after` step had `X` as its associated phase. This causes confusion because we have only entered phase `X` once the `after` step is complete. Therefore, this refactor pushes the after's phase to be associated with the previous phase. This first phase is an exception. The first phase's `after` step is associated with the first phase (not some non-existent prior phase).
1 parent d509834 commit 689d628

File tree

3 files changed

+78
-21
lines changed

3 files changed

+78
-21
lines changed

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/InitializePolicyContextStep.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import org.elasticsearch.index.Index;
1313

1414
public class InitializePolicyContextStep extends Step {
15+
public static final StepKey KEY = new StepKey("pre-phase", "pre-action", "init");
1516

1617
public InitializePolicyContextStep(Step.StepKey key, StepKey nextStepKey) {
1718
super(key, nextStepKey);

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/LifecyclePolicy.java

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,32 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
139139
return builder;
140140
}
141141

142+
/**
143+
* This method is used to compile this policy into its execution plan built out
144+
* of {@link Step} instances. The order of the {@link Phase}s and {@link LifecycleAction}s is
145+
* determined by the {@link LifecycleType} associated with this policy.
146+
*
147+
* The order of the policy will have this structure:
148+
*
149+
* - initialize policy context step
150+
* - phase-1 phase-after-step
151+
* - ... phase-1 action steps
152+
* - phase-2 phase-after-step
153+
* - ...
154+
* - terminal policy step
155+
*
156+
* We first initialize the policy's context and ensure that the index has proper settings set.
157+
* Then we begin each phase's after-step along with all its actions as steps. Finally, we have
158+
* a terminal step to inform us that this policy's steps are all complete. Each phase's `after`
159+
* step is associated with the previous phase's phase. For example, the warm phase's `after` is
160+
* associated with the hot phase so that it is clear that we haven't stepped into the warm phase
161+
* just yet (until this step is complete).
162+
*
163+
* @param client The Elasticsearch Client to use during execution of {@link AsyncActionStep}
164+
* and {@link AsyncWaitStep} steps.
165+
* @param nowSupplier The supplier of the current time for {@link PhaseAfterStep} steps.
166+
* @return The list of {@link Step} objects in order of their execution.
167+
*/
142168
public List<Step> toSteps(Client client, LongSupplier nowSupplier) {
143169
List<Step> steps = new ArrayList<>();
144170
List<Phase> orderedPhases = type.getOrderedPhases(phases);
@@ -148,9 +174,19 @@ public List<Step> toSteps(Client client, LongSupplier nowSupplier) {
148174
steps.add(TerminalPolicyStep.INSTANCE);
149175
Step.StepKey lastStepKey = TerminalPolicyStep.KEY;
150176

177+
Phase phase = null;
151178
// add steps for each phase, in reverse
152179
while (phaseIterator.hasPrevious()) {
153-
Phase phase = phaseIterator.previous();
180+
181+
// add `after` step for phase before next
182+
if (phase != null) {
183+
Step.StepKey afterStepKey = new Step.StepKey(phase.getName(), "pre-" + lastStepKey.getAction(), "after");
184+
Step phaseAfterStep = new PhaseAfterStep(nowSupplier, phase.getAfter(), afterStepKey, lastStepKey);
185+
steps.add(phaseAfterStep);
186+
lastStepKey = phaseAfterStep.getKey();
187+
}
188+
189+
phase = phaseIterator.previous();
154190
List<LifecycleAction> orderedActions = type.getOrderedActions(phase);
155191
ListIterator<LifecycleAction> actionIterator = orderedActions.listIterator(orderedActions.size());
156192
// add steps for each action, in reverse
@@ -164,23 +200,24 @@ public List<Step> toSteps(Client client, LongSupplier nowSupplier) {
164200
lastStepKey = step.getKey();
165201
}
166202
}
203+
}
167204

168-
// add `after` step for phase
169-
Step.StepKey afterStepKey = new Step.StepKey(phase.getName(), "pre-action", "after");
205+
if (phase != null) {
206+
Step.StepKey afterStepKey = new Step.StepKey(phase.getName(), "pre-" + lastStepKey.getAction(), "after");
170207
Step phaseAfterStep = new PhaseAfterStep(nowSupplier, phase.getAfter(), afterStepKey, lastStepKey);
171208
steps.add(phaseAfterStep);
172209
lastStepKey = phaseAfterStep.getKey();
173210
}
174211

175212
// init step so that policy is guaranteed to have
176-
steps.add(new InitializePolicyContextStep(
177-
new Step.StepKey("pre-phase", "pre-action", "init"), lastStepKey));
213+
steps.add(new InitializePolicyContextStep(InitializePolicyContextStep.KEY, lastStepKey));
178214

179215
Collections.reverse(steps);
180216
logger.debug("STEP COUNT: " + steps.size());
181217
for (Step step : steps) {
182218
logger.debug(step.getKey() + " -> " + step.getNextStepKey());
183219
}
220+
184221
return steps;
185222
}
186223

x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/LifecyclePolicyTests.java

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
1616
import org.elasticsearch.common.xcontent.XContentParser;
1717
import org.elasticsearch.test.AbstractSerializingTestCase;
18+
import org.elasticsearch.xpack.core.indexlifecycle.Step.StepKey;
1819

1920
import java.io.IOException;
2021
import java.util.ArrayList;
@@ -27,6 +28,7 @@
2728
import java.util.function.LongSupplier;
2829

2930
import static org.hamcrest.Matchers.equalTo;
31+
import static org.hamcrest.Matchers.instanceOf;
3032
import static org.mockito.Mockito.mock;
3133

3234
public class LifecyclePolicyTests extends AbstractSerializingTestCase<LifecyclePolicy> {
@@ -105,38 +107,55 @@ public void testDefaultLifecycleType() {
105107
assertSame(TimeseriesLifecycleType.INSTANCE, policy.getType());
106108
}
107109

110+
public void testFirstAndLastSteps() {
111+
Client client = mock(Client.class);
112+
LongSupplier nowSupplier = () -> 0L;
113+
lifecycleName = randomAlphaOfLengthBetween(1, 20);
114+
Map<String, Phase> phases = new LinkedHashMap<>();
115+
LifecyclePolicy policy = new LifecyclePolicy(TestLifecycleType.INSTANCE, lifecycleName, phases);
116+
List<Step> steps = policy.toSteps(client, nowSupplier);
117+
assertThat(steps.size(), equalTo(2));
118+
assertThat(steps.get(0), instanceOf(InitializePolicyContextStep.class));
119+
assertThat(steps.get(0).getKey(), equalTo(new StepKey("pre-phase", "pre-action", "init")));
120+
assertThat(steps.get(0).getNextStepKey(), equalTo(TerminalPolicyStep.KEY));
121+
assertSame(steps.get(1), TerminalPolicyStep.INSTANCE);
122+
}
123+
108124
public void testToStepsWithOneStep() {
109125
Client client = mock(Client.class);
110126
LongSupplier nowSupplier = () -> 0L;
111-
MockStep firstStep = new MockStep(new Step.StepKey("test", "test", "test"), null);
127+
MockStep mockStep = new MockStep(
128+
new Step.StepKey("test", "test", "test"), TerminalPolicyStep.KEY);
112129

113130
lifecycleName = randomAlphaOfLengthBetween(1, 20);
114131
Map<String, Phase> phases = new LinkedHashMap<>();
115-
LifecycleAction firstAction = new MockAction(Arrays.asList(firstStep));
132+
LifecycleAction firstAction = new MockAction(Arrays.asList(mockStep));
116133
Map<String, LifecycleAction> actions = Collections.singletonMap(MockAction.NAME, firstAction);
117134
Phase firstPhase = new Phase("test", TimeValue.ZERO, actions);
118135
phases.put(firstPhase.getName(), firstPhase);
119136
LifecyclePolicy policy = new LifecyclePolicy(TestLifecycleType.INSTANCE, lifecycleName, phases);
120-
137+
StepKey firstStepKey = InitializePolicyContextStep.KEY;
138+
StepKey secondStepKey = new StepKey("test", "pre-test", "after");
121139
List<Step> steps = policy.toSteps(client, nowSupplier);
122140
assertThat(steps.size(), equalTo(4));
123-
assertThat(steps.get(0).getKey(), equalTo(new Step.StepKey("pre-phase", "pre-action", "init")));
124-
assertThat(steps.get(0).getNextStepKey(), equalTo(new Step.StepKey("test", "pre-action", "after")));
125-
assertThat(steps.get(1).getKey(), equalTo(new Step.StepKey("test", "pre-action", "after")));
126-
assertThat(steps.get(1).getNextStepKey(), equalTo(firstStep.getKey()));
127-
assertThat(steps.get(2), equalTo(firstStep));
128-
assertNull(steps.get(2).getNextStepKey());
141+
assertSame(steps.get(0).getKey(), firstStepKey);
142+
assertThat(steps.get(0).getNextStepKey(), equalTo(secondStepKey));
143+
assertThat(steps.get(1).getKey(), equalTo(secondStepKey));
144+
assertThat(steps.get(1).getNextStepKey(), equalTo(mockStep.getKey()));
145+
assertThat(steps.get(2).getKey(), equalTo(mockStep.getKey()));
146+
assertThat(steps.get(2).getNextStepKey(), equalTo(TerminalPolicyStep.KEY));
147+
assertSame(steps.get(3), TerminalPolicyStep.INSTANCE);
129148
}
130149

131150
public void testToStepsWithTwoPhases() {
132151
Client client = mock(Client.class);
133152
LongSupplier nowSupplier = () -> 0L;
134-
MockStep secondActionStep = new MockStep(new Step.StepKey("second_phase", "test", "test"), null);
135-
MockStep secondAfter = new MockStep(new Step.StepKey("second_phase", "pre-action", "after"), secondActionStep.getKey());
136-
MockStep firstActionAnotherStep = new MockStep(new Step.StepKey("first_phase", "test", "test"), secondAfter.getKey());
137-
MockStep firstActionStep = new MockStep(new Step.StepKey("first_phase", "test", "test"), firstActionAnotherStep.getKey());
138-
MockStep firstAfter = new MockStep(new Step.StepKey("first_phase", "pre-action", "after"), firstActionStep.getKey());
139-
MockStep init = new MockStep(new Step.StepKey("pre-phase", "pre-action", "init"), firstAfter.getKey());
153+
MockStep secondActionStep = new MockStep(new StepKey("second_phase", "test2", "test"), TerminalPolicyStep.KEY);
154+
MockStep secondAfter = new MockStep(new StepKey("second_phase", "pre-test2", "after"), secondActionStep.getKey());
155+
MockStep firstActionAnotherStep = new MockStep(new StepKey("first_phase", "test", "bar"), secondAfter.getKey());
156+
MockStep firstActionStep = new MockStep(new StepKey("first_phase", "test", "foo"), firstActionAnotherStep.getKey());
157+
MockStep firstAfter = new MockStep(new StepKey("first_phase", "pre-test", "after"), firstActionStep.getKey());
158+
MockStep init = new MockStep(InitializePolicyContextStep.KEY, firstAfter.getKey());
140159

141160
lifecycleName = randomAlphaOfLengthBetween(1, 20);
142161
Map<String, Phase> phases = new LinkedHashMap<>();
@@ -164,6 +183,6 @@ public void testToStepsWithTwoPhases() {
164183
assertThat(steps.get(4).getKey(), equalTo(secondAfter.getKey()));
165184
assertThat(steps.get(4).getNextStepKey(), equalTo(secondAfter.getNextStepKey()));
166185
assertThat(steps.get(5), equalTo(secondActionStep));
167-
assertThat(steps.get(6).getClass(), equalTo(TerminalPolicyStep.class));
186+
assertSame(steps.get(6), TerminalPolicyStep.INSTANCE);
168187
}
169188
}

0 commit comments

Comments
 (0)