[ML] Make ModelSnapshot immutable (elastic/x-pack-elasticsearch#770)

In preparation of extending the model snapshot update API,
it makes sense to make it immutable to avoid any confusion
that could be caused by having setters on it.

I also like immutable stuff :-)

Original commit: elastic/x-pack-elasticsearch@6b2ee527a8
This commit is contained in:
Dimitris Athanasiou 2017-03-21 12:00:54 +00:00 committed by GitHub
parent 7cf959cb66
commit 62721c78ea
24 changed files with 266 additions and 257 deletions

View File

@ -38,6 +38,7 @@ import org.elasticsearch.xpack.ml.utils.ExceptionsHelper;
import java.io.IOException;
import java.util.Objects;
import java.util.stream.Collectors;
public class GetModelSnapshotsAction
extends Action<GetModelSnapshotsAction.Request, GetModelSnapshotsAction.Response, GetModelSnapshotsAction.RequestBuilder> {
@ -333,18 +334,17 @@ extends Action<GetModelSnapshotsAction.Request, GetModelSnapshotsAction.Response
request.getStart(), request.getEnd(), request.getSort(), request.getDescOrder(), request.getSnapshotId(),
request.getDescriptionString(),
page -> {
clearQuantiles(page);
listener.onResponse(new Response(page));
listener.onResponse(new Response(clearQuantiles(page)));
}, listener::onFailure);
}
public static void clearQuantiles(QueryPage<ModelSnapshot> page) {
if (page.results() != null) {
for (ModelSnapshot modelSnapshot : page.results()) {
modelSnapshot.setQuantiles(null);
public static QueryPage<ModelSnapshot> clearQuantiles(QueryPage<ModelSnapshot> page) {
if (page.results() == null) {
return page;
}
return new QueryPage<>(page.results().stream().map(snapshot ->
new ModelSnapshot.Builder(snapshot).setQuantiles(null).build())
.collect(Collectors.toList()), page.count(), page.getResultsField());
}
}
}
}
}

View File

@ -48,7 +48,6 @@ import org.elasticsearch.xpack.ml.utils.ExceptionsHelper;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
@ -312,8 +311,7 @@ extends Action<RevertModelSnapshotAction.Request, RevertModelSnapshotAction.Resp
}
// The quantiles can be large, and totally dominate the output -
// it's clearer to remove them as they are not necessary for the revert op
modelSnapshot.setQuantiles(null);
handler.accept(modelSnapshot);
handler.accept(new ModelSnapshot.Builder(modelSnapshot).setQuantiles(null).build());
}, errorHandler);
}

View File

@ -258,14 +258,13 @@ UpdateModelSnapshotAction.RequestBuilder> {
logger.warn("More than one model found for [{}: {}, {}: {}] tuple.", Job.ID.getPreferredName(), request.getJobId(),
ModelSnapshot.SNAPSHOT_ID.getPreferredName(), request.getSnapshotId());
}
ModelSnapshot modelSnapshot = changeCandidates.get(0);
modelSnapshot.setDescription(request.getDescriptionString());
jobManager.updateModelSnapshot(modelSnapshot, b -> {
modelSnapshot.setDescription(request.getDescriptionString());
ModelSnapshot.Builder updatedSnapshotBuilder = new ModelSnapshot.Builder(changeCandidates.get(0));
updatedSnapshotBuilder.setDescription(request.getDescriptionString());
ModelSnapshot updatedSnapshot = updatedSnapshotBuilder.build();
jobManager.updateModelSnapshot(updatedSnapshot, b -> {
// The quantiles can be large, and totally dominate the output -
// it's clearer to remove them
modelSnapshot.setQuantiles(null);
listener.onResponse(new Response(modelSnapshot));
listener.onResponse(new Response(new ModelSnapshot.Builder(updatedSnapshot).setQuantiles(null).build()));
}, listener::onFailure);
}, listener::onFailure);
}, listener::onFailure);

View File

@ -80,6 +80,10 @@ public final class QueryPage<T extends ToXContent & Writeable> extends ToXConten
return count;
}
public ParseField getResultsField() {
return resultsField;
}
@Override
public int hashCode() {
return Objects.hash(results, count);

View File

@ -235,11 +235,11 @@ public class JobProvider {
*/
public void dataCounts(String jobId, Consumer<DataCounts> handler, Consumer<Exception> errorHandler) {
String indexName = AnomalyDetectorsIndex.jobResultsAliasedName(jobId);
get(jobId, indexName, DataCounts.TYPE.getPreferredName(), DataCounts.documentId(jobId), handler, errorHandler,
get(indexName, DataCounts.TYPE.getPreferredName(), DataCounts.documentId(jobId), handler, errorHandler,
DataCounts.PARSER, () -> new DataCounts(jobId));
}
private <T, U> void get(String jobId, String indexName, String type, String id, Consumer<T> handler, Consumer<Exception> errorHandler,
private <T, U> void get(String indexName, String type, String id, Consumer<T> handler, Consumer<Exception> errorHandler,
BiFunction<XContentParser, U, T> objectParser, Supplier<T> notFoundSupplier) {
GetRequest getRequest = new GetRequest(indexName, type, id);
client.get(getRequest, ActionListener.wrap(
@ -758,7 +758,7 @@ public class JobProvider {
String indexName = AnomalyDetectorsIndex.jobStateIndexName();
String quantilesId = Quantiles.documentId(jobId);
LOGGER.trace("ES API CALL: get ID {} type {} from index {}", quantilesId, Quantiles.TYPE.getPreferredName(), indexName);
get(jobId, indexName, Quantiles.TYPE.getPreferredName(), quantilesId, handler, errorHandler, Quantiles.PARSER, () -> {
get(indexName, Quantiles.TYPE.getPreferredName(), quantilesId, handler, errorHandler, Quantiles.PARSER, () -> {
LOGGER.info("There are currently no quantiles for job " + jobId);
return null;
});
@ -773,8 +773,9 @@ public class JobProvider {
handler.accept(null);
return;
}
get(jobId, AnomalyDetectorsIndex.jobResultsAliasedName(jobId), ModelSnapshot.TYPE.getPreferredName(),
ModelSnapshot.documentId(jobId, modelSnapshotId), handler, errorHandler, ModelSnapshot.PARSER, () -> null);
get(AnomalyDetectorsIndex.jobResultsAliasedName(jobId), ModelSnapshot.TYPE.getPreferredName(),
ModelSnapshot.documentId(jobId, modelSnapshotId), handler, errorHandler,
(parser, context) -> ModelSnapshot.PARSER.apply(parser, null).build(), () -> null);
}
/**
@ -975,7 +976,7 @@ public class JobProvider {
ModelSizeStats.RESULT_TYPE_VALUE, ModelSizeStats.RESULT_TYPE_FIELD, jobId);
String indexName = AnomalyDetectorsIndex.jobResultsAliasedName(jobId);
get(jobId, indexName, Result.TYPE.getPreferredName(), ModelSizeStats.documentId(jobId),
get(indexName, Result.TYPE.getPreferredName(), ModelSizeStats.documentId(jobId),
handler, errorHandler, (parser, context) -> ModelSizeStats.PARSER.apply(parser, null).build(),
() -> {
LOGGER.trace("No memory usage details for job with id {}", jobId);

View File

@ -146,8 +146,8 @@ public class ModelSizeStats extends ToXContentToBytes implements Writeable {
totalPartitionFieldCount = in.readVLong();
bucketAllocationFailuresCount = in.readVLong();
memoryStatus = MemoryStatus.readFromStream(in);
logTime = new Date(in.readLong());
timestamp = in.readBoolean() ? new Date(in.readLong()) : null;
logTime = new Date(in.readVLong());
timestamp = in.readBoolean() ? new Date(in.readVLong()) : null;
}
@Override
@ -159,11 +159,11 @@ public class ModelSizeStats extends ToXContentToBytes implements Writeable {
out.writeVLong(totalPartitionFieldCount);
out.writeVLong(bucketAllocationFailuresCount);
memoryStatus.writeTo(out);
out.writeLong(logTime.getTime());
out.writeVLong(logTime.getTime());
boolean hasTimestamp = timestamp != null;
out.writeBoolean(hasTimestamp);
if (hasTimestamp) {
out.writeLong(timestamp.getTime());
out.writeVLong(timestamp.getTime());
}
}

View File

@ -12,8 +12,8 @@ import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.io.stream.Writeable;
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
import org.elasticsearch.common.xcontent.ObjectParser;
import org.elasticsearch.common.xcontent.ObjectParser.ValueType;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
@ -49,12 +49,11 @@ public class ModelSnapshot extends ToXContentToBytes implements Writeable {
*/
public static final ParseField TYPE = new ParseField("model_snapshot");
public static final ConstructingObjectParser<ModelSnapshot, Void> PARSER =
new ConstructingObjectParser<>(TYPE.getPreferredName(), a -> new ModelSnapshot((String) a[0]));
public static final ObjectParser<Builder, Void> PARSER = new ObjectParser<>(TYPE.getPreferredName(), Builder::new);
static {
PARSER.declareString(ConstructingObjectParser.constructorArg(), Job.ID);
PARSER.declareField(ModelSnapshot::setTimestamp, p -> {
PARSER.declareString(Builder::setJobId, Job.ID);
PARSER.declareField(Builder::setTimestamp, p -> {
if (p.currentToken() == Token.VALUE_NUMBER) {
return new Date(p.longValue());
} else if (p.currentToken() == Token.VALUE_STRING) {
@ -62,11 +61,11 @@ public class ModelSnapshot extends ToXContentToBytes implements Writeable {
}
throw new IllegalArgumentException("unexpected token [" + p.currentToken() + "] for [" + TIMESTAMP.getPreferredName() + "]");
}, TIMESTAMP, ValueType.VALUE);
PARSER.declareString(ModelSnapshot::setDescription, DESCRIPTION);
PARSER.declareString(ModelSnapshot::setSnapshotId, SNAPSHOT_ID);
PARSER.declareInt(ModelSnapshot::setSnapshotDocCount, SNAPSHOT_DOC_COUNT);
PARSER.declareObject(ModelSnapshot::setModelSizeStats, ModelSizeStats.PARSER, ModelSizeStats.RESULT_TYPE_FIELD);
PARSER.declareField(ModelSnapshot::setLatestRecordTimeStamp, p -> {
PARSER.declareString(Builder::setDescription, DESCRIPTION);
PARSER.declareString(Builder::setSnapshotId, SNAPSHOT_ID);
PARSER.declareInt(Builder::setSnapshotDocCount, SNAPSHOT_DOC_COUNT);
PARSER.declareObject(Builder::setModelSizeStats, ModelSizeStats.PARSER, ModelSizeStats.RESULT_TYPE_FIELD);
PARSER.declareField(Builder::setLatestRecordTimeStamp, p -> {
if (p.currentToken() == Token.VALUE_NUMBER) {
return new Date(p.longValue());
} else if (p.currentToken() == Token.VALUE_STRING) {
@ -75,7 +74,7 @@ public class ModelSnapshot extends ToXContentToBytes implements Writeable {
throw new IllegalArgumentException(
"unexpected token [" + p.currentToken() + "] for [" + LATEST_RECORD_TIME.getPreferredName() + "]");
}, LATEST_RECORD_TIME, ValueType.VALUE);
PARSER.declareField(ModelSnapshot::setLatestResultTimeStamp, p -> {
PARSER.declareField(Builder::setLatestResultTimeStamp, p -> {
if (p.currentToken() == Token.VALUE_NUMBER) {
return new Date(p.longValue());
} else if (p.currentToken() == Token.VALUE_STRING) {
@ -84,76 +83,70 @@ public class ModelSnapshot extends ToXContentToBytes implements Writeable {
throw new IllegalArgumentException(
"unexpected token [" + p.currentToken() + "] for [" + LATEST_RESULT_TIME.getPreferredName() + "]");
}, LATEST_RESULT_TIME, ValueType.VALUE);
PARSER.declareObject(ModelSnapshot::setQuantiles, Quantiles.PARSER, Quantiles.TYPE);
PARSER.declareObject(Builder::setQuantiles, Quantiles.PARSER, Quantiles.TYPE);
}
private final String jobId;
private Date timestamp;
private String description;
private String snapshotId;
private int snapshotDocCount;
private ModelSizeStats modelSizeStats;
private Date latestRecordTimeStamp;
private Date latestResultTimeStamp;
private Quantiles quantiles;
private final Date timestamp;
private final String description;
private final String snapshotId;
private final int snapshotDocCount;
private final ModelSizeStats modelSizeStats;
private final Date latestRecordTimeStamp;
private final Date latestResultTimeStamp;
private final Quantiles quantiles;
public ModelSnapshot(String jobId) {
private ModelSnapshot(String jobId, Date timestamp, String description, String snapshotId, int snapshotDocCount,
ModelSizeStats modelSizeStats, Date latestRecordTimeStamp, Date latestResultTimeStamp, Quantiles quantiles) {
this.jobId = jobId;
this.timestamp = timestamp;
this.description = description;
this.snapshotId = snapshotId;
this.snapshotDocCount = snapshotDocCount;
this.modelSizeStats = modelSizeStats;
this.latestRecordTimeStamp = latestRecordTimeStamp;
this.latestResultTimeStamp = latestResultTimeStamp;
this.quantiles = quantiles;
}
public ModelSnapshot(StreamInput in) throws IOException {
jobId = in.readString();
if (in.readBoolean()) {
timestamp = new Date(in.readLong());
}
timestamp = in.readBoolean() ? new Date(in.readVLong()) : null;
description = in.readOptionalString();
snapshotId = in.readOptionalString();
snapshotDocCount = in.readInt();
if (in.readBoolean()) {
modelSizeStats = new ModelSizeStats(in);
}
if (in.readBoolean()) {
latestRecordTimeStamp = new Date(in.readLong());
}
if (in.readBoolean()) {
latestResultTimeStamp = new Date(in.readLong());
}
if (in.readBoolean()) {
quantiles = new Quantiles(in);
}
modelSizeStats = in.readOptionalWriteable(ModelSizeStats::new);
latestRecordTimeStamp = in.readBoolean() ? new Date(in.readVLong()) : null;
latestResultTimeStamp = in.readBoolean() ? new Date(in.readVLong()) : null;
quantiles = in.readOptionalWriteable(Quantiles::new);
}
@Override
public void writeTo(StreamOutput out) throws IOException {
out.writeString(jobId);
boolean hasTimestamp = timestamp != null;
out.writeBoolean(hasTimestamp);
if (hasTimestamp) {
out.writeLong(timestamp.getTime());
if (timestamp != null) {
out.writeBoolean(true);
out.writeVLong(timestamp.getTime());
} else {
out.writeBoolean(false);
}
out.writeOptionalString(description);
out.writeOptionalString(snapshotId);
out.writeInt(snapshotDocCount);
boolean hasModelSizeStats = modelSizeStats != null;
out.writeBoolean(hasModelSizeStats);
if (hasModelSizeStats) {
modelSizeStats.writeTo(out);
out.writeOptionalWriteable(modelSizeStats);
if (latestRecordTimeStamp != null) {
out.writeBoolean(true);
out.writeVLong(latestRecordTimeStamp.getTime());
} else {
out.writeBoolean(false);
}
boolean hasLatestRecordTimeStamp = latestRecordTimeStamp != null;
out.writeBoolean(hasLatestRecordTimeStamp);
if (hasLatestRecordTimeStamp) {
out.writeLong(latestRecordTimeStamp.getTime());
}
boolean hasLatestResultTimeStamp = latestResultTimeStamp != null;
out.writeBoolean(hasLatestResultTimeStamp);
if (hasLatestResultTimeStamp) {
out.writeLong(latestResultTimeStamp.getTime());
}
boolean hasQuantiles = quantiles != null;
out.writeBoolean(hasQuantiles);
if (hasQuantiles) {
quantiles.writeTo(out);
if (latestResultTimeStamp != null) {
out.writeBoolean(true);
out.writeVLong(latestResultTimeStamp.getTime());
} else {
out.writeBoolean(false);
}
out.writeOptionalWriteable(quantiles);
}
@Override
@ -196,66 +189,34 @@ public class ModelSnapshot extends ToXContentToBytes implements Writeable {
return timestamp;
}
public void setTimestamp(Date timestamp) {
this.timestamp = timestamp;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getSnapshotId() {
return snapshotId;
}
public void setSnapshotId(String snapshotId) {
this.snapshotId = snapshotId;
}
public int getSnapshotDocCount() {
return snapshotDocCount;
}
public void setSnapshotDocCount(int snapshotDocCount) {
this.snapshotDocCount = snapshotDocCount;
}
public ModelSizeStats getModelSizeStats() {
return modelSizeStats;
}
public void setModelSizeStats(ModelSizeStats.Builder modelSizeStats) {
this.modelSizeStats = modelSizeStats.build();
}
public Quantiles getQuantiles() {
return quantiles;
}
public void setQuantiles(Quantiles q) {
quantiles = q;
}
public Date getLatestRecordTimeStamp() {
return latestRecordTimeStamp;
}
public void setLatestRecordTimeStamp(Date latestRecordTimeStamp) {
this.latestRecordTimeStamp = latestRecordTimeStamp;
}
public Date getLatestResultTimeStamp() {
return latestResultTimeStamp;
}
public void setLatestResultTimeStamp(Date latestResultTimeStamp) {
this.latestResultTimeStamp = latestResultTimeStamp;
}
@Override
public int hashCode() {
return Objects.hash(jobId, timestamp, description, snapshotId, quantiles, snapshotDocCount, modelSizeStats, latestRecordTimeStamp,
@ -298,9 +259,96 @@ public class ModelSnapshot extends ToXContentToBytes implements Writeable {
public static ModelSnapshot fromJson(BytesReference bytesReference) {
try (XContentParser parser = XContentFactory.xContent(bytesReference).createParser(NamedXContentRegistry.EMPTY, bytesReference)) {
return PARSER.apply(parser, null);
return PARSER.apply(parser, null).build();
} catch (IOException e) {
throw new ElasticsearchParseException("failed to parse modelSnapshot", e);
}
}
public static class Builder {
private String jobId;
private Date timestamp;
private String description;
private String snapshotId;
private int snapshotDocCount;
private ModelSizeStats modelSizeStats;
private Date latestRecordTimeStamp;
private Date latestResultTimeStamp;
private Quantiles quantiles;
public Builder() {
}
public Builder(String jobId) {
this();
this.jobId = jobId;
}
public Builder(ModelSnapshot modelSnapshot) {
this.jobId = modelSnapshot.jobId;
this.timestamp = modelSnapshot.timestamp;
this.description = modelSnapshot.description;
this.snapshotId = modelSnapshot.snapshotId;
this.snapshotDocCount = modelSnapshot.snapshotDocCount;
this.modelSizeStats = modelSnapshot.modelSizeStats;
this.latestRecordTimeStamp = modelSnapshot.latestRecordTimeStamp;
this.latestResultTimeStamp = modelSnapshot.latestResultTimeStamp;
this.quantiles = modelSnapshot.quantiles;
}
public Builder setJobId(String jobId) {
this.jobId = jobId;
return this;
}
public Builder setTimestamp(Date timestamp) {
this.timestamp = timestamp;
return this;
}
public Builder setDescription(String description) {
this.description = description;
return this;
}
public Builder setSnapshotId(String snapshotId) {
this.snapshotId = snapshotId;
return this;
}
public Builder setSnapshotDocCount(int snapshotDocCount) {
this.snapshotDocCount = snapshotDocCount;
return this;
}
public Builder setModelSizeStats(ModelSizeStats.Builder modelSizeStats) {
this.modelSizeStats = modelSizeStats.build();
return this;
}
public Builder setModelSizeStats(ModelSizeStats modelSizeStats) {
this.modelSizeStats = modelSizeStats;
return this;
}
public Builder setLatestRecordTimeStamp(Date latestRecordTimeStamp) {
this.latestRecordTimeStamp = latestRecordTimeStamp;
return this;
}
public Builder setLatestResultTimeStamp(Date latestResultTimeStamp) {
this.latestResultTimeStamp = latestResultTimeStamp;
return this;
}
public Builder setQuantiles(Quantiles quantiles) {
this.quantiles = quantiles;
return this;
}
public ModelSnapshot build() {
return new ModelSnapshot(jobId, timestamp, description, snapshotId, snapshotDocCount, modelSizeStats, latestRecordTimeStamp,
latestResultTimeStamp, quantiles);
}
}
}

View File

@ -60,14 +60,14 @@ public class Quantiles extends ToXContentToBytes implements Writeable {
public Quantiles(StreamInput in) throws IOException {
jobId = in.readString();
timestamp = new Date(in.readLong());
timestamp = new Date(in.readVLong());
quantileState = in.readOptionalString();
}
@Override
public void writeTo(StreamOutput out) throws IOException {
out.writeString(jobId);
out.writeLong(timestamp.getTime());
out.writeVLong(timestamp.getTime());
out.writeOptionalString(quantileState);
}

View File

@ -13,9 +13,9 @@ import org.elasticsearch.common.io.stream.Writeable;
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.xpack.ml.job.process.autodetect.output.FlushAcknowledgement;
import org.elasticsearch.xpack.ml.job.process.autodetect.state.ModelSizeStats;
import org.elasticsearch.xpack.ml.job.process.autodetect.state.ModelSnapshot;
import org.elasticsearch.xpack.ml.job.process.autodetect.output.FlushAcknowledgement;
import org.elasticsearch.xpack.ml.job.process.autodetect.state.Quantiles;
import java.io.IOException;
@ -29,7 +29,8 @@ public class AutodetectResult extends ToXContentToBytes implements Writeable {
@SuppressWarnings("unchecked")
public static final ConstructingObjectParser<AutodetectResult, Void> PARSER = new ConstructingObjectParser<>(
TYPE.getPreferredName(), a -> new AutodetectResult((Bucket) a[0], (List<AnomalyRecord>) a[1], (List<Influencer>) a[2],
(Quantiles) a[3], (ModelSnapshot) a[4], a[5] == null ? null : ((ModelSizeStats.Builder) a[5]).build(),
(Quantiles) a[3], a[4] == null ? null : ((ModelSnapshot.Builder) a[4]).build(),
a[5] == null ? null : ((ModelSizeStats.Builder) a[5]).build(),
(ModelPlot) a[6], (CategoryDefinition) a[7], (FlushAcknowledgement) a[8]));
static {

View File

@ -8,10 +8,8 @@ package org.elasticsearch.xpack.ml.utils.time;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.mapper.DateFieldMapper;
import org.elasticsearch.xpack.ml.job.messages.Messages;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
public final class TimeUtils {
private TimeUtils() {

View File

@ -6,8 +6,9 @@
package org.elasticsearch.xpack.ml.action;
import org.elasticsearch.xpack.ml.action.GetModelSnapshotsAction.Response;
import org.elasticsearch.xpack.ml.job.process.autodetect.state.ModelSnapshot;
import org.elasticsearch.xpack.ml.action.util.QueryPage;
import org.elasticsearch.xpack.ml.job.process.autodetect.state.ModelSnapshot;
import org.elasticsearch.xpack.ml.job.process.autodetect.state.ModelSnapshotTests;
import org.elasticsearch.xpack.ml.support.AbstractStreamableTestCase;
import java.util.ArrayList;
@ -20,9 +21,7 @@ public class GetModelSnapshotsActionResponseTests extends AbstractStreamableTest
int listSize = randomInt(10);
List<ModelSnapshot> hits = new ArrayList<>(listSize);
for (int j = 0; j < listSize; j++) {
ModelSnapshot snapshot = new ModelSnapshot(randomAsciiOfLengthBetween(1, 20));
snapshot.setDescription(randomAsciiOfLengthBetween(1, 20));
hits.add(snapshot);
hits.add(ModelSnapshotTests.createRandomized());
}
QueryPage<ModelSnapshot> snapshots = new QueryPage<>(hits, listSize, ModelSnapshot.RESULTS_FIELD);
return new Response(snapshots);
@ -32,5 +31,4 @@ public class GetModelSnapshotsActionResponseTests extends AbstractStreamableTest
protected Response createBlankInstance() {
return new Response();
}
}

View File

@ -6,21 +6,18 @@
package org.elasticsearch.xpack.ml.action;
import org.elasticsearch.xpack.ml.action.UpdateModelSnapshotAction.Response;
import org.elasticsearch.xpack.ml.job.process.autodetect.state.ModelSnapshot;
import org.elasticsearch.xpack.ml.job.process.autodetect.state.ModelSnapshotTests;
import org.elasticsearch.xpack.ml.support.AbstractStreamableTestCase;
public class PutModelSnapshotDescriptionActionResponseTests extends AbstractStreamableTestCase<UpdateModelSnapshotAction.Response> {
@Override
protected Response createTestInstance() {
ModelSnapshot snapshot = new ModelSnapshot(randomAsciiOfLengthBetween(1, 20));
snapshot.setDescription(randomAsciiOfLengthBetween(1, 20));
return new Response(snapshot);
return new Response(ModelSnapshotTests.createRandomized());
}
@Override
protected Response createBlankInstance() {
return new Response();
}
}

View File

@ -6,16 +6,14 @@
package org.elasticsearch.xpack.ml.action;
import org.elasticsearch.xpack.ml.action.RevertModelSnapshotAction.Response;
import org.elasticsearch.xpack.ml.job.process.autodetect.state.ModelSnapshot;
import org.elasticsearch.xpack.ml.job.process.autodetect.state.ModelSnapshotTests;
import org.elasticsearch.xpack.ml.support.AbstractStreamableTestCase;
public class RevertModelSnapshotActionResponseTests extends AbstractStreamableTestCase<RevertModelSnapshotAction.Response> {
@Override
protected Response createTestInstance() {
ModelSnapshot modelSnapshot = new ModelSnapshot(randomAsciiOfLengthBetween(1, 20));
modelSnapshot.setDescription(randomAsciiOfLengthBetween(1, 20));
return new RevertModelSnapshotAction.Response(modelSnapshot);
return new RevertModelSnapshotAction.Response(ModelSnapshotTests.createRandomized());
}
@Override

View File

@ -53,7 +53,6 @@ import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import static org.mockito.Matchers.any;
@ -305,9 +304,7 @@ public class AutodetectResultProcessorIT extends ESSingleNodeTestCase {
}
private ModelSnapshot createModelSnapshot() {
ModelSnapshot snapshot = new ModelSnapshot(JOB_ID);
snapshot.setSnapshotId(randomAsciiOfLength(12));
return snapshot;
return new ModelSnapshot.Builder(JOB_ID).setSnapshotId(randomAsciiOfLength(12)).build();
}
private Quantiles createQuantiles() {

View File

@ -80,9 +80,8 @@ public class JobDataDeleterTests extends ESTestCase {
public void testDeleteModelSnapShot() {
String jobId = "foo";
ModelSnapshot snapshot = new ModelSnapshot(jobId);
snapshot.setSnapshotDocCount(5);
snapshot.setSnapshotId("snap-1");
ModelSnapshot snapshot = new ModelSnapshot.Builder(jobId).setSnapshotDocCount(5)
.setSnapshotId("snap-1").build();
BulkResponse bulkResponse = Mockito.mock(BulkResponse.class);
Client client = new MockClientBuilder("myCluster").prepareBulk(bulkResponse).build();

View File

@ -974,9 +974,7 @@ public class JobProviderTests extends ESTestCase {
JobProvider provider = createProvider(clientBuilder.build());
ModelSnapshot modelSnapshot = new ModelSnapshot(JOB_ID);
modelSnapshot.setSnapshotId("123");
modelSnapshot.setSnapshotDocCount(2);
ModelSnapshot modelSnapshot = new ModelSnapshot.Builder(JOB_ID).setSnapshotId("123").setSnapshotDocCount(2).build();
ByteArrayOutputStream stream = new ByteArrayOutputStream();

View File

@ -80,7 +80,7 @@ public class AutodetectProcessManagerTests extends ESTestCase {
private NormalizerFactory normalizerFactory;
private DataCounts dataCounts = new DataCounts("foo");
private ModelSnapshot modelSnapshot = new ModelSnapshot("foo");
private ModelSnapshot modelSnapshot = new ModelSnapshot.Builder("foo").build();
private Quantiles quantiles = new Quantiles("foo", new Date(), "state");
private Set<MlFilter> filters = new HashSet<>();
@ -164,7 +164,7 @@ public class AutodetectProcessManagerTests extends ESTestCase {
jobResultsPersister, jobDataCountsPersister, autodetectProcessFactory, normalizerFactory));
DataCounts dataCounts = new DataCounts("foo");
ModelSnapshot modelSnapshot = new ModelSnapshot("foo");
ModelSnapshot modelSnapshot = new ModelSnapshot.Builder("foo").build();
Quantiles quantiles = new Quantiles("foo", new Date(), "state");
Set<MlFilter> filters = new HashSet<>();
doAnswer(invocationOnMock -> {

View File

@ -262,8 +262,8 @@ public class AutoDetectResultProcessorTests extends ESTestCase {
AutoDetectResultProcessor.Context context = new AutoDetectResultProcessor.Context(JOB_ID, false, bulkBuilder);
context.deleteInterimRequired = false;
AutodetectResult result = mock(AutodetectResult.class);
ModelSnapshot modelSnapshot = new ModelSnapshot(JOB_ID);
modelSnapshot.setSnapshotId("a_snapshot_id");
ModelSnapshot modelSnapshot = new ModelSnapshot.Builder(JOB_ID)
.setSnapshotId("a_snapshot_id").build();
when(result.getModelSnapshot()).thenReturn(modelSnapshot);
processorUnderTest.processResult(context, result);

View File

@ -6,6 +6,7 @@
package org.elasticsearch.xpack.ml.job.process.autodetect.state;
import org.elasticsearch.common.io.stream.Writeable.Reader;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.xpack.ml.job.process.autodetect.state.ModelSizeStats.MemoryStatus;
import org.elasticsearch.xpack.ml.support.AbstractSerializingTestCase;
@ -46,6 +47,10 @@ public class ModelSizeStatsTests extends AbstractSerializingTestCase<ModelSizeSt
@Override
protected ModelSizeStats createTestInstance() {
return createRandomized();
}
public static ModelSizeStats createRandomized() {
ModelSizeStats.Builder stats = new ModelSizeStats.Builder("foo");
if (randomBoolean()) {
stats.setBucketAllocationFailuresCount(randomNonNegativeLong());
@ -63,10 +68,10 @@ public class ModelSizeStatsTests extends AbstractSerializingTestCase<ModelSizeSt
stats.setTotalPartitionFieldCount(randomNonNegativeLong());
}
if (randomBoolean()) {
stats.setLogTime(new Date(randomLong()));
stats.setLogTime(new Date(TimeValue.parseTimeValue(randomTimeValue(), "test").millis()));
}
if (randomBoolean()) {
stats.setTimestamp(new Date(randomLong()));
stats.setTimestamp(new Date(TimeValue.parseTimeValue(randomTimeValue(), "test").millis()));
}
if (randomBoolean()) {
stats.setMemoryStatus(randomFrom(MemoryStatus.values()));

View File

@ -6,10 +6,9 @@
package org.elasticsearch.xpack.ml.job.process.autodetect.state;
import org.elasticsearch.common.io.stream.Writeable.Reader;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.xpack.ml.job.process.autodetect.state.ModelSizeStats.MemoryStatus;
import org.elasticsearch.xpack.ml.support.AbstractSerializingTestCase;
import org.elasticsearch.xpack.ml.utils.time.TimeUtils;
import java.util.Date;
@ -21,117 +20,108 @@ public class ModelSnapshotTests extends AbstractSerializingTestCase<ModelSnapsho
private static final Date DEFAULT_LATEST_RESULT_TIMESTAMP = new Date(12345678901234L);
private static final Date DEFAULT_LATEST_RECORD_TIMESTAMP = new Date(12345678904321L);
public void testCopyBuilder() {
ModelSnapshot modelSnapshot1 = createFullyPopulated().build();
ModelSnapshot modelSnapshot2 = new ModelSnapshot.Builder(modelSnapshot1).build();
assertEquals(modelSnapshot1, modelSnapshot2);
}
public void testEquals_GivenSameObject() {
ModelSnapshot modelSnapshot = new ModelSnapshot(randomAsciiOfLengthBetween(1, 20));
ModelSnapshot modelSnapshot = createFullyPopulated().build();
assertTrue(modelSnapshot.equals(modelSnapshot));
}
public void testEquals_GivenObjectOfDifferentClass() {
ModelSnapshot modelSnapshot = new ModelSnapshot(randomAsciiOfLengthBetween(1, 20));
ModelSnapshot modelSnapshot = createFullyPopulated().build();
assertFalse(modelSnapshot.equals("a string"));
}
public void testEquals_GivenEqualModelSnapshots() {
ModelSnapshot modelSnapshot1 = createFullyPopulated();
ModelSnapshot modelSnapshot2 = createFullyPopulated();
modelSnapshot2.setTimestamp(modelSnapshot1.getTimestamp());
ModelSnapshot modelSnapshot1 = createFullyPopulated().build();
ModelSnapshot modelSnapshot2 = createFullyPopulated().build();
assertEquals(modelSnapshot1, modelSnapshot2);
assertEquals(modelSnapshot2, modelSnapshot1);
assertEquals(modelSnapshot1.hashCode(), modelSnapshot2.hashCode());
}
public void testEquals_GivenDifferentTimestamp() {
ModelSnapshot modelSnapshot1 = createFullyPopulated();
ModelSnapshot modelSnapshot2 = createFullyPopulated();
modelSnapshot2.setTimestamp(new Date(modelSnapshot2.getTimestamp().getTime() + 1));
ModelSnapshot modelSnapshot1 = createFullyPopulated().build();
ModelSnapshot modelSnapshot2 = createFullyPopulated().setTimestamp(
new Date(modelSnapshot1.getTimestamp().getTime() + 1)).build();
assertFalse(modelSnapshot1.equals(modelSnapshot2));
assertFalse(modelSnapshot2.equals(modelSnapshot1));
}
public void testEquals_GivenDifferentDescription() {
ModelSnapshot modelSnapshot1 = createFullyPopulated();
ModelSnapshot modelSnapshot2 = createFullyPopulated();
modelSnapshot2.setDescription(modelSnapshot2.getDescription() + " blah");
ModelSnapshot modelSnapshot1 = createFullyPopulated().build();
ModelSnapshot modelSnapshot2 = createFullyPopulated()
.setDescription(modelSnapshot1.getDescription() + " blah").build();
assertFalse(modelSnapshot1.equals(modelSnapshot2));
assertFalse(modelSnapshot2.equals(modelSnapshot1));
}
public void testEquals_GivenDifferentId() {
ModelSnapshot modelSnapshot1 = createFullyPopulated();
ModelSnapshot modelSnapshot2 = createFullyPopulated();
modelSnapshot2.setSnapshotId(modelSnapshot2.getSnapshotId() + "_2");
ModelSnapshot modelSnapshot1 = createFullyPopulated().build();
ModelSnapshot modelSnapshot2 = createFullyPopulated()
.setSnapshotId(modelSnapshot1.getSnapshotId() + "_2").build();
assertFalse(modelSnapshot1.equals(modelSnapshot2));
assertFalse(modelSnapshot2.equals(modelSnapshot1));
}
public void testEquals_GivenDifferentDocCount() {
ModelSnapshot modelSnapshot1 = createFullyPopulated();
ModelSnapshot modelSnapshot2 = createFullyPopulated();
modelSnapshot2.setSnapshotDocCount(modelSnapshot2.getSnapshotDocCount() + 1);
ModelSnapshot modelSnapshot1 = createFullyPopulated().build();
ModelSnapshot modelSnapshot2 = createFullyPopulated()
.setSnapshotDocCount(modelSnapshot1.getSnapshotDocCount() + 1).build();
assertFalse(modelSnapshot1.equals(modelSnapshot2));
assertFalse(modelSnapshot2.equals(modelSnapshot1));
}
public void testEquals_GivenDifferentModelSizeStats() {
ModelSnapshot modelSnapshot1 = createFullyPopulated();
ModelSnapshot modelSnapshot2 = createFullyPopulated();
ModelSnapshot modelSnapshot1 = createFullyPopulated().build();
ModelSizeStats.Builder modelSizeStats = new ModelSizeStats.Builder("foo");
modelSizeStats.setModelBytes(42L);
modelSnapshot2.setModelSizeStats(modelSizeStats);
ModelSnapshot modelSnapshot2 = createFullyPopulated().setModelSizeStats(modelSizeStats).build();
assertFalse(modelSnapshot1.equals(modelSnapshot2));
assertFalse(modelSnapshot2.equals(modelSnapshot1));
}
public void testEquals_GivenDifferentQuantiles() {
ModelSnapshot modelSnapshot1 = createFullyPopulated();
ModelSnapshot modelSnapshot2 = createFullyPopulated();
modelSnapshot2.setQuantiles(new Quantiles("foo", modelSnapshot2.getQuantiles().getTimestamp(), "different state"));
ModelSnapshot modelSnapshot1 = createFullyPopulated().build();
ModelSnapshot modelSnapshot2 = createFullyPopulated()
.setQuantiles(new Quantiles("foo", modelSnapshot1.getQuantiles().getTimestamp(),
"different state")).build();
assertFalse(modelSnapshot1.equals(modelSnapshot2));
assertFalse(modelSnapshot2.equals(modelSnapshot1));
}
public void testEquals_GivenDifferentLatestResultTimestamp() {
ModelSnapshot modelSnapshot1 = createFullyPopulated();
ModelSnapshot modelSnapshot2 = createFullyPopulated();
modelSnapshot2.setLatestResultTimeStamp(
new Date(modelSnapshot2.getLatestResultTimeStamp().getTime() + 1));
ModelSnapshot modelSnapshot1 = createFullyPopulated().build();
ModelSnapshot modelSnapshot2 = createFullyPopulated().setLatestResultTimeStamp(
new Date(modelSnapshot1.getLatestResultTimeStamp().getTime() + 1)).build();
assertFalse(modelSnapshot1.equals(modelSnapshot2));
assertFalse(modelSnapshot2.equals(modelSnapshot1));
}
public void testEquals_GivenDifferentLatestRecordTimestamp() {
ModelSnapshot modelSnapshot1 = createFullyPopulated();
ModelSnapshot modelSnapshot2 = createFullyPopulated();
modelSnapshot2.setLatestRecordTimeStamp(
new Date(modelSnapshot2.getLatestRecordTimeStamp().getTime() + 1));
ModelSnapshot modelSnapshot1 = createFullyPopulated().build();
ModelSnapshot modelSnapshot2 = createFullyPopulated().setLatestRecordTimeStamp(
new Date(modelSnapshot1.getLatestRecordTimeStamp().getTime() + 1)).build();
assertFalse(modelSnapshot1.equals(modelSnapshot2));
assertFalse(modelSnapshot2.equals(modelSnapshot1));
}
private static ModelSnapshot createFullyPopulated() {
ModelSnapshot modelSnapshot = new ModelSnapshot("foo");
private static ModelSnapshot.Builder createFullyPopulated() {
ModelSnapshot.Builder modelSnapshot = new ModelSnapshot.Builder();
modelSnapshot.setJobId("foo");
modelSnapshot.setTimestamp(DEFAULT_TIMESTAMP);
modelSnapshot.setDescription(DEFAULT_DESCRIPTION);
modelSnapshot.setSnapshotId(DEFAULT_ID);
@ -147,46 +137,22 @@ public class ModelSnapshotTests extends AbstractSerializingTestCase<ModelSnapsho
@Override
protected ModelSnapshot createTestInstance() {
ModelSnapshot modelSnapshot = new ModelSnapshot(randomAsciiOfLengthBetween(1, 20));
modelSnapshot.setTimestamp(new Date(TimeUtils.dateStringToEpoch(randomTimeValue())));
return createRandomized();
}
public static ModelSnapshot createRandomized() {
ModelSnapshot.Builder modelSnapshot = new ModelSnapshot.Builder(randomAsciiOfLengthBetween(1, 20));
modelSnapshot.setTimestamp(new Date(TimeValue.parseTimeValue(randomTimeValue(), "test").millis()));
modelSnapshot.setDescription(randomAsciiOfLengthBetween(1, 20));
modelSnapshot.setSnapshotId(randomAsciiOfLengthBetween(1, 20));
modelSnapshot.setSnapshotDocCount(randomInt());
ModelSizeStats.Builder stats = new ModelSizeStats.Builder(randomAsciiOfLengthBetween(1, 20));
if (randomBoolean()) {
stats.setBucketAllocationFailuresCount(randomNonNegativeLong());
}
if (randomBoolean()) {
stats.setModelBytes(randomNonNegativeLong());
}
if (randomBoolean()) {
stats.setTotalByFieldCount(randomNonNegativeLong());
}
if (randomBoolean()) {
stats.setTotalOverFieldCount(randomNonNegativeLong());
}
if (randomBoolean()) {
stats.setTotalPartitionFieldCount(randomNonNegativeLong());
}
if (randomBoolean()) {
stats.setLogTime(new Date(randomLong()));
}
if (randomBoolean()) {
stats.setTimestamp(new Date(randomLong()));
}
if (randomBoolean()) {
stats.setMemoryStatus(randomFrom(MemoryStatus.values()));
}
if (randomBoolean()) {
stats.setId(randomAsciiOfLengthBetween(1, 20));
}
modelSnapshot.setModelSizeStats(stats);
modelSnapshot.setLatestResultTimeStamp(new Date(TimeUtils.dateStringToEpoch(randomTimeValue())));
modelSnapshot.setLatestRecordTimeStamp(new Date(TimeUtils.dateStringToEpoch(randomTimeValue())));
Quantiles quantiles =
new Quantiles("foo", new Date(TimeUtils.dateStringToEpoch(randomTimeValue())), randomAsciiOfLengthBetween(0, 1000));
modelSnapshot.setQuantiles(quantiles);
return modelSnapshot;
modelSnapshot.setModelSizeStats(ModelSizeStatsTests.createRandomized());
modelSnapshot.setLatestResultTimeStamp(
new Date(TimeValue.parseTimeValue(randomTimeValue(), "test").millis()));
modelSnapshot.setLatestRecordTimeStamp(
new Date(TimeValue.parseTimeValue(randomTimeValue(), "test").millis()));
modelSnapshot.setQuantiles(QuantilesTests.createRandomized());
return modelSnapshot.build();
}
@Override
@ -196,16 +162,13 @@ public class ModelSnapshotTests extends AbstractSerializingTestCase<ModelSnapsho
@Override
protected ModelSnapshot parseInstance(XContentParser parser) {
return ModelSnapshot.PARSER.apply(parser, null);
return ModelSnapshot.PARSER.apply(parser, null).build();
}
public void testDocumentId() {
ModelSnapshot snapshot1 = new ModelSnapshot("foo");
snapshot1.setSnapshotId("1");
ModelSnapshot snapshot2 = new ModelSnapshot("foo");
snapshot2.setSnapshotId("2");
ModelSnapshot snapshot3 = new ModelSnapshot("bar");
snapshot3.setSnapshotId("1");
ModelSnapshot snapshot1 = new ModelSnapshot.Builder("foo").setSnapshotId("1").build();
ModelSnapshot snapshot2 = new ModelSnapshot.Builder("foo").setSnapshotId("2").build();
ModelSnapshot snapshot3 = new ModelSnapshot.Builder("bar").setSnapshotId("1").build();
assertEquals("foo-1", ModelSnapshot.documentId(snapshot1));
assertEquals("foo-2", ModelSnapshot.documentId(snapshot2));

View File

@ -6,6 +6,7 @@
package org.elasticsearch.xpack.ml.job.process.autodetect.state;
import org.elasticsearch.common.io.stream.Writeable.Reader;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.xpack.ml.support.AbstractSerializingTestCase;
@ -56,8 +57,13 @@ public class QuantilesTests extends AbstractSerializingTestCase<Quantiles> {
@Override
protected Quantiles createTestInstance() {
Quantiles quantiles = new Quantiles("foo", new Date(randomLong()), randomAsciiOfLengthBetween(0, 1000));
return quantiles;
return createRandomized();
}
public static Quantiles createRandomized() {
return new Quantiles(randomAsciiOfLengthBetween(1, 20),
new Date(TimeValue.parseTimeValue(randomTimeValue(), "test").millis()),
randomAsciiOfLengthBetween(0, 1000));
}
@Override

View File

@ -10,7 +10,9 @@ import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.xpack.ml.job.process.autodetect.state.ModelSizeStats;
import org.elasticsearch.xpack.ml.job.process.autodetect.state.ModelSnapshot;
import org.elasticsearch.xpack.ml.job.process.autodetect.output.FlushAcknowledgement;
import org.elasticsearch.xpack.ml.job.process.autodetect.state.ModelSnapshotTests;
import org.elasticsearch.xpack.ml.job.process.autodetect.state.Quantiles;
import org.elasticsearch.xpack.ml.job.process.autodetect.state.QuantilesTests;
import org.elasticsearch.xpack.ml.support.AbstractSerializingTestCase;
import java.util.ArrayList;
@ -62,13 +64,12 @@ public class AutodetectResultTests extends AbstractSerializingTestCase<Autodetec
}
}
if (randomBoolean()) {
quantiles = new Quantiles(jobId, new Date(randomLong()), randomAsciiOfLengthBetween(1, 20));
quantiles = QuantilesTests.createRandomized();
} else {
quantiles = null;
}
if (randomBoolean()) {
modelSnapshot = new ModelSnapshot(jobId);
modelSnapshot.setDescription(randomAsciiOfLengthBetween(1, 20));
modelSnapshot = ModelSnapshotTests.createRandomized();
} else {
modelSnapshot = null;
}

View File

@ -204,9 +204,7 @@ public class ExpiredModelSnapshotsRemoverTests extends ESTestCase {
}
private static ModelSnapshot createModelSnapshot(String jobId, String snapshotId) {
ModelSnapshot modelSnapshot = new ModelSnapshot(jobId);
modelSnapshot.setSnapshotId(snapshotId);
return modelSnapshot;
return new ModelSnapshot.Builder(jobId).setSnapshotId(snapshotId).build();
}
private static SearchResponse createSearchResponse(List<ModelSnapshot> modelSnapshots) throws IOException {

View File

@ -31,12 +31,12 @@ public class GetModelSnapshotsTests extends ESTestCase {
}
public void testModelSnapshots_clearQuantiles() {
ModelSnapshot m1 = new ModelSnapshot("jobId");
m1.setQuantiles(new Quantiles("jobId", new Date(), "quantileState"));
ModelSnapshot m2 = new ModelSnapshot("jobId");
ModelSnapshot m1 = new ModelSnapshot.Builder("jobId").setQuantiles(
new Quantiles("jobId", new Date(), "quantileState")).build();
ModelSnapshot m2 = new ModelSnapshot.Builder("jobId").build();
QueryPage<ModelSnapshot> page = new QueryPage<>(Arrays.asList(m1, m2), 2, new ParseField("field"));
GetModelSnapshotsAction.TransportAction.clearQuantiles(page);
page = GetModelSnapshotsAction.TransportAction.clearQuantiles(page);
assertEquals(2, page.results().size());
for (ModelSnapshot modelSnapshot : page.results()) {
assertNull(modelSnapshot.getQuantiles());