io.polyglotted.elastic.index.BulkRecord Maven / Gradle / Ivy
package io.polyglotted.elastic.index;
import io.polyglotted.common.model.MapResult;
import io.polyglotted.common.util.ListBuilder.ImmutableListBuilder;
import io.polyglotted.elastic.common.MetaFields;
import io.polyglotted.elastic.common.Notification;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.SneakyThrows;
import lombok.experimental.Accessors;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import static io.polyglotted.common.util.Assertions.checkBool;
import static io.polyglotted.common.util.CollUtil.transformList;
import static io.polyglotted.common.util.ListBuilder.immutableListBuilder;
import static io.polyglotted.common.util.MapBuilder.immutableMap;
import static io.polyglotted.common.util.MapBuilder.simpleMap;
import static io.polyglotted.elastic.common.DocStatus.PENDING;
import static io.polyglotted.elastic.common.MetaFields.id;
import static io.polyglotted.elastic.common.MetaFields.tstamp;
import static io.polyglotted.elastic.common.Notification.notificationBuilder;
import static io.polyglotted.elastic.index.ApprovalUtil.approvalModel;
import static io.polyglotted.elastic.index.IndexRecord.createRecord;
import static io.polyglotted.elastic.index.IndexRecord.saveRecord;
import static java.util.Objects.requireNonNull;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
@SuppressWarnings({"unused", "WeakerAccess", "UnusedReturnValue"})
@Accessors(fluent = true) @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
public final class BulkRecord {
public final String repo;
public final String model;
public final String parent;
public final List records;
public final IgnoreErrors ignoreErrors;
public final Validator validator;
private final Map actions = simpleMap();
@Getter private volatile boolean hasNoFailure = true;
@Getter @Setter private volatile Map indexMap = immutableMap();
public Notification notification() { return notification(null); }
public Notification notification(String realm) {
Notification.Builder builder = notificationBuilder().realm(realm);
records.forEach(rec -> builder.keyAction(rec.id, rec.simpleKey(), actions.get(rec.id)));
return builder.build();
}
@SneakyThrows public String toResult() {
XContentBuilder builder = jsonBuilder().startObject();
for (IndexRecord rec : records) { rec.toAction(builder, actions.get(rec.id)); }
return Strings.toString(builder.endObject());
}
public int size() { return records.size(); }
void actionWith(int index, String result) { actionWith(indexMap.get(index), result); }
void failureWith(String id, String result) { actionWith(id, result); hasNoFailure = false; }
void actionWith(String id, String result) { actions.put(id, result); }
public static Builder bulkBuilder(String repo, String model, long timestamp, String user) {
return new Builder(requireNonNull(repo), requireNonNull(model), timestamp, requireNonNull(user));
}
@RequiredArgsConstructor @Accessors(fluent = true, chain = true)
public static class Builder {
@NonNull private final String repo;
@NonNull private final String model;
private final long timestamp;
@NonNull private final String user;
@Setter private String parent;
@Setter private boolean hasApproval;
@Setter @NonNull private IgnoreErrors ignoreErrors = IgnoreErrors.STRICT;
@Setter @NonNull private Validator validator = Validator.STRICT;
private final ImmutableListBuilder records = immutableListBuilder();
public Builder hasApproval() { return hasApproval(true); }
public Builder record(IndexRecord.Builder record) { this.records.add(checkParent(record).userTs(user, timestamp)); return this; }
public Builder records(Iterable records) { for (IndexRecord.Builder rec : records) { this.record(rec); } return this; }
public Builder objects(Iterable docs) { for (MapResult doc : docs) { this.record(indexRec(doc)); } return this; }
public Builder objectsWith(Iterable docs, String pipeline) {
for (MapResult doc : docs) { this.record(indexRec(doc).pipeline(pipeline)); } return this;
}
private IndexRecord.Builder indexRec(MapResult doc) {
IndexRecord.Builder builder = hasApproval ? createRecord(repo, approvalModel(model), id(doc), MetaFields.parent(doc), doc)
.status(PENDING) : saveRecord(repo, model, id(doc), MetaFields.parent(doc), tstamp(doc), doc);
return builder.userTs(user, timestamp);
}
private IndexRecord.Builder checkParent(IndexRecord.Builder record) {
checkBool(Objects.equals(parent, record.parent), "bulk record cannot index child records for multiple parents"); return record;
}
public BulkRecord build() {
return new BulkRecord(repo, model, parent, transformList(records.build(), IndexRecord.Builder::build), ignoreErrors, validator);
}
}
private static boolean isChangeAction(String action) { return "created".equals(action) || "updated".equals(action) || "deleted".equals(action); }
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy