
com.couchbase.transactions.log.PersistedLogWriter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of couchbase-transactions Show documentation
Show all versions of couchbase-transactions Show documentation
Transaction Support for Couchbase on top of the Java SDK
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