Skip to content

Commit eb2bb17

Browse files
committed
HLRC: ML Stop datafeed API (#33946)
* HLRC: ML stop data feed api
1 parent 55f68eb commit eb2bb17

File tree

11 files changed

+691
-0
lines changed

11 files changed

+691
-0
lines changed

client/rest-high-level/src/main/java/org/elasticsearch/client/MLRequestConverters.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
import org.elasticsearch.client.ml.PutDatafeedRequest;
5050
import org.elasticsearch.client.ml.PutJobRequest;
5151
import org.elasticsearch.client.ml.StartDatafeedRequest;
52+
import org.elasticsearch.client.ml.StopDatafeedRequest;
5253
import org.elasticsearch.client.ml.UpdateJobRequest;
5354
import org.elasticsearch.common.Strings;
5455
import org.elasticsearch.common.bytes.BytesReference;
@@ -245,6 +246,19 @@ static Request startDatafeed(StartDatafeedRequest startDatafeedRequest) throws I
245246
return request;
246247
}
247248

249+
static Request stopDatafeed(StopDatafeedRequest stopDatafeedRequest) throws IOException {
250+
String endpoint = new EndpointBuilder()
251+
.addPathPartAsIs("_xpack")
252+
.addPathPartAsIs("ml")
253+
.addPathPartAsIs("datafeeds")
254+
.addPathPart(Strings.collectionToCommaDelimitedString(stopDatafeedRequest.getDatafeedIds()))
255+
.addPathPartAsIs("_stop")
256+
.build();
257+
Request request = new Request(HttpPost.METHOD_NAME, endpoint);
258+
request.setEntity(createEntity(stopDatafeedRequest, REQUEST_BODY_CONTENT_TYPE));
259+
return request;
260+
}
261+
248262
static Request deleteForecast(DeleteForecastRequest deleteForecastRequest) {
249263
String endpoint = new EndpointBuilder()
250264
.addPathPartAsIs("_xpack")

client/rest-high-level/src/main/java/org/elasticsearch/client/MachineLearningClient.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@
6060
import org.elasticsearch.client.ml.PutJobResponse;
6161
import org.elasticsearch.client.ml.StartDatafeedRequest;
6262
import org.elasticsearch.client.ml.StartDatafeedResponse;
63+
import org.elasticsearch.client.ml.StopDatafeedRequest;
64+
import org.elasticsearch.client.ml.StopDatafeedResponse;
6365
import org.elasticsearch.client.ml.UpdateJobRequest;
6466
import org.elasticsearch.client.ml.job.stats.JobStats;
6567

@@ -607,6 +609,46 @@ public void startDatafeedAsync(StartDatafeedRequest request, RequestOptions opti
607609
Collections.emptySet());
608610
}
609611

612+
/**
613+
* Stops the given Machine Learning Datafeed
614+
* <p>
615+
* For additional info
616+
* see <a href="http://www.elastic.co/guide/en/elasticsearch/reference/current/ml-stop-datafeed.html">
617+
* ML Stop Datafeed documentation</a>
618+
*
619+
* @param request The request to stop the datafeed
620+
* @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
621+
* @return action acknowledgement
622+
* @throws IOException when there is a serialization issue sending the request or receiving the response
623+
*/
624+
public StopDatafeedResponse stopDatafeed(StopDatafeedRequest request, RequestOptions options) throws IOException {
625+
return restHighLevelClient.performRequestAndParseEntity(request,
626+
MLRequestConverters::stopDatafeed,
627+
options,
628+
StopDatafeedResponse::fromXContent,
629+
Collections.emptySet());
630+
}
631+
632+
/**
633+
* Stops the given Machine Learning Datafeed asynchronously and notifies the listener on completion
634+
* <p>
635+
* For additional info
636+
* see <a href="http://www.elastic.co/guide/en/elasticsearch/reference/current/ml-stop-datafeed.html">
637+
* ML Stop Datafeed documentation</a>
638+
*
639+
* @param request The request to stop the datafeed
640+
* @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
641+
* @param listener Listener to be notified upon request completion
642+
*/
643+
public void stopDatafeedAsync(StopDatafeedRequest request, RequestOptions options, ActionListener<StopDatafeedResponse> listener) {
644+
restHighLevelClient.performRequestAsyncAndParseEntity(request,
645+
MLRequestConverters::stopDatafeed,
646+
options,
647+
StopDatafeedResponse::fromXContent,
648+
listener,
649+
Collections.emptySet());
650+
}
651+
610652
/**
611653
* Updates a Machine Learning {@link org.elasticsearch.client.ml.job.config.Job}
612654
* <p>
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.elasticsearch.client.ml;
20+
21+
import org.elasticsearch.action.ActionRequest;
22+
import org.elasticsearch.action.ActionRequestValidationException;
23+
import org.elasticsearch.client.ml.datafeed.DatafeedConfig;
24+
import org.elasticsearch.common.ParseField;
25+
import org.elasticsearch.common.Strings;
26+
import org.elasticsearch.common.unit.TimeValue;
27+
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
28+
import org.elasticsearch.common.xcontent.ObjectParser;
29+
import org.elasticsearch.common.xcontent.ToXContentObject;
30+
import org.elasticsearch.common.xcontent.XContentBuilder;
31+
32+
import java.io.IOException;
33+
import java.security.InvalidParameterException;
34+
import java.util.ArrayList;
35+
import java.util.Arrays;
36+
import java.util.List;
37+
import java.util.Objects;
38+
39+
/**
40+
* Request to stop Machine Learning Datafeeds
41+
*/
42+
public class StopDatafeedRequest extends ActionRequest implements ToXContentObject {
43+
44+
public static final ParseField TIMEOUT = new ParseField("timeout");
45+
public static final ParseField FORCE = new ParseField("force");
46+
public static final ParseField ALLOW_NO_DATAFEEDS = new ParseField("allow_no_datafeeds");
47+
48+
@SuppressWarnings("unchecked")
49+
public static final ConstructingObjectParser<StopDatafeedRequest, Void> PARSER = new ConstructingObjectParser<>(
50+
"stop_datafeed_request",
51+
a -> new StopDatafeedRequest((List<String>) a[0]));
52+
53+
static {
54+
PARSER.declareField(ConstructingObjectParser.constructorArg(),
55+
p -> Arrays.asList(Strings.commaDelimitedListToStringArray(p.text())),
56+
DatafeedConfig.ID, ObjectParser.ValueType.STRING_ARRAY);
57+
PARSER.declareString((obj, val) -> obj.setTimeout(TimeValue.parseTimeValue(val, TIMEOUT.getPreferredName())), TIMEOUT);
58+
PARSER.declareBoolean(StopDatafeedRequest::setForce, FORCE);
59+
PARSER.declareBoolean(StopDatafeedRequest::setAllowNoDatafeeds, ALLOW_NO_DATAFEEDS);
60+
}
61+
62+
private static final String ALL_DATAFEEDS = "_all";
63+
64+
private final List<String> datafeedIds;
65+
private TimeValue timeout;
66+
private Boolean force;
67+
private Boolean allowNoDatafeeds;
68+
69+
/**
70+
* Explicitly stop all datafeeds
71+
*
72+
* @return a {@link StopDatafeedRequest} for all existing datafeeds
73+
*/
74+
public static StopDatafeedRequest stopAllDatafeedsRequest(){
75+
return new StopDatafeedRequest(ALL_DATAFEEDS);
76+
}
77+
78+
StopDatafeedRequest(List<String> datafeedIds) {
79+
if (datafeedIds.isEmpty()) {
80+
throw new InvalidParameterException("datafeedIds must not be empty");
81+
}
82+
if (datafeedIds.stream().anyMatch(Objects::isNull)) {
83+
throw new NullPointerException("datafeedIds must not contain null values");
84+
}
85+
this.datafeedIds = new ArrayList<>(datafeedIds);
86+
}
87+
88+
/**
89+
* Close the specified Datafeeds via their unique datafeedIds
90+
*
91+
* @param datafeedIds must be non-null and non-empty and each datafeedId must be non-null
92+
*/
93+
public StopDatafeedRequest(String... datafeedIds) {
94+
this(Arrays.asList(datafeedIds));
95+
}
96+
97+
/**
98+
* All the datafeedIds to be stopped
99+
*/
100+
public List<String> getDatafeedIds() {
101+
return datafeedIds;
102+
}
103+
104+
public TimeValue getTimeout() {
105+
return timeout;
106+
}
107+
108+
/**
109+
* How long to wait for the stop request to complete before timing out.
110+
*
111+
* @param timeout Default value: 30 minutes
112+
*/
113+
public void setTimeout(TimeValue timeout) {
114+
this.timeout = timeout;
115+
}
116+
117+
public Boolean isForce() {
118+
return force;
119+
}
120+
121+
/**
122+
* Should the stopping be forced.
123+
*
124+
* Use to forcefully stop a datafeed
125+
*
126+
* @param force When {@code true} forcefully stop the datafeed. Defaults to {@code false}
127+
*/
128+
public void setForce(boolean force) {
129+
this.force = force;
130+
}
131+
132+
public Boolean isAllowNoDatafeeds() {
133+
return this.allowNoDatafeeds;
134+
}
135+
136+
/**
137+
* Whether to ignore if a wildcard expression matches no datafeeds.
138+
*
139+
* This includes {@code _all} string.
140+
*
141+
* @param allowNoDatafeeds When {@code true} ignore if wildcard or {@code _all} matches no datafeeds. Defaults to {@code true}
142+
*/
143+
public void setAllowNoDatafeeds(boolean allowNoDatafeeds) {
144+
this.allowNoDatafeeds = allowNoDatafeeds;
145+
}
146+
147+
@Override
148+
public ActionRequestValidationException validate() {
149+
return null;
150+
}
151+
152+
@Override
153+
public int hashCode() {
154+
return Objects.hash(datafeedIds, timeout, force, allowNoDatafeeds);
155+
}
156+
157+
@Override
158+
public boolean equals(Object other) {
159+
if (this == other) {
160+
return true;
161+
}
162+
163+
if (other == null || getClass() != other.getClass()) {
164+
return false;
165+
}
166+
167+
StopDatafeedRequest that = (StopDatafeedRequest) other;
168+
return Objects.equals(datafeedIds, that.datafeedIds) &&
169+
Objects.equals(timeout, that.timeout) &&
170+
Objects.equals(force, that.force) &&
171+
Objects.equals(allowNoDatafeeds, that.allowNoDatafeeds);
172+
}
173+
174+
@Override
175+
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
176+
builder.startObject();
177+
builder.field(DatafeedConfig.ID.getPreferredName(), Strings.collectionToCommaDelimitedString(datafeedIds));
178+
if (timeout != null) {
179+
builder.field(TIMEOUT.getPreferredName(), timeout.getStringRep());
180+
}
181+
if (force != null) {
182+
builder.field(FORCE.getPreferredName(), force);
183+
}
184+
if (allowNoDatafeeds != null) {
185+
builder.field(ALLOW_NO_DATAFEEDS.getPreferredName(), allowNoDatafeeds);
186+
}
187+
builder.endObject();
188+
return builder;
189+
}
190+
191+
@Override
192+
public String toString() {
193+
return Strings.toString(this);
194+
}
195+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.elasticsearch.client.ml;
20+
21+
import org.elasticsearch.action.ActionResponse;
22+
import org.elasticsearch.common.ParseField;
23+
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
24+
import org.elasticsearch.common.xcontent.ToXContentObject;
25+
import org.elasticsearch.common.xcontent.XContentBuilder;
26+
import org.elasticsearch.common.xcontent.XContentParser;
27+
28+
import java.io.IOException;
29+
import java.util.Objects;
30+
31+
/**
32+
* Response indicating if the Machine Learning Datafeed is now stopped or not
33+
*/
34+
public class StopDatafeedResponse extends ActionResponse implements ToXContentObject {
35+
36+
private static final ParseField STOPPED = new ParseField("stopped");
37+
38+
public static final ConstructingObjectParser<StopDatafeedResponse, Void> PARSER =
39+
new ConstructingObjectParser<>(
40+
"stop_datafeed_response",
41+
true,
42+
(a) -> new StopDatafeedResponse((Boolean)a[0]));
43+
44+
static {
45+
PARSER.declareBoolean(ConstructingObjectParser.constructorArg(), STOPPED);
46+
}
47+
48+
private final boolean stopped;
49+
50+
public StopDatafeedResponse(boolean stopped) {
51+
this.stopped = stopped;
52+
}
53+
54+
public static StopDatafeedResponse fromXContent(XContentParser parser) throws IOException {
55+
return PARSER.parse(parser, null);
56+
}
57+
58+
/**
59+
* Has the Datafeed stopped or not
60+
*
61+
* @return boolean value indicating the Datafeed stopped status
62+
*/
63+
public boolean isStopped() {
64+
return stopped;
65+
}
66+
67+
@Override
68+
public boolean equals(Object other) {
69+
if (this == other) {
70+
return true;
71+
}
72+
73+
if (other == null || getClass() != other.getClass()) {
74+
return false;
75+
}
76+
77+
StopDatafeedResponse that = (StopDatafeedResponse) other;
78+
return isStopped() == that.isStopped();
79+
}
80+
81+
@Override
82+
public int hashCode() {
83+
return Objects.hash(isStopped());
84+
}
85+
86+
@Override
87+
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
88+
builder.startObject();
89+
builder.field(STOPPED.getPreferredName(), stopped);
90+
builder.endObject();
91+
return builder;
92+
}
93+
}

0 commit comments

Comments
 (0)