[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.io.IOException;
import java.util.Objects; import java.util.Objects;
import java.util.stream.Collectors;
public class GetModelSnapshotsAction public class GetModelSnapshotsAction
extends Action<GetModelSnapshotsAction.Request, GetModelSnapshotsAction.Response, GetModelSnapshotsAction.RequestBuilder> { 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.getStart(), request.getEnd(), request.getSort(), request.getDescOrder(), request.getSnapshotId(),
request.getDescriptionString(), request.getDescriptionString(),
page -> { page -> {
clearQuantiles(page); listener.onResponse(new Response(clearQuantiles(page)));
listener.onResponse(new Response(page));
}, listener::onFailure); }, listener::onFailure);
} }
public static void clearQuantiles(QueryPage<ModelSnapshot> page) { public static QueryPage<ModelSnapshot> clearQuantiles(QueryPage<ModelSnapshot> page) {
if (page.results() != null) { if (page.results() == null) {
for (ModelSnapshot modelSnapshot : page.results()) { return page;
modelSnapshot.setQuantiles(null); }
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.io.IOException;
import java.util.Date; import java.util.Date;
import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.function.Consumer; 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 - // 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 // it's clearer to remove them as they are not necessary for the revert op
modelSnapshot.setQuantiles(null); handler.accept(new ModelSnapshot.Builder(modelSnapshot).setQuantiles(null).build());
handler.accept(modelSnapshot);
}, errorHandler); }, errorHandler);
} }

View File

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

View File

@ -80,6 +80,10 @@ public final class QueryPage<T extends ToXContent & Writeable> extends ToXConten
return count; return count;
} }
public ParseField getResultsField() {
return resultsField;
}
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(results, count); 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) { public void dataCounts(String jobId, Consumer<DataCounts> handler, Consumer<Exception> errorHandler) {
String indexName = AnomalyDetectorsIndex.jobResultsAliasedName(jobId); 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)); 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) { BiFunction<XContentParser, U, T> objectParser, Supplier<T> notFoundSupplier) {
GetRequest getRequest = new GetRequest(indexName, type, id); GetRequest getRequest = new GetRequest(indexName, type, id);
client.get(getRequest, ActionListener.wrap( client.get(getRequest, ActionListener.wrap(
@ -758,7 +758,7 @@ public class JobProvider {
String indexName = AnomalyDetectorsIndex.jobStateIndexName(); String indexName = AnomalyDetectorsIndex.jobStateIndexName();
String quantilesId = Quantiles.documentId(jobId); String quantilesId = Quantiles.documentId(jobId);
LOGGER.trace("ES API CALL: get ID {} type {} from index {}", quantilesId, Quantiles.TYPE.getPreferredName(), indexName); 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); LOGGER.info("There are currently no quantiles for job " + jobId);
return null; return null;
}); });
@ -773,8 +773,9 @@ public class JobProvider {
handler.accept(null); handler.accept(null);
return; return;
} }
get(jobId, AnomalyDetectorsIndex.jobResultsAliasedName(jobId), ModelSnapshot.TYPE.getPreferredName(), get(AnomalyDetectorsIndex.jobResultsAliasedName(jobId), ModelSnapshot.TYPE.getPreferredName(),
ModelSnapshot.documentId(jobId, modelSnapshotId), handler, errorHandler, ModelSnapshot.PARSER, () -> null); 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); ModelSizeStats.RESULT_TYPE_VALUE, ModelSizeStats.RESULT_TYPE_FIELD, jobId);
String indexName = AnomalyDetectorsIndex.jobResultsAliasedName(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(), handler, errorHandler, (parser, context) -> ModelSizeStats.PARSER.apply(parser, null).build(),
() -> { () -> {
LOGGER.trace("No memory usage details for job with id {}", jobId); 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(); totalPartitionFieldCount = in.readVLong();
bucketAllocationFailuresCount = in.readVLong(); bucketAllocationFailuresCount = in.readVLong();
memoryStatus = MemoryStatus.readFromStream(in); memoryStatus = MemoryStatus.readFromStream(in);
logTime = new Date(in.readLong()); logTime = new Date(in.readVLong());
timestamp = in.readBoolean() ? new Date(in.readLong()) : null; timestamp = in.readBoolean() ? new Date(in.readVLong()) : null;
} }
@Override @Override
@ -159,11 +159,11 @@ public class ModelSizeStats extends ToXContentToBytes implements Writeable {
out.writeVLong(totalPartitionFieldCount); out.writeVLong(totalPartitionFieldCount);
out.writeVLong(bucketAllocationFailuresCount); out.writeVLong(bucketAllocationFailuresCount);
memoryStatus.writeTo(out); memoryStatus.writeTo(out);
out.writeLong(logTime.getTime()); out.writeVLong(logTime.getTime());
boolean hasTimestamp = timestamp != null; boolean hasTimestamp = timestamp != null;
out.writeBoolean(hasTimestamp); out.writeBoolean(hasTimestamp);
if (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.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.io.stream.Writeable; import org.elasticsearch.common.io.stream.Writeable;
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
import org.elasticsearch.common.xcontent.NamedXContentRegistry; import org.elasticsearch.common.xcontent.NamedXContentRegistry;
import org.elasticsearch.common.xcontent.ObjectParser;
import org.elasticsearch.common.xcontent.ObjectParser.ValueType; import org.elasticsearch.common.xcontent.ObjectParser.ValueType;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory; 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 ParseField TYPE = new ParseField("model_snapshot");
public static final ConstructingObjectParser<ModelSnapshot, Void> PARSER = public static final ObjectParser<Builder, Void> PARSER = new ObjectParser<>(TYPE.getPreferredName(), Builder::new);
new ConstructingObjectParser<>(TYPE.getPreferredName(), a -> new ModelSnapshot((String) a[0]));
static { static {
PARSER.declareString(ConstructingObjectParser.constructorArg(), Job.ID); PARSER.declareString(Builder::setJobId, Job.ID);
PARSER.declareField(ModelSnapshot::setTimestamp, p -> { PARSER.declareField(Builder::setTimestamp, p -> {
if (p.currentToken() == Token.VALUE_NUMBER) { if (p.currentToken() == Token.VALUE_NUMBER) {
return new Date(p.longValue()); return new Date(p.longValue());
} else if (p.currentToken() == Token.VALUE_STRING) { } 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() + "]"); throw new IllegalArgumentException("unexpected token [" + p.currentToken() + "] for [" + TIMESTAMP.getPreferredName() + "]");
}, TIMESTAMP, ValueType.VALUE); }, TIMESTAMP, ValueType.VALUE);
PARSER.declareString(ModelSnapshot::setDescription, DESCRIPTION); PARSER.declareString(Builder::setDescription, DESCRIPTION);
PARSER.declareString(ModelSnapshot::setSnapshotId, SNAPSHOT_ID); PARSER.declareString(Builder::setSnapshotId, SNAPSHOT_ID);
PARSER.declareInt(ModelSnapshot::setSnapshotDocCount, SNAPSHOT_DOC_COUNT); PARSER.declareInt(Builder::setSnapshotDocCount, SNAPSHOT_DOC_COUNT);
PARSER.declareObject(ModelSnapshot::setModelSizeStats, ModelSizeStats.PARSER, ModelSizeStats.RESULT_TYPE_FIELD); PARSER.declareObject(Builder::setModelSizeStats, ModelSizeStats.PARSER, ModelSizeStats.RESULT_TYPE_FIELD);
PARSER.declareField(ModelSnapshot::setLatestRecordTimeStamp, p -> { PARSER.declareField(Builder::setLatestRecordTimeStamp, p -> {
if (p.currentToken() == Token.VALUE_NUMBER) { if (p.currentToken() == Token.VALUE_NUMBER) {
return new Date(p.longValue()); return new Date(p.longValue());
} else if (p.currentToken() == Token.VALUE_STRING) { } else if (p.currentToken() == Token.VALUE_STRING) {
@ -75,7 +74,7 @@ public class ModelSnapshot extends ToXContentToBytes implements Writeable {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"unexpected token [" + p.currentToken() + "] for [" + LATEST_RECORD_TIME.getPreferredName() + "]"); "unexpected token [" + p.currentToken() + "] for [" + LATEST_RECORD_TIME.getPreferredName() + "]");
}, LATEST_RECORD_TIME, ValueType.VALUE); }, LATEST_RECORD_TIME, ValueType.VALUE);
PARSER.declareField(ModelSnapshot::setLatestResultTimeStamp, p -> { PARSER.declareField(Builder::setLatestResultTimeStamp, p -> {
if (p.currentToken() == Token.VALUE_NUMBER) { if (p.currentToken() == Token.VALUE_NUMBER) {
return new Date(p.longValue()); return new Date(p.longValue());
} else if (p.currentToken() == Token.VALUE_STRING) { } else if (p.currentToken() == Token.VALUE_STRING) {
@ -84,76 +83,70 @@ public class ModelSnapshot extends ToXContentToBytes implements Writeable {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"unexpected token [" + p.currentToken() + "] for [" + LATEST_RESULT_TIME.getPreferredName() + "]"); "unexpected token [" + p.currentToken() + "] for [" + LATEST_RESULT_TIME.getPreferredName() + "]");
}, LATEST_RESULT_TIME, ValueType.VALUE); }, 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 final String jobId;
private Date timestamp; private final Date timestamp;
private String description; private final String description;
private String snapshotId; private final String snapshotId;
private int snapshotDocCount; private final int snapshotDocCount;
private ModelSizeStats modelSizeStats; private final ModelSizeStats modelSizeStats;
private Date latestRecordTimeStamp; private final Date latestRecordTimeStamp;
private Date latestResultTimeStamp; private final Date latestResultTimeStamp;
private Quantiles quantiles; 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.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 { public ModelSnapshot(StreamInput in) throws IOException {
jobId = in.readString(); jobId = in.readString();
if (in.readBoolean()) { timestamp = in.readBoolean() ? new Date(in.readVLong()) : null;
timestamp = new Date(in.readLong());
}
description = in.readOptionalString(); description = in.readOptionalString();
snapshotId = in.readOptionalString(); snapshotId = in.readOptionalString();
snapshotDocCount = in.readInt(); snapshotDocCount = in.readInt();
if (in.readBoolean()) { modelSizeStats = in.readOptionalWriteable(ModelSizeStats::new);
modelSizeStats = new ModelSizeStats(in); latestRecordTimeStamp = in.readBoolean() ? new Date(in.readVLong()) : null;
} latestResultTimeStamp = in.readBoolean() ? new Date(in.readVLong()) : null;
if (in.readBoolean()) { quantiles = in.readOptionalWriteable(Quantiles::new);
latestRecordTimeStamp = new Date(in.readLong());
}
if (in.readBoolean()) {
latestResultTimeStamp = new Date(in.readLong());
}
if (in.readBoolean()) {
quantiles = new Quantiles(in);
}
} }
@Override @Override
public void writeTo(StreamOutput out) throws IOException { public void writeTo(StreamOutput out) throws IOException {
out.writeString(jobId); out.writeString(jobId);
boolean hasTimestamp = timestamp != null; if (timestamp != null) {
out.writeBoolean(hasTimestamp); out.writeBoolean(true);
if (hasTimestamp) { out.writeVLong(timestamp.getTime());
out.writeLong(timestamp.getTime()); } else {
out.writeBoolean(false);
} }
out.writeOptionalString(description); out.writeOptionalString(description);
out.writeOptionalString(snapshotId); out.writeOptionalString(snapshotId);
out.writeInt(snapshotDocCount); out.writeInt(snapshotDocCount);
boolean hasModelSizeStats = modelSizeStats != null; out.writeOptionalWriteable(modelSizeStats);
out.writeBoolean(hasModelSizeStats); if (latestRecordTimeStamp != null) {
if (hasModelSizeStats) { out.writeBoolean(true);
modelSizeStats.writeTo(out); out.writeVLong(latestRecordTimeStamp.getTime());
} else {
out.writeBoolean(false);
} }
boolean hasLatestRecordTimeStamp = latestRecordTimeStamp != null; if (latestResultTimeStamp != null) {
out.writeBoolean(hasLatestRecordTimeStamp); out.writeBoolean(true);
if (hasLatestRecordTimeStamp) { out.writeVLong(latestResultTimeStamp.getTime());
out.writeLong(latestRecordTimeStamp.getTime()); } else {
} out.writeBoolean(false);
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);
} }
out.writeOptionalWriteable(quantiles);
} }
@Override @Override
@ -196,66 +189,34 @@ public class ModelSnapshot extends ToXContentToBytes implements Writeable {
return timestamp; return timestamp;
} }
public void setTimestamp(Date timestamp) {
this.timestamp = timestamp;
}
public String getDescription() { public String getDescription() {
return description; return description;
} }
public void setDescription(String description) {
this.description = description;
}
public String getSnapshotId() { public String getSnapshotId() {
return snapshotId; return snapshotId;
} }
public void setSnapshotId(String snapshotId) {
this.snapshotId = snapshotId;
}
public int getSnapshotDocCount() { public int getSnapshotDocCount() {
return snapshotDocCount; return snapshotDocCount;
} }
public void setSnapshotDocCount(int snapshotDocCount) {
this.snapshotDocCount = snapshotDocCount;
}
public ModelSizeStats getModelSizeStats() { public ModelSizeStats getModelSizeStats() {
return modelSizeStats; return modelSizeStats;
} }
public void setModelSizeStats(ModelSizeStats.Builder modelSizeStats) {
this.modelSizeStats = modelSizeStats.build();
}
public Quantiles getQuantiles() { public Quantiles getQuantiles() {
return quantiles; return quantiles;
} }
public void setQuantiles(Quantiles q) {
quantiles = q;
}
public Date getLatestRecordTimeStamp() { public Date getLatestRecordTimeStamp() {
return latestRecordTimeStamp; return latestRecordTimeStamp;
} }
public void setLatestRecordTimeStamp(Date latestRecordTimeStamp) {
this.latestRecordTimeStamp = latestRecordTimeStamp;
}
public Date getLatestResultTimeStamp() { public Date getLatestResultTimeStamp() {
return latestResultTimeStamp; return latestResultTimeStamp;
} }
public void setLatestResultTimeStamp(Date latestResultTimeStamp) {
this.latestResultTimeStamp = latestResultTimeStamp;
}
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(jobId, timestamp, description, snapshotId, quantiles, snapshotDocCount, modelSizeStats, latestRecordTimeStamp, 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) { public static ModelSnapshot fromJson(BytesReference bytesReference) {
try (XContentParser parser = XContentFactory.xContent(bytesReference).createParser(NamedXContentRegistry.EMPTY, 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) { } catch (IOException e) {
throw new ElasticsearchParseException("failed to parse modelSnapshot", 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 { public Quantiles(StreamInput in) throws IOException {
jobId = in.readString(); jobId = in.readString();
timestamp = new Date(in.readLong()); timestamp = new Date(in.readVLong());
quantileState = in.readOptionalString(); quantileState = in.readOptionalString();
} }
@Override @Override
public void writeTo(StreamOutput out) throws IOException { public void writeTo(StreamOutput out) throws IOException {
out.writeString(jobId); out.writeString(jobId);
out.writeLong(timestamp.getTime()); out.writeVLong(timestamp.getTime());
out.writeOptionalString(quantileState); 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.ConstructingObjectParser;
import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder; 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.ModelSizeStats;
import org.elasticsearch.xpack.ml.job.process.autodetect.state.ModelSnapshot; 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 org.elasticsearch.xpack.ml.job.process.autodetect.state.Quantiles;
import java.io.IOException; import java.io.IOException;
@ -29,7 +29,8 @@ public class AutodetectResult extends ToXContentToBytes implements Writeable {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static final ConstructingObjectParser<AutodetectResult, Void> PARSER = new ConstructingObjectParser<>( 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], 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])); (ModelPlot) a[6], (CategoryDefinition) a[7], (FlushAcknowledgement) a[8]));
static { static {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -6,6 +6,7 @@
package org.elasticsearch.xpack.ml.job.process.autodetect.state; package org.elasticsearch.xpack.ml.job.process.autodetect.state;
import org.elasticsearch.common.io.stream.Writeable.Reader; import org.elasticsearch.common.io.stream.Writeable.Reader;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.xpack.ml.support.AbstractSerializingTestCase; import org.elasticsearch.xpack.ml.support.AbstractSerializingTestCase;
@ -56,8 +57,13 @@ public class QuantilesTests extends AbstractSerializingTestCase<Quantiles> {
@Override @Override
protected Quantiles createTestInstance() { protected Quantiles createTestInstance() {
Quantiles quantiles = new Quantiles("foo", new Date(randomLong()), randomAsciiOfLengthBetween(0, 1000)); return createRandomized();
return quantiles; }
public static Quantiles createRandomized() {
return new Quantiles(randomAsciiOfLengthBetween(1, 20),
new Date(TimeValue.parseTimeValue(randomTimeValue(), "test").millis()),
randomAsciiOfLengthBetween(0, 1000));
} }
@Override @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.ModelSizeStats;
import org.elasticsearch.xpack.ml.job.process.autodetect.state.ModelSnapshot; 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.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.Quantiles;
import org.elasticsearch.xpack.ml.job.process.autodetect.state.QuantilesTests;
import org.elasticsearch.xpack.ml.support.AbstractSerializingTestCase; import org.elasticsearch.xpack.ml.support.AbstractSerializingTestCase;
import java.util.ArrayList; import java.util.ArrayList;
@ -62,13 +64,12 @@ public class AutodetectResultTests extends AbstractSerializingTestCase<Autodetec
} }
} }
if (randomBoolean()) { if (randomBoolean()) {
quantiles = new Quantiles(jobId, new Date(randomLong()), randomAsciiOfLengthBetween(1, 20)); quantiles = QuantilesTests.createRandomized();
} else { } else {
quantiles = null; quantiles = null;
} }
if (randomBoolean()) { if (randomBoolean()) {
modelSnapshot = new ModelSnapshot(jobId); modelSnapshot = ModelSnapshotTests.createRandomized();
modelSnapshot.setDescription(randomAsciiOfLengthBetween(1, 20));
} else { } else {
modelSnapshot = null; modelSnapshot = null;
} }

View File

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

View File

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