/
Job.java
379 lines (348 loc) · 12 KB
/
Job.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
/*
*
* Copyright 2015 Netflix, Inc.
*
* Licensed 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.
*
*/
package com.netflix.genie.common.dto;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.netflix.genie.common.util.TimeUtils;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;
import javax.annotation.Nullable;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.time.Duration;
import java.time.Instant;
import java.util.List;
import java.util.Optional;
/**
* Read only data transfer object representing a Job in the Genie system.
*
* @author tgianos
* @since 3.0.0
*/
@Getter
@JsonDeserialize(builder = Job.Builder.class)
public class Job extends CommonDTO {
private static final long serialVersionUID = -4218933066048954819L;
@NotNull(message = "A valid job status is required")
private final JobStatus status;
@Size(max = 255, message = "Max length of the status message is 255 characters")
private final String statusMsg;
private final Instant started;
private final Instant finished;
@Size(max = 1024, message = "Max character length is 1024 characters for the archive location")
private final String archiveLocation;
@Size(max = 255, message = "Max character length is 255 characters for the cluster name")
private final String clusterName;
@Size(max = 255, message = "Max character length is 255 characters for the command name")
private final String commandName;
@NotNull
@JsonSerialize(using = ToStringSerializer.class)
private final Duration runtime;
@Size(max = 10_000, message = "The maximum number of characters for the command arguments is 10,000")
private final String commandArgs;
private final String grouping;
private final String groupingInstance;
/**
* Constructor used by the builder.
*
* @param builder The builder to use
*/
protected Job(@Valid final Builder builder) {
super(builder);
this.commandArgs = builder.bCommandArgs;
this.status = builder.bStatus;
this.statusMsg = builder.bStatusMsg;
this.started = builder.bStarted;
this.finished = builder.bFinished;
this.archiveLocation = builder.bArchiveLocation;
this.clusterName = builder.bClusterName;
this.commandName = builder.bCommandName;
this.grouping = builder.bGrouping;
this.groupingInstance = builder.bGroupingInstance;
this.runtime = TimeUtils.getDuration(this.started, this.finished);
}
/**
* Get the arguments to be put on the command line along with the command executable.
*
* @return The command arguments
*/
public Optional<String> getCommandArgs() {
return Optional.ofNullable(this.commandArgs);
}
/**
* Get the current status message.
*
* @return The status message as an optional
*/
public Optional<String> getStatusMsg() {
return Optional.ofNullable(this.statusMsg);
}
/**
* Get the archive location for the job if there is one.
*
* @return The archive location
*/
public Optional<String> getArchiveLocation() {
return Optional.ofNullable(this.archiveLocation);
}
/**
* Get the name of the cluster running the job if there currently is one.
*
* @return The name of the cluster where the job is running
*/
public Optional<String> getClusterName() {
return Optional.ofNullable(this.clusterName);
}
/**
* Get the name of the command running this job if there currently is one.
*
* @return The name of the command
*/
public Optional<String> getCommandName() {
return Optional.ofNullable(this.commandName);
}
/**
* Get the grouping for this job if there currently is one.
*
* @return The grouping
* @since 3.3.0
*/
public Optional<String> getGrouping() {
return Optional.ofNullable(this.grouping);
}
/**
* Get the grouping instance for this job if there currently is one.
*
* @return The grouping instance
* @since 3.3.0
*/
public Optional<String> getGroupingInstance() {
return Optional.ofNullable(this.groupingInstance);
}
/**
* Get the time the job started.
*
* @return The started time or null if not set
*/
public Optional<Instant> getStarted() {
return Optional.ofNullable(this.started);
}
/**
* Get the time the job finished.
*
* @return The finished time or null if not set
*/
public Optional<Instant> getFinished() {
return Optional.ofNullable(this.finished);
}
/**
* A builder to create jobs.
*
* @author tgianos
* @since 3.0.0
*/
public static class Builder extends CommonDTO.Builder<Builder> {
private String bCommandArgs;
private JobStatus bStatus = JobStatus.INIT;
private String bStatusMsg;
private Instant bStarted;
private Instant bFinished;
private String bArchiveLocation;
private String bClusterName;
private String bCommandName;
private String bGrouping;
private String bGroupingInstance;
/**
* Constructor which has required fields.
*
* @param name The name to use for the Job
* @param user The user to use for the Job
* @param version The version to use for the Job
* @since 3.3.0
*/
@JsonCreator
public Builder(
@JsonProperty("name") final String name,
@JsonProperty("user") final String user,
@JsonProperty("version") final String version
) {
super(name, user, version);
}
/**
* Constructor which has required fields.
* <p>
* Deprecated: Command args is optional. Use new constructor. Will be removed in 4.0.0
*
* @param name The name to use for the Job
* @param user The user to use for the Job
* @param version The version to use for the Job
* @param commandArgs The command arguments used for this job. Max length 10,000 characters
* @see #Builder(String, String, String)
*/
@Deprecated
public Builder(
final String name,
final String user,
final String version,
@Nullable final String commandArgs
) {
super(name, user, version);
this.bCommandArgs = StringUtils.isBlank(commandArgs) ? null : commandArgs;
}
/**
* The command arguments to use in conjunction with the command executable selected for this job.
* <p>
* DEPRECATED: This API will be removed in 4.0.0 in favor of the List based method for improved control over
* escaping of arguments.
*
* @param commandArgs The command args. The max length is 10,000 characters
* @return The builder
* @since 3.3.0
* @deprecated See {@link #withCommandArgs(List)}
*/
@Deprecated
public Builder withCommandArgs(@Nullable final String commandArgs) {
this.bCommandArgs = StringUtils.isBlank(commandArgs) ? null : commandArgs;
return this;
}
/**
* The command arguments to use in conjunction with the command executable selected for this job.
*
* @param commandArgs The command args. The maximum combined size of the command args plus 1 space character
* between each argument must be <= 10,000 characters
* @return The builder
* @since 3.3.0
*/
public Builder withCommandArgs(@Nullable final List<String> commandArgs) {
if (commandArgs != null) {
this.bCommandArgs = StringUtils.join(commandArgs, StringUtils.SPACE);
if (StringUtils.isBlank(this.bCommandArgs)) {
this.bCommandArgs = null;
}
} else {
this.bCommandArgs = null;
}
return this;
}
/**
* Set the execution cluster name for this job.
*
* @param clusterName The execution cluster name
* @return The builder
*/
public Builder withClusterName(@Nullable final String clusterName) {
this.bClusterName = clusterName;
return this;
}
/**
* Set the name of the command used to run this job.
*
* @param commandName The name of the command
* @return The builder
*/
public Builder withCommandName(@Nullable final String commandName) {
this.bCommandName = commandName;
return this;
}
/**
* Set the status of the job.
*
* @param status The status
* @return The builder
* @see JobStatus
*/
public Builder withStatus(final JobStatus status) {
this.bStatus = status;
return this;
}
/**
* Set the detailed status message of the job.
*
* @param statusMsg The status message
* @return The builder
*/
public Builder withStatusMsg(@Nullable final String statusMsg) {
this.bStatusMsg = statusMsg;
return this;
}
/**
* Set the started time of the job.
*
* @param started The started time of the job
* @return The builder
*/
public Builder withStarted(@Nullable final Instant started) {
this.bStarted = started;
return this;
}
/**
* Set the finished time of the job.
*
* @param finished The time the job finished
* @return The builder
*/
public Builder withFinished(@Nullable final Instant finished) {
this.bFinished = finished;
return this;
}
/**
* Set the archive location of the job.
*
* @param archiveLocation The location where the job results are archived
* @return The builder
*/
public Builder withArchiveLocation(@Nullable final String archiveLocation) {
this.bArchiveLocation = archiveLocation;
return this;
}
/**
* Set the grouping to use for this job.
*
* @param grouping The grouping
* @return The builder
* @since 3.3.0
*/
public Builder withGrouping(@Nullable final String grouping) {
this.bGrouping = grouping;
return this;
}
/**
* Set the grouping instance to use for this job.
*
* @param groupingInstance The grouping instance
* @return The builder
* @since 3.3.0
*/
public Builder withGroupingInstance(@Nullable final String groupingInstance) {
this.bGroupingInstance = groupingInstance;
return this;
}
/**
* Build the job.
*
* @return Create the final read-only Job instance
*/
public Job build() {
return new Job(this);
}
}
}