CavalliumDBEngine/src/main/java/it/cavallium/dbengine/database/collections/DatabaseMapDictionary.java

470 lines
16 KiB
Java
Raw Normal View History

package it.cavallium.dbengine.database.collections;
2021-09-17 16:56:28 +02:00
import io.net5.buffer.api.Buffer;
2021-09-23 20:57:28 +02:00
import io.net5.buffer.api.Drop;
2021-09-17 16:56:28 +02:00
import io.net5.buffer.api.Send;
import io.net5.buffer.api.internal.ResourceSupport;
import it.cavallium.dbengine.client.CompositeSnapshot;
2021-05-08 03:09:00 +02:00
import it.cavallium.dbengine.database.Delta;
2021-07-17 11:52:08 +02:00
import it.cavallium.dbengine.database.ExtraKeyOperationResult;
import it.cavallium.dbengine.database.LLDictionary;
2021-01-31 21:23:43 +01:00
import it.cavallium.dbengine.database.LLDictionaryResultType;
2021-08-28 22:42:51 +02:00
import it.cavallium.dbengine.database.LLEntry;
2021-01-31 21:23:43 +01:00
import it.cavallium.dbengine.database.LLUtils;
2021-05-02 19:18:15 +02:00
import it.cavallium.dbengine.database.UpdateMode;
2021-05-08 03:09:00 +02:00
import it.cavallium.dbengine.database.UpdateReturnMode;
2021-08-22 21:23:22 +02:00
import it.cavallium.dbengine.database.serialization.BiSerializationFunction;
import it.cavallium.dbengine.database.serialization.SerializationException;
import it.cavallium.dbengine.database.serialization.SerializationFunction;
2021-02-02 19:40:37 +01:00
import it.cavallium.dbengine.database.serialization.Serializer;
import it.cavallium.dbengine.database.serialization.SerializerFixedBinaryLength;
2021-06-06 02:23:51 +02:00
import java.util.Collections;
2021-01-31 21:23:43 +01:00
import java.util.HashMap;
2021-09-08 00:22:39 +02:00
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
2021-05-02 19:18:15 +02:00
import java.util.Objects;
2021-07-23 15:20:33 +02:00
import java.util.Optional;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
2021-08-22 21:23:22 +02:00
import reactor.core.publisher.SynchronousSink;
2021-07-17 11:52:08 +02:00
import reactor.util.function.Tuple2;
import reactor.util.function.Tuples;
2021-01-31 21:23:43 +01:00
/**
* Optimized implementation of "DatabaseMapDictionary with SubStageGetterSingle"
*/
public class DatabaseMapDictionary<T, U> extends DatabaseMapDictionaryDeep<T, U, DatabaseStageEntry<U>> {
2021-09-02 17:15:40 +02:00
private final Serializer<U> valueSerializer;
protected DatabaseMapDictionary(LLDictionary dictionary,
@NotNull Send<Buffer> prefixKey,
2021-09-02 17:15:40 +02:00
SerializerFixedBinaryLength<T> keySuffixSerializer,
2021-09-23 20:57:28 +02:00
Serializer<U> valueSerializer,
Drop<DatabaseMapDictionaryDeep<T, U, DatabaseStageEntry<U>>> drop) {
// Do not retain or release or use the prefixKey here
2021-09-23 20:57:28 +02:00
super(dictionary, prefixKey, keySuffixSerializer, new SubStageGetterSingle<>(valueSerializer), 0, drop);
2021-01-31 21:23:43 +01:00
this.valueSerializer = valueSerializer;
}
2021-01-31 21:23:43 +01:00
public static <T, U> DatabaseMapDictionary<T, U> simple(LLDictionary dictionary,
2021-09-02 17:15:40 +02:00
SerializerFixedBinaryLength<T> keySerializer,
2021-09-23 20:57:28 +02:00
Serializer<U> valueSerializer,
Drop<DatabaseMapDictionaryDeep<T, U, DatabaseStageEntry<U>>> drop) {
return new DatabaseMapDictionary<>(dictionary, LLUtils.empty(dictionary.getAllocator()), keySerializer,
valueSerializer, drop);
}
2021-01-31 21:23:43 +01:00
public static <T, U> DatabaseMapDictionary<T, U> tail(LLDictionary dictionary,
2021-08-29 23:18:03 +02:00
Send<Buffer> prefixKey,
2021-09-02 17:15:40 +02:00
SerializerFixedBinaryLength<T> keySuffixSerializer,
2021-09-23 20:57:28 +02:00
Serializer<U> valueSerializer,
Drop<DatabaseMapDictionaryDeep<T, U, DatabaseStageEntry<U>>> drop) {
return new DatabaseMapDictionary<>(dictionary, prefixKey, keySuffixSerializer, valueSerializer, drop);
}
private Send<Buffer> toKey(Send<Buffer> suffixKeyToSend) {
try (var suffixKey = suffixKeyToSend.receive()) {
assert suffixKeyConsistency(suffixKey.readableBytes());
if (keyPrefix.readableBytes() > 0) {
try (var result = LLUtils.compositeBuffer(dictionary.getAllocator(),
LLUtils.copy(dictionary.getAllocator(), keyPrefix),
suffixKey.send()
)) {
assert result.readableBytes() == keyPrefixLength + keySuffixLength + keyExtLength;
return result.send();
}
} else {
assert suffixKey.readableBytes() == keyPrefixLength + keySuffixLength + keyExtLength;
return suffixKey.send();
}
}
}
2021-08-29 23:18:03 +02:00
private void deserializeValue(Send<Buffer> value, SynchronousSink<U> sink) {
2021-08-22 21:23:22 +02:00
try {
2021-09-02 17:15:40 +02:00
sink.next(valueSerializer.deserialize(value).deserializedData());
2021-08-22 21:23:22 +02:00
} catch (SerializationException ex) {
sink.error(ex);
}
}
2021-01-31 21:23:43 +01:00
@Override
2021-03-18 16:19:41 +01:00
public Mono<Map<T, U>> get(@Nullable CompositeSnapshot snapshot, boolean existsAlmostCertainly) {
return dictionary
.getRange(resolveSnapshot(snapshot), rangeMono, existsAlmostCertainly)
2021-08-31 09:14:46 +02:00
.<Entry<T, U>>handle((entrySend, sink) -> {
try (var entry = entrySend.receive()) {
T key;
try (var serializedKey = entry.getKey().receive()) {
removePrefix(serializedKey);
suffixKeyConsistency(serializedKey.readableBytes());
key = deserializeSuffix(serializedKey.send());
}
2021-09-02 17:15:40 +02:00
var value = valueSerializer.deserialize(entry.getValue()).deserializedData();
2021-08-22 21:23:22 +02:00
sink.next(Map.entry(key, value));
} catch (SerializationException ex) {
sink.error(ex);
}
})
.collectMap(Entry::getKey, Entry::getValue, HashMap::new)
.filter(map -> !map.isEmpty());
2021-01-31 19:52:47 +01:00
}
2021-01-31 21:23:43 +01:00
@Override
public Mono<Map<T, U>> setAndGetPrevious(Map<T, U> value) {
2021-08-22 21:23:22 +02:00
return this
.get(null, false)
.concatWith(dictionary.setRange(rangeMono, Flux
2021-08-22 19:54:23 +02:00
.fromIterable(Collections.unmodifiableMap(value).entrySet())
2021-08-22 21:23:22 +02:00
.handle((entry, sink) -> {
try {
sink.next(LLEntry.of(this.toKey(serializeSuffix(entry.getKey())),
2021-08-31 09:14:46 +02:00
valueSerializer.serialize(entry.getValue())).send());
2021-08-22 21:23:22 +02:00
} catch (SerializationException e) {
sink.error(e);
}
})
).then(Mono.empty()))
.singleOrEmpty()
.transform(LLUtils::handleDiscard);
2021-01-31 19:52:47 +01:00
}
2021-01-31 21:23:43 +01:00
@Override
public Mono<Map<T, U>> clearAndGetPrevious() {
2021-05-02 19:18:15 +02:00
return this
.setAndGetPrevious(Map.of());
}
2021-01-31 21:23:43 +01:00
@Override
2021-02-24 16:43:07 +01:00
public Mono<Long> leavesCount(@Nullable CompositeSnapshot snapshot, boolean fast) {
return dictionary.sizeRange(resolveSnapshot(snapshot), rangeMono, fast);
}
2021-03-14 03:13:19 +01:00
@Override
public Mono<Boolean> isEmpty(@Nullable CompositeSnapshot snapshot) {
return dictionary.isRangeEmpty(resolveSnapshot(snapshot), rangeMono);
2021-03-14 03:13:19 +01:00
}
2021-01-31 21:23:43 +01:00
@Override
public Mono<DatabaseStageEntry<U>> at(@Nullable CompositeSnapshot snapshot, T keySuffix) {
2021-09-02 17:15:40 +02:00
return Mono.fromCallable(() ->
2021-09-23 20:57:28 +02:00
new DatabaseSingle<>(dictionary, toKey(serializeSuffix(keySuffix)), valueSerializer, d -> {}));
}
2021-01-31 21:23:43 +01:00
@Override
2021-03-18 16:19:41 +01:00
public Mono<U> getValue(@Nullable CompositeSnapshot snapshot, T keySuffix, boolean existsAlmostCertainly) {
2021-08-31 09:14:46 +02:00
return dictionary
2021-09-22 18:33:28 +02:00
.get(resolveSnapshot(snapshot),
Mono.fromCallable(() -> toKey(serializeSuffix(keySuffix))),
2021-09-22 18:33:28 +02:00
existsAlmostCertainly
)
2021-09-02 17:15:40 +02:00
.handle((value, sink) -> deserializeValue(value, sink));
}
2021-01-31 21:23:43 +01:00
@Override
public Mono<Void> putValue(T keySuffix, U value) {
var keyMono = Mono.fromCallable(() -> toKey(serializeSuffix(keySuffix))).single();
var valueMono = Mono.fromCallable(() -> valueSerializer.serialize(value)).single();
2021-08-31 09:14:46 +02:00
return dictionary
.put(keyMono, valueMono, LLDictionaryResultType.VOID)
.doOnNext(Send::close)
.then();
}
2021-05-02 19:18:15 +02:00
@Override
public Mono<UpdateMode> getUpdateMode() {
return dictionary.getUpdateMode();
}
2021-02-06 19:21:31 +01:00
@Override
2021-05-08 03:09:00 +02:00
public Mono<U> updateValue(T keySuffix,
UpdateReturnMode updateReturnMode,
2021-03-18 16:19:41 +01:00
boolean existsAlmostCertainly,
2021-08-22 21:23:22 +02:00
SerializationFunction<@Nullable U, @Nullable U> updater) {
var keyMono = Mono.fromCallable(() -> toKey(serializeSuffix(keySuffix)));
2021-08-31 09:14:46 +02:00
return dictionary
.update(keyMono, getSerializedUpdater(updater), updateReturnMode, existsAlmostCertainly)
2021-09-02 17:15:40 +02:00
.handle((value, sink) -> deserializeValue(value, sink));
2021-05-08 03:09:00 +02:00
}
@Override
public Mono<Delta<U>> updateValueAndGetDelta(T keySuffix,
boolean existsAlmostCertainly,
2021-08-22 21:23:22 +02:00
SerializationFunction<@Nullable U, @Nullable U> updater) {
var keyMono = Mono.fromCallable(() -> toKey(serializeSuffix(keySuffix)));
2021-08-31 09:14:46 +02:00
return dictionary
.updateAndGetDelta(keyMono, getSerializedUpdater(updater), existsAlmostCertainly)
2021-09-02 17:15:40 +02:00
.transform(mono -> LLUtils.mapLLDelta(mono,
serialized -> valueSerializer.deserialize(serialized).deserializedData()
));
2021-02-06 19:21:31 +01:00
}
2021-08-31 09:14:46 +02:00
public SerializationFunction<@Nullable Send<Buffer>, @Nullable Send<Buffer>> getSerializedUpdater(
SerializationFunction<@Nullable U, @Nullable U> updater) {
2021-07-17 11:52:08 +02:00
return oldSerialized -> {
2021-08-31 09:14:46 +02:00
try (oldSerialized) {
2021-08-22 21:23:22 +02:00
U result;
if (oldSerialized == null) {
result = updater.apply(null);
} else {
2021-09-02 17:15:40 +02:00
result = updater.apply(valueSerializer.deserialize(oldSerialized).deserializedData());
2021-08-22 21:23:22 +02:00
}
2021-07-17 11:52:08 +02:00
if (result == null) {
return null;
} else {
return valueSerializer.serialize(result);
2021-07-17 11:52:08 +02:00
}
}
};
}
2021-08-31 09:14:46 +02:00
public <X> BiSerializationFunction<@Nullable Send<Buffer>, X, @Nullable Send<Buffer>> getSerializedUpdater(
2021-08-22 21:23:22 +02:00
BiSerializationFunction<@Nullable U, X, @Nullable U> updater) {
2021-07-17 11:52:08 +02:00
return (oldSerialized, extra) -> {
2021-08-31 09:14:46 +02:00
try (oldSerialized) {
2021-08-22 21:23:22 +02:00
U result;
if (oldSerialized == null) {
result = updater.apply(null, extra);
} else {
2021-09-02 17:15:40 +02:00
result = updater.apply(valueSerializer.deserialize(oldSerialized).deserializedData(), extra);
2021-08-22 21:23:22 +02:00
}
2021-07-17 11:52:08 +02:00
if (result == null) {
return null;
} else {
return valueSerializer.serialize(result);
2021-07-17 11:52:08 +02:00
}
}
};
}
2021-01-31 21:23:43 +01:00
@Override
public Mono<U> putValueAndGetPrevious(T keySuffix, U value) {
var keyMono = Mono.fromCallable(() -> toKey(serializeSuffix(keySuffix)));
2021-08-31 09:14:46 +02:00
var valueMono = Mono.fromCallable(() -> valueSerializer.serialize(value));
return dictionary
.put(keyMono,
valueMono,
LLDictionaryResultType.PREVIOUS_VALUE)
2021-09-02 17:15:40 +02:00
.handle((value1, sink) -> deserializeValue(value1, sink));
}
2021-01-31 21:23:43 +01:00
@Override
2021-05-02 19:18:15 +02:00
public Mono<Boolean> putValueAndGetChanged(T keySuffix, U value) {
var keyMono = Mono.fromCallable(() -> toKey(serializeSuffix(keySuffix)));
2021-08-31 09:14:46 +02:00
var valueMono = Mono.fromCallable(() -> valueSerializer.serialize(value));
return dictionary
.put(keyMono, valueMono, LLDictionaryResultType.PREVIOUS_VALUE)
2021-09-02 17:15:40 +02:00
.handle((Send<Buffer> value1, SynchronousSink<U> sink) -> deserializeValue(value1, sink))
2021-08-31 09:14:46 +02:00
.map(oldValue -> !Objects.equals(oldValue, value))
.defaultIfEmpty(value != null);
}
2021-01-31 21:23:43 +01:00
@Override
public Mono<Void> remove(T keySuffix) {
var keyMono = Mono.fromCallable(() -> toKey(serializeSuffix(keySuffix)));
2021-08-31 09:14:46 +02:00
return dictionary
.remove(keyMono, LLDictionaryResultType.VOID)
.doOnNext(Send::close)
.then();
}
2021-01-31 21:23:43 +01:00
@Override
public Mono<U> removeAndGetPrevious(T keySuffix) {
var keyMono = Mono.fromCallable(() -> toKey(serializeSuffix(keySuffix)));
2021-08-31 09:14:46 +02:00
return dictionary
.remove(keyMono, LLDictionaryResultType.PREVIOUS_VALUE)
2021-09-02 17:15:40 +02:00
.handle((value, sink) -> deserializeValue(value, sink));
}
2021-01-31 21:23:43 +01:00
@Override
public Mono<Boolean> removeAndGetStatus(T keySuffix) {
var keyMono = Mono.fromCallable(() -> toKey(serializeSuffix(keySuffix)));
2021-08-31 09:14:46 +02:00
return dictionary
.remove(keyMono, LLDictionaryResultType.PREVIOUS_VALUE_EXISTENCE)
.map(LLUtils::responseToBoolean);
}
@Override
2021-07-23 15:20:33 +02:00
public Flux<Entry<T, Optional<U>>> getMulti(@Nullable CompositeSnapshot snapshot, Flux<T> keys, boolean existsAlmostCertainly) {
2021-08-31 09:14:46 +02:00
var mappedKeys = keys
.<Tuple2<T, Send<Buffer>>>handle((keySuffix, sink) -> {
2021-08-28 22:42:51 +02:00
try {
sink.next(Tuples.of(keySuffix, toKey(serializeSuffix(keySuffix))));
2021-08-31 09:14:46 +02:00
} catch (SerializationException ex) {
sink.error(ex);
2021-08-22 21:23:22 +02:00
}
2021-08-31 09:14:46 +02:00
});
return dictionary
.getMulti(resolveSnapshot(snapshot), mappedKeys, existsAlmostCertainly)
.<Entry<T, Optional<U>>>handle((entry, sink) -> {
try {
Optional<U> valueOpt;
if (entry.getT3().isPresent()) {
try (var buf = entry.getT3().get()) {
2021-09-02 17:15:40 +02:00
valueOpt = Optional.of(valueSerializer.deserialize(buf).deserializedData());
2021-08-31 09:14:46 +02:00
}
} else {
valueOpt = Optional.empty();
}
sink.next(Map.entry(entry.getT1(), valueOpt));
} catch (SerializationException ex) {
sink.error(ex);
2021-09-08 00:22:39 +02:00
} finally {
entry.getT2().close();
entry.getT3().ifPresent(Send::close);
2021-08-31 09:14:46 +02:00
}
})
.transform(LLUtils::handleDiscard);
2021-05-02 19:18:15 +02:00
}
2021-08-31 09:14:46 +02:00
private Send<LLEntry> serializeEntry(T key, U value) throws SerializationException {
try (var serializedKey = toKey(serializeSuffix(key))) {
var serializedValueToReceive = valueSerializer.serialize(value);
try (var serializedValue = serializedValueToReceive.receive()) {
return LLEntry.of(serializedKey, serializedValue.send()).send();
2021-05-02 19:18:15 +02:00
}
}
}
@Override
public Mono<Void> putMulti(Flux<Entry<T, U>> entries) {
2021-05-02 19:18:15 +02:00
var serializedEntries = entries
2021-08-31 09:14:46 +02:00
.<Send<LLEntry>>handle((entry, sink) -> {
2021-08-28 22:42:51 +02:00
try {
sink.next(serializeEntry(entry.getKey(), entry.getValue()));
} catch (SerializationException e) {
sink.error(e);
}
2021-09-08 00:22:39 +02:00
})
.doOnDiscard(Send.class, Send::close);
return dictionary
2021-05-02 19:18:15 +02:00
.putMulti(serializedEntries, false)
2021-08-28 22:42:51 +02:00
.then()
2021-09-08 00:22:39 +02:00
.doOnDiscard(Send.class, Send::close)
.doOnDiscard(LLEntry.class, ResourceSupport::close)
.doOnDiscard(List.class, list -> {
for (Object o : list) {
if (o instanceof Send send) {
send.close();
} else if (o instanceof Buffer buf) {
buf.close();
}
}
});
}
2021-07-17 11:52:08 +02:00
@Override
public <X> Flux<ExtraKeyOperationResult<T, X>> updateMulti(Flux<Tuple2<T, X>> entries,
2021-08-22 21:23:22 +02:00
BiSerializationFunction<@Nullable U, X, @Nullable U> updater) {
2021-08-31 09:14:46 +02:00
var serializedEntries = entries
.<Tuple2<Send<Buffer>, X>>handle((entry, sink) -> {
try {
sink.next(Tuples.of(serializeSuffix(entry.getT1()), entry.getT2()));
2021-08-31 09:14:46 +02:00
} catch (SerializationException ex) {
sink.error(ex);
}
})
2021-07-23 22:18:08 +02:00
.doOnDiscard(Tuple2.class, uncastedEntry -> {
2021-08-29 23:18:03 +02:00
if (uncastedEntry.getT1() instanceof Buffer byteBuf) {
2021-08-31 09:14:46 +02:00
byteBuf.close();
2021-07-23 22:18:08 +02:00
}
2021-08-29 23:18:03 +02:00
if (uncastedEntry.getT2() instanceof Buffer byteBuf) {
2021-08-31 09:14:46 +02:00
byteBuf.close();
2021-07-23 22:18:08 +02:00
}
});
2021-07-17 11:52:08 +02:00
var serializedUpdater = getSerializedUpdater(updater);
return dictionary.updateMulti(serializedEntries, serializedUpdater)
2021-08-22 21:23:22 +02:00
.handle((result, sink) -> {
try {
sink.next(new ExtraKeyOperationResult<>(deserializeSuffix(result.key()),
result.extra(),
result.changed()
));
} catch (SerializationException ex) {
sink.error(ex);
}
});
2021-07-17 11:52:08 +02:00
}
@Override
2021-01-31 21:23:43 +01:00
public Flux<Entry<T, DatabaseStageEntry<U>>> getAllStages(@Nullable CompositeSnapshot snapshot) {
return dictionary
.getRangeKeys(resolveSnapshot(snapshot), rangeMono)
.handle((keyBufToReceive, sink) -> {
try (var keyBuf = keyBufToReceive.receive()) {
assert keyBuf.readableBytes() == keyPrefixLength + keySuffixLength + keyExtLength;
// Remove prefix. Keep only the suffix and the ext
removePrefix(keyBuf);
suffixKeyConsistency(keyBuf.readableBytes());
sink.next(Map.entry(deserializeSuffix(keyBuf.copy().send()),
2021-09-23 20:57:28 +02:00
new DatabaseSingle<>(dictionary, toKey(keyBuf.send()), valueSerializer, d -> {})
));
2021-08-31 09:14:46 +02:00
} catch (SerializationException ex) {
sink.error(ex);
2021-05-02 19:18:15 +02:00
}
});
}
2021-03-22 20:02:19 +01:00
@Override
public Flux<Entry<T, U>> getAllValues(@Nullable CompositeSnapshot snapshot) {
return dictionary
.getRange(resolveSnapshot(snapshot), rangeMono)
2021-08-31 09:14:46 +02:00
.<Entry<T, U>>handle((serializedEntryToReceive, sink) -> {
try (var serializedEntry = serializedEntryToReceive.receive()) {
try (var keyBuf = serializedEntry.getKey().receive()) {
assert keyBuf.readableBytes() == keyPrefixLength + keySuffixLength + keyExtLength;
// Remove prefix. Keep only the suffix and the ext
removePrefix(keyBuf);
suffixKeyConsistency(keyBuf.readableBytes());
sink.next(Map.entry(deserializeSuffix(keyBuf.send()),
valueSerializer.deserialize(serializedEntry.getValue()).deserializedData()));
}
2021-08-22 21:23:22 +02:00
} catch (SerializationException e) {
sink.error(e);
}
})
2021-07-23 22:18:08 +02:00
.doOnDiscard(Entry.class, uncastedEntry -> {
2021-08-29 23:18:03 +02:00
if (uncastedEntry.getKey() instanceof Buffer byteBuf) {
2021-08-31 09:14:46 +02:00
byteBuf.close();
2021-07-23 22:18:08 +02:00
}
2021-08-29 23:18:03 +02:00
if (uncastedEntry.getValue() instanceof Buffer byteBuf) {
2021-08-31 09:14:46 +02:00
byteBuf.close();
2021-07-23 22:18:08 +02:00
}
});
2021-03-22 20:02:19 +01:00
}
2021-01-31 15:47:48 +01:00
@Override
public Flux<Entry<T, U>> setAllValuesAndGetPrevious(Flux<Entry<T, U>> entries) {
2021-08-29 01:15:51 +02:00
return Flux.concat(
this.getAllValues(null),
dictionary.setRange(rangeMono, entries.handle((entry, sink) -> {
2021-08-22 21:23:22 +02:00
try {
sink.next(LLEntry.of(toKey(serializeSuffix(entry.getKey())),
2021-08-31 09:14:46 +02:00
valueSerializer.serialize(entry.getValue())).send());
2021-08-22 21:23:22 +02:00
} catch (SerializationException e) {
sink.error(e);
}
2021-08-29 01:15:51 +02:00
})).then(Mono.empty())
2021-08-22 21:23:22 +02:00
);
2021-01-31 15:47:48 +01:00
}
2021-03-14 03:13:19 +01:00
@Override
public Mono<Void> clear() {
2021-08-31 09:14:46 +02:00
if (range.isAll()) {
return dictionary.clear();
} else if (range.isSingle()) {
return dictionary
.remove(Mono.fromCallable(range::getSingle), LLDictionaryResultType.VOID)
.doOnNext(Send::close)
.then();
} else {
return dictionary.setRange(rangeMono, Flux.empty());
}
}
}