All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.polyglotted.elastic.index.BulkRecord Maven / Gradle / Ivy

There is a newer version: 6.8.5
Show newest version
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