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

com.couchbase.transactions.log.PersistedLogWriter Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2021 Couchbase, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.couchbase.transactions.log;

import com.couchbase.client.core.annotation.Stability;
import com.couchbase.client.java.Collection;
import com.couchbase.client.java.json.JsonObject;
import com.couchbase.client.java.kv.MutateInMacro;
import com.couchbase.client.java.kv.MutateInOptions;
import com.couchbase.client.java.kv.MutateInSpec;
import com.couchbase.client.java.kv.StoreSemantics;
import reactor.core.publisher.Mono;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;

import static com.couchbase.transactions.components.SerializationUtil.DEFAULT_JSON_SERIALIZER;

/**
 * Implements a persisted log for [LOG-PERSIST].
 *
 * @author Graham Pople
 * @since 1.0.0
 */
@Stability.Internal
public class PersistedLogWriter {
    public static final String PERSISTED_LOG_DOC_ID = "txn-log";
    // At about 100 bytes per log on average gives 10MB
    // Hopefully enough to be able to debug useful problems without overfilling the doc
    public static final int MAX_LOG_ENTRIES_DEFAULT = 100000;
    private final Collection collection;
    private final int maxEntries;
    private boolean compactionRequired;

    public PersistedLogWriter(Collection collection, int maxEntries) {
        this.collection = collection;
        this.maxEntries = maxEntries;
    }

    public Mono write(String clientUuid, String v) {
        JsonObject obj = JsonObject.create()
                .put("v", v)
                .put("u", clientUuid)
                .put("t", LocalDateTime.now().toString());

        ArrayList ops = new ArrayList<>();
        MutateInOptions opts = MutateInOptions.mutateInOptions().serializer(DEFAULT_JSON_SERIALIZER);

        if (compactionRequired) {
            // 16 ops are allowed total, we need 3, fill the rest with removes
            int NUMBER_OF_SUBDOC_OPS_REMAINING = 13;

            // Adjust the count.  We're removing a bunch, adding one.
            ops.add(MutateInSpec.decrement("l.count", NUMBER_OF_SUBDOC_OPS_REMAINING - 1).xattr().createPath());

            for (int i = 0; i < 13; i++) {
                ops.add(MutateInSpec.remove("l.logs[" + 0 + "]").xattr());
            }

            compactionRequired = false;
        } else {
            ops.add(MutateInSpec.increment("l.count", 1).xattr().createPath());

            // Can't use this option at same time as removing a log, unclear why.  But if compaction is required, document should
            // exist anyway.
            opts.storeSemantics(StoreSemantics.UPSERT);
        }

        ops.add(MutateInSpec.arrayAppend("l.logs", Arrays.asList(obj)).xattr().createPath());
        ops.add(MutateInSpec.upsert("l.logs[-1].c", MutateInMacro.CAS));


        return collection.reactive().mutateIn(PERSISTED_LOG_DOC_ID, ops, opts)

                .doOnNext(result -> {

                    try {
                        Integer count = result.contentAs(0, Integer.class);

                        if (count >= maxEntries) {
                            compactionRequired = true;
                        }
                    } catch (RuntimeException err) {
                    }
                })

                .then();
    }

    public boolean compactionRequired() {
        return compactionRequired;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy