Skip to content

Commit 2d056a2

Browse files
benwtrentjimczi
authored andcommitted
HLRC: adding machine learning delete job (#32820)
* HLRC: adding machine learning delete job * Fixing whitespace * Moving docs and tests around * Unifying ml asciidoc file naming convention
1 parent 364c9f6 commit 2d056a2

File tree

11 files changed

+412
-3
lines changed

11 files changed

+412
-3
lines changed

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

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
package org.elasticsearch.client;
2020

2121
import org.elasticsearch.action.ActionListener;
22+
import org.elasticsearch.protocol.xpack.ml.DeleteJobRequest;
23+
import org.elasticsearch.protocol.xpack.ml.DeleteJobResponse;
2224
import org.elasticsearch.protocol.xpack.ml.OpenJobRequest;
2325
import org.elasticsearch.protocol.xpack.ml.OpenJobResponse;
2426
import org.elasticsearch.protocol.xpack.ml.PutJobRequest;
@@ -80,6 +82,44 @@ public void putJobAsync(PutJobRequest request, RequestOptions options, ActionLis
8082
Collections.emptySet());
8183
}
8284

85+
/**
86+
* Deletes the given Machine Learning Job
87+
* <p>
88+
* For additional info
89+
* see <a href="http://www.elastic.co/guide/en/elasticsearch/reference/current/ml-delete-job.html">ML Delete Job documentation</a>
90+
* </p>
91+
* @param request the request to delete the job
92+
* @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
93+
* @return action acknowledgement
94+
* @throws IOException when there is a serialization issue sending the request or receiving the response
95+
*/
96+
public DeleteJobResponse deleteJob(DeleteJobRequest request, RequestOptions options) throws IOException {
97+
return restHighLevelClient.performRequestAndParseEntity(request,
98+
RequestConverters::deleteMachineLearningJob,
99+
options,
100+
DeleteJobResponse::fromXContent,
101+
Collections.emptySet());
102+
}
103+
104+
/**
105+
* Deletes the given Machine Learning Job asynchronously and notifies the listener on completion
106+
* <p>
107+
* For additional info
108+
* see <a href="http://www.elastic.co/guide/en/elasticsearch/reference/current/ml-delete-job.html">ML Delete Job documentation</a>
109+
* </p>
110+
* @param request the request to delete the job
111+
* @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
112+
* @param listener Listener to be notified upon request completion
113+
*/
114+
public void deleteJobAsync(DeleteJobRequest request, RequestOptions options, ActionListener<DeleteJobResponse> listener) {
115+
restHighLevelClient.performRequestAsyncAndParseEntity(request,
116+
RequestConverters::deleteMachineLearningJob,
117+
options,
118+
DeleteJobResponse::fromXContent,
119+
listener,
120+
Collections.emptySet());
121+
}
122+
83123
/**
84124
* Opens a Machine Learning Job.
85125
* When you open a new job, it starts with an empty model.

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@
112112
import org.elasticsearch.protocol.xpack.license.GetLicenseRequest;
113113
import org.elasticsearch.protocol.xpack.license.PutLicenseRequest;
114114
import org.elasticsearch.protocol.xpack.migration.IndexUpgradeInfoRequest;
115+
import org.elasticsearch.protocol.xpack.ml.DeleteJobRequest;
115116
import org.elasticsearch.protocol.xpack.ml.OpenJobRequest;
116117
import org.elasticsearch.protocol.xpack.ml.PutJobRequest;
117118
import org.elasticsearch.protocol.xpack.watcher.DeleteWatchRequest;
@@ -1211,6 +1212,21 @@ static Request putMachineLearningJob(PutJobRequest putJobRequest) throws IOExcep
12111212
return request;
12121213
}
12131214

1215+
static Request deleteMachineLearningJob(DeleteJobRequest deleteJobRequest) {
1216+
String endpoint = new EndpointBuilder()
1217+
.addPathPartAsIs("_xpack")
1218+
.addPathPartAsIs("ml")
1219+
.addPathPartAsIs("anomaly_detectors")
1220+
.addPathPart(deleteJobRequest.getJobId())
1221+
.build();
1222+
Request request = new Request(HttpDelete.METHOD_NAME, endpoint);
1223+
1224+
Params params = new Params(request);
1225+
params.putParam("force", Boolean.toString(deleteJobRequest.isForce()));
1226+
1227+
return request;
1228+
}
1229+
12141230
static Request machineLearningOpenJob(OpenJobRequest openJobRequest) throws IOException {
12151231
String endpoint = new EndpointBuilder()
12161232
.addPathPartAsIs("_xpack")

client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningIT.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020

2121
import com.carrotsearch.randomizedtesting.generators.CodepointSetGenerator;
2222
import org.elasticsearch.common.unit.TimeValue;
23+
import org.elasticsearch.protocol.xpack.ml.DeleteJobRequest;
24+
import org.elasticsearch.protocol.xpack.ml.DeleteJobResponse;
2325
import org.elasticsearch.protocol.xpack.ml.OpenJobRequest;
2426
import org.elasticsearch.protocol.xpack.ml.OpenJobResponse;
2527
import org.elasticsearch.protocol.xpack.ml.PutJobRequest;
@@ -48,6 +50,19 @@ public void testPutJob() throws Exception {
4850
assertThat(createdJob.getJobType(), is(Job.ANOMALY_DETECTOR_JOB_TYPE));
4951
}
5052

53+
public void testDeleteJob() throws Exception {
54+
String jobId = randomValidJobId();
55+
Job job = buildJob(jobId);
56+
MachineLearningClient machineLearningClient = highLevelClient().machineLearning();
57+
machineLearningClient.putJob(new PutJobRequest(job), RequestOptions.DEFAULT);
58+
59+
DeleteJobResponse response = execute(new DeleteJobRequest(jobId),
60+
machineLearningClient::deleteJob,
61+
machineLearningClient::deleteJobAsync);
62+
63+
assertTrue(response.isAcknowledged());
64+
}
65+
5166
public void testOpenJob() throws Exception {
5267
String jobId = randomValidJobId();
5368
Job job = buildJob(jobId);

client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@
127127
import org.elasticsearch.index.rankeval.RestRankEvalAction;
128128
import org.elasticsearch.protocol.xpack.XPackInfoRequest;
129129
import org.elasticsearch.protocol.xpack.migration.IndexUpgradeInfoRequest;
130+
import org.elasticsearch.protocol.xpack.ml.DeleteJobRequest;
130131
import org.elasticsearch.protocol.xpack.ml.OpenJobRequest;
131132
import org.elasticsearch.protocol.xpack.watcher.DeleteWatchRequest;
132133
import org.elasticsearch.protocol.xpack.watcher.PutWatchRequest;
@@ -2611,6 +2612,20 @@ public void testXPackDeleteWatch() {
26112612
assertThat(request.getEntity(), nullValue());
26122613
}
26132614

2615+
public void testDeleteMachineLearningJob() {
2616+
String jobId = randomAlphaOfLength(10);
2617+
DeleteJobRequest deleteJobRequest = new DeleteJobRequest(jobId);
2618+
2619+
Request request = RequestConverters.deleteMachineLearningJob(deleteJobRequest);
2620+
assertEquals(HttpDelete.METHOD_NAME, request.getMethod());
2621+
assertEquals("/_xpack/ml/anomaly_detectors/" + jobId, request.getEndpoint());
2622+
assertEquals(Boolean.toString(false), request.getParameters().get("force"));
2623+
2624+
deleteJobRequest.setForce(true);
2625+
request = RequestConverters.deleteMachineLearningJob(deleteJobRequest);
2626+
assertEquals(Boolean.toString(true), request.getParameters().get("force"));
2627+
}
2628+
26142629
public void testPostMachineLearningOpenJob() throws Exception {
26152630
String jobId = "some-job-id";
26162631
OpenJobRequest openJobRequest = new OpenJobRequest(jobId);

client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/MlClientDocumentationIT.java

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
import org.elasticsearch.client.RequestOptions;
2626
import org.elasticsearch.client.RestHighLevelClient;
2727
import org.elasticsearch.common.unit.TimeValue;
28+
import org.elasticsearch.protocol.xpack.ml.DeleteJobRequest;
29+
import org.elasticsearch.protocol.xpack.ml.DeleteJobResponse;
2830
import org.elasticsearch.protocol.xpack.ml.OpenJobRequest;
2931
import org.elasticsearch.protocol.xpack.ml.OpenJobResponse;
3032
import org.elasticsearch.protocol.xpack.ml.PutJobRequest;
@@ -122,6 +124,56 @@ public void onFailure(Exception e) {
122124
}
123125
}
124126

127+
public void testDeleteJob() throws Exception {
128+
RestHighLevelClient client = highLevelClient();
129+
130+
String jobId = "my-first-machine-learning-job";
131+
132+
Job job = MachineLearningIT.buildJob(jobId);
133+
client.machineLearning().putJob(new PutJobRequest(job), RequestOptions.DEFAULT);
134+
135+
Job secondJob = MachineLearningIT.buildJob("my-second-machine-learning-job");
136+
client.machineLearning().putJob(new PutJobRequest(secondJob), RequestOptions.DEFAULT);
137+
138+
{
139+
//tag::x-pack-delete-ml-job-request
140+
DeleteJobRequest deleteJobRequest = new DeleteJobRequest("my-first-machine-learning-job");
141+
deleteJobRequest.setForce(false); //<1>
142+
DeleteJobResponse deleteJobResponse = client.machineLearning().deleteJob(deleteJobRequest, RequestOptions.DEFAULT);
143+
//end::x-pack-delete-ml-job-request
144+
145+
//tag::x-pack-delete-ml-job-response
146+
boolean isAcknowledged = deleteJobResponse.isAcknowledged(); //<1>
147+
//end::x-pack-delete-ml-job-response
148+
}
149+
{
150+
//tag::x-pack-delete-ml-job-request-listener
151+
ActionListener<DeleteJobResponse> listener = new ActionListener<DeleteJobResponse>() {
152+
@Override
153+
public void onResponse(DeleteJobResponse deleteJobResponse) {
154+
// <1>
155+
}
156+
157+
@Override
158+
public void onFailure(Exception e) {
159+
// <2>
160+
}
161+
};
162+
//end::x-pack-delete-ml-job-request-listener
163+
164+
// Replace the empty listener by a blocking listener in test
165+
final CountDownLatch latch = new CountDownLatch(1);
166+
listener = new LatchedActionListener<>(listener, latch);
167+
168+
//tag::x-pack-delete-ml-job-request-async
169+
DeleteJobRequest deleteJobRequest = new DeleteJobRequest("my-second-machine-learning-job");
170+
client.machineLearning().deleteJobAsync(deleteJobRequest, RequestOptions.DEFAULT, listener); // <1>
171+
//end::x-pack-delete-ml-job-request-async
172+
173+
assertTrue(latch.await(30L, TimeUnit.SECONDS));
174+
}
175+
}
176+
125177
public void testOpenJob() throws Exception {
126178
RestHighLevelClient client = highLevelClient();
127179

@@ -143,7 +195,6 @@ public void testOpenJob() throws Exception {
143195
//end::x-pack-ml-open-job-execute
144196

145197
}
146-
147198
{
148199
//tag::x-pack-ml-open-job-listener
149200
ActionListener<OpenJobResponse> listener = new ActionListener<OpenJobResponse>() {
@@ -154,7 +205,7 @@ public void onResponse(OpenJobResponse openJobResponse) {
154205

155206
@Override
156207
public void onFailure(Exception e) {
157-
//<2>
208+
// <2>
158209
}
159210
};
160211
//end::x-pack-ml-open-job-listener
@@ -169,6 +220,5 @@ public void onFailure(Exception e) {
169220

170221
assertTrue(latch.await(30L, TimeUnit.SECONDS));
171222
}
172-
173223
}
174224
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
[[java-rest-high-x-pack-ml-delete-job]]
2+
=== Delete Job API
3+
4+
[[java-rest-high-x-pack-machine-learning-delete-job-request]]
5+
==== Delete Job Request
6+
7+
A `DeleteJobRequest` object requires a non-null `jobId` and can optionally set `force`.
8+
Can be executed as follows:
9+
10+
["source","java",subs="attributes,callouts,macros"]
11+
---------------------------------------------------
12+
include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-delete-ml-job-request]
13+
---------------------------------------------------
14+
<1> Use to forcefully delete an opened job;
15+
this method is quicker than closing and deleting the job.
16+
Defaults to `false`
17+
18+
[[java-rest-high-x-pack-machine-learning-delete-job-response]]
19+
==== Delete Job Response
20+
21+
The returned `DeleteJobResponse` object indicates the acknowledgement of the request:
22+
["source","java",subs="attributes,callouts,macros"]
23+
---------------------------------------------------
24+
include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-delete-ml-job-response]
25+
---------------------------------------------------
26+
<1> `isAcknowledged` was the deletion request acknowledged or not
27+
28+
[[java-rest-high-x-pack-machine-learning-delete-job-async]]
29+
==== Delete Job Asynchronously
30+
31+
This request can also be made asynchronously.
32+
["source","java",subs="attributes,callouts,macros"]
33+
---------------------------------------------------
34+
include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-delete-ml-job-request-async]
35+
---------------------------------------------------
36+
<1> The `DeleteJobRequest` to execute and the `ActionListener` to alert on completion or error.
37+
38+
The deletion request returns immediately. Once the request is completed, the `ActionListener` is
39+
called back using the `onResponse` or `onFailure`. The latter indicates some failure occurred when
40+
making the request.
41+
42+
A typical listener for a `DeleteJobRequest` could be defined as follows:
43+
44+
["source","java",subs="attributes,callouts,macros"]
45+
---------------------------------------------------
46+
include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-delete-ml-job-request-listener]
47+
---------------------------------------------------
48+
<1> The action to be taken when it is completed
49+
<2> What to do when a failure occurs

docs/java-rest/high-level/supported-apis.asciidoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,9 +205,11 @@ include::licensing/delete-license.asciidoc[]
205205
The Java High Level REST Client supports the following Machine Learning APIs:
206206

207207
* <<java-rest-high-x-pack-ml-put-job>>
208+
* <<java-rest-high-x-pack-ml-delete-job>>
208209
* <<java-rest-high-x-pack-ml-open-job>>
209210

210211
include::ml/put-job.asciidoc[]
212+
include::ml/delete-job.asciidoc[]
211213
include::ml/open-job.asciidoc[]
212214

213215
== Migration APIs
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
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.protocol.xpack.ml;
20+
21+
import org.elasticsearch.action.ActionRequest;
22+
import org.elasticsearch.action.ActionRequestValidationException;
23+
24+
import java.util.Objects;
25+
26+
public class DeleteJobRequest extends ActionRequest {
27+
28+
private String jobId;
29+
private boolean force;
30+
31+
public DeleteJobRequest(String jobId) {
32+
this.jobId = Objects.requireNonNull(jobId, "[job_id] must not be null");
33+
}
34+
35+
public String getJobId() {
36+
return jobId;
37+
}
38+
39+
public void setJobId(String jobId) {
40+
this.jobId = Objects.requireNonNull(jobId, "[job_id] must not be null");
41+
}
42+
43+
public boolean isForce() {
44+
return force;
45+
}
46+
47+
public void setForce(boolean force) {
48+
this.force = force;
49+
}
50+
51+
@Override
52+
public ActionRequestValidationException validate() {
53+
return null;
54+
}
55+
56+
@Override
57+
public int hashCode() {
58+
return Objects.hash(jobId, force);
59+
}
60+
61+
@Override
62+
public boolean equals(Object obj) {
63+
if (this == obj) {
64+
return true;
65+
}
66+
67+
if (obj == null || obj.getClass() != getClass()) {
68+
return false;
69+
}
70+
71+
DeleteJobRequest other = (DeleteJobRequest) obj;
72+
return Objects.equals(jobId, other.jobId) && Objects.equals(force, other.force);
73+
}
74+
75+
}

0 commit comments

Comments
 (0)