Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.redisson.reactive.RedissonMapCacheReactive Maven / Gradle / Ivy
/**
* Copyright 2018 Nikita Koksharov
*
* 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 org.redisson.reactive;
import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
import org.reactivestreams.Publisher;
import org.redisson.RedissonMapCache;
import org.redisson.api.MapOptions;
import org.redisson.api.RFuture;
import org.redisson.api.RMapCacheAsync;
import org.redisson.api.RMapCacheReactive;
import org.redisson.api.RMapReactive;
import org.redisson.client.RedisClient;
import org.redisson.client.codec.Codec;
import org.redisson.client.protocol.decoder.MapScanResult;
import org.redisson.client.protocol.decoder.ScanObjectEntry;
import org.redisson.command.CommandReactiveExecutor;
import org.redisson.eviction.EvictionScheduler;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
/**
* Map-based cache with ability to set TTL for each entry via
* {@link #put(Object, Object, long, TimeUnit)} or {@link #putIfAbsent(Object, Object, long, TimeUnit)} method.
* And therefore has an complex lua-scripts inside.
*
* Current redis implementation doesnt have map entry eviction functionality.
* Thus entries are checked for TTL expiration during any key/value/entry read operation.
* If key/value/entry expired then it doesn't returns and clean task runs asynchronous.
* Clean task deletes removes 100 expired entries at once.
* In addition there is {@link org.redisson.eviction.EvictionScheduler}. This scheduler
* deletes expired entries in time interval between 5 seconds to 2 hours.
*
* If eviction is not required then it's better to use {@link org.redisson.reactive.RedissonMapReactive}.
*
* @author Nikita Koksharov
*
* @param key
* @param value
*/
public class RedissonMapCacheReactive extends RedissonExpirableReactive implements RMapCacheReactive, MapReactive {
private final RMapCacheAsync mapCache;
public RedissonMapCacheReactive(EvictionScheduler evictionScheduler, CommandReactiveExecutor commandExecutor, String name, MapOptions options) {
this(commandExecutor, name, options, new RedissonMapCache(evictionScheduler, commandExecutor, name, null, options));
}
public RedissonMapCacheReactive(CommandReactiveExecutor commandExecutor, String name, MapOptions options, RMapCacheAsync mapCache) {
super(commandExecutor, name, mapCache);
this.mapCache = mapCache;
}
public RedissonMapCacheReactive(EvictionScheduler evictionScheduler, Codec codec, CommandReactiveExecutor commandExecutor, String name, MapOptions options) {
this(codec, commandExecutor, name, options, new RedissonMapCache(codec, evictionScheduler, commandExecutor, name, null, options));
}
public RedissonMapCacheReactive(Codec codec, CommandReactiveExecutor commandExecutor, String name, MapOptions options, RMapCacheAsync mapCache) {
super(codec, commandExecutor, name, mapCache);
this.mapCache = mapCache;
}
@Override
public Publisher containsKey(final Object key) {
return reactive(new Supplier>() {
@Override
public RFuture get() {
return mapCache.containsKeyAsync(key);
}
});
}
@Override
public Publisher containsValue(final Object value) {
return reactive(new Supplier>() {
@Override
public RFuture get() {
return mapCache.containsValueAsync(value);
}
});
}
@Override
public Publisher> getAll(final Set keys) {
return reactive(new Supplier>>() {
@Override
public RFuture> get() {
return mapCache.getAllAsync(keys);
}
});
}
@Override
public Publisher putIfAbsent(final K key, final V value, final long ttl, final TimeUnit unit) {
return reactive(new Supplier>() {
@Override
public RFuture get() {
return mapCache.putIfAbsentAsync(key, value, ttl, unit);
}
});
}
@Override
public Publisher remove(final Object key, final Object value) {
return reactive(new Supplier>() {
@Override
public RFuture get() {
return mapCache.removeAsync(key, value);
}
});
}
@Override
public Publisher get(final K key) {
return reactive(new Supplier>() {
@Override
public RFuture get() {
return mapCache.getAsync(key);
}
});
}
@Override
public Publisher put(final K key, final V value, final long ttl, final TimeUnit unit) {
return reactive(new Supplier>() {
@Override
public RFuture get() {
return mapCache.putAsync(key, value, ttl, unit);
}
});
}
@Override
public Publisher remove(final K key) {
return reactive(new Supplier>() {
@Override
public RFuture get() {
return mapCache.removeAsync(key);
}
});
}
@Override
public Publisher fastRemove(final K ... keys) {
return reactive(new Supplier>() {
@Override
public RFuture get() {
return mapCache.fastRemoveAsync(keys);
}
});
}
@Override
public Publisher> scanIteratorReactive(final RedisClient client, final long startPos) {
return reactive(new Supplier>>() {
@Override
public RFuture> get() {
return ((RedissonMapCache)mapCache).scanIteratorAsync(getName(), client, startPos, null);
}
});
}
@Override
public Publisher delete() {
return reactive(new Supplier>() {
@Override
public RFuture get() {
return mapCache.deleteAsync();
}
});
}
@Override
public Publisher expire(final long timeToLive, final TimeUnit timeUnit) {
return reactive(new Supplier>() {
@Override
public RFuture get() {
return mapCache.expireAsync(timeToLive, timeUnit);
}
});
}
@Override
public Publisher expireAt(final long timestamp) {
return reactive(new Supplier>() {
@Override
public RFuture get() {
return mapCache.expireAtAsync(timestamp);
}
});
}
@Override
public Publisher clearExpire() {
return reactive(new Supplier>() {
@Override
public RFuture get() {
return mapCache.clearExpireAsync();
}
});
}
@Override
public Publisher putAll(final Map map) {
return reactive(new Supplier>() {
@Override
public RFuture get() {
return mapCache.putAllAsync(map);
}
});
}
@Override
public Publisher addAndGet(final K key, final Number delta) {
return reactive(new Supplier>() {
@Override
public RFuture get() {
return mapCache.addAndGetAsync(key, delta);
}
});
}
@Override
public Publisher fastPut(final K key, final V value) {
return reactive(new Supplier>() {
@Override
public RFuture get() {
return mapCache.fastPutAsync(key, value);
}
});
}
@Override
public Publisher put(final K key, final V value) {
return reactive(new Supplier>() {
@Override
public RFuture get() {
return mapCache.putAsync(key, value);
}
});
}
@Override
public Publisher replace(final K key, final V value) {
return reactive(new Supplier>() {
@Override
public RFuture get() {
return mapCache.replaceAsync(key, value);
}
});
}
@Override
public Publisher replace(final K key, final V oldValue, final V newValue) {
return reactive(new Supplier>() {
@Override
public RFuture get() {
return mapCache.replaceAsync(key, oldValue, newValue);
}
});
}
@Override
public Publisher putIfAbsent(final K key, final V value) {
return reactive(new Supplier>() {
@Override
public RFuture get() {
return mapCache.putIfAbsentAsync(key, value);
}
});
}
@Override
public Publisher> entryIterator() {
return Flux.create(new RedissonMapReactiveIterator>(this));
}
@Override
public Publisher valueIterator() {
return Flux.create(new RedissonMapReactiveIterator(this) {
@Override
V getValue(Entry entry) {
return (V) entry.getValue().getObj();
}
});
}
@Override
public Publisher keyIterator() {
return Flux.create(new RedissonMapReactiveIterator(this) {
@Override
K getValue(Entry entry) {
return (K) entry.getKey().getObj();
}
});
}
@Override
public Publisher size() {
return reactive(new Supplier>() {
@Override
public RFuture get() {
return mapCache.sizeAsync();
}
});
}
@Override
public boolean equals(Object o) {
if (o == this)
return true;
if (o instanceof Map) {
final Map m = (Map) o;
if (m.size() != Mono.from(size()).block()) {
return false;
}
return Flux.from(entryIterator()).map(mapFunction(m)).reduce(true, booleanAnd()).block();
} else if (o instanceof RMapReactive) {
final RMapReactive m = (RMapReactive) o;
if (Mono.from(m.size()).block() != Mono.from(size()).block()) {
return false;
}
return Flux.from(entryIterator()).map(mapFunction(m)).reduce(true, booleanAnd()).block();
}
return true;
}
private BiFunction booleanAnd() {
return new BiFunction() {
@Override
public Boolean apply(Boolean t, Boolean u) {
return t & u;
}
};
}
private Function, Boolean> mapFunction(final Map m) {
return new Function, Boolean>() {
@Override
public Boolean apply(Entry e) {
K key = e.getKey();
V value = e.getValue();
if (value == null) {
if (!(m.get(key)==null && m.containsKey(key)))
return false;
} else {
if (!value.equals(m.get(key)))
return false;
}
return true;
}
};
}
private Function, Boolean> mapFunction(final RMapReactive m) {
return new Function, Boolean>() {
@Override
public Boolean apply(Entry e) {
Object key = e.getKey();
Object value = e.getValue();
if (value == null) {
if (!(Mono.from(m.get(key)).block() == null && Mono.from(m.containsKey(key)).block()))
return false;
} else {
if (!value.equals(Mono.from(m.get(key)).block()))
return false;
}
return true;
}
};
}
@Override
public int hashCode() {
return Flux.from(entryIterator()).map(new Function, Integer>() {
@Override
public Integer apply(Entry t) {
return t.hashCode();
}
}).reduce(0, new BiFunction() {
@Override
public Integer apply(Integer t, Integer u) {
return t + u;
}
}).block();
}
@Override
public Publisher loadAll(final boolean replaceExistingValues, final int parallelism) {
return reactive(new Supplier>() {
@Override
public RFuture get() {
return mapCache.loadAllAsync(replaceExistingValues, parallelism);
}
});
}
@Override
public Publisher loadAll(final Set keys, final boolean replaceExistingValues, final int parallelism) {
return reactive(new Supplier>() {
@Override
public RFuture get() {
return mapCache.loadAllAsync(keys, replaceExistingValues, parallelism);
}
});
}
@Override
public Publisher valueSize(final K key) {
return reactive(new Supplier>() {
@Override
public RFuture get() {
return mapCache.valueSizeAsync(key);
}
});
}
@Override
public Publisher fastPutIfAbsent(final K key, final V value) {
return reactive(new Supplier>() {
@Override
public RFuture get() {
return mapCache.fastPutIfAbsentAsync(key, value);
}
});
}
@Override
public Publisher> readAllKeySet() {
return reactive(new Supplier>>() {
@Override
public RFuture> get() {
return mapCache.readAllKeySetAsync();
}
});
}
@Override
public Publisher> readAllValues() {
return reactive(new Supplier>>() {
@Override
public RFuture> get() {
return mapCache.readAllValuesAsync();
}
});
}
@Override
public Publisher>> readAllEntrySet() {
return reactive(new Supplier>>>() {
@Override
public RFuture>> get() {
return mapCache.readAllEntrySetAsync();
}
});
}
@Override
public Publisher> readAllMap() {
return reactive(new Supplier>>() {
@Override
public RFuture> get() {
return mapCache.readAllMapAsync();
}
});
}
@Override
public Publisher putIfAbsent(final K key, final V value, final long ttl, final TimeUnit ttlUnit, final long maxIdleTime,
final TimeUnit maxIdleUnit) {
return reactive(new Supplier>() {
@Override
public RFuture get() {
return mapCache.putIfAbsentAsync(key, value, ttl, ttlUnit, maxIdleTime, maxIdleUnit);
}
});
}
@Override
public Publisher put(final K key, final V value, final long ttl, final TimeUnit ttlUnit, final long maxIdleTime, final TimeUnit maxIdleUnit) {
return reactive(new Supplier>() {
@Override
public RFuture get() {
return mapCache.putAsync(key, value, ttl, ttlUnit, maxIdleTime, maxIdleUnit);
}
});
}
@Override
public Publisher fastPut(final K key, final V value, final long ttl, final TimeUnit unit) {
return reactive(new Supplier>() {
@Override
public RFuture get() {
return mapCache.fastPutAsync(key, value, ttl, unit);
}
});
}
@Override
public Publisher fastPut(final K key, final V value, final long ttl, final TimeUnit ttlUnit, final long maxIdleTime,
final TimeUnit maxIdleUnit) {
return reactive(new Supplier>() {
@Override
public RFuture get() {
return mapCache.fastPutAsync(key, value, ttl, ttlUnit, maxIdleTime, maxIdleUnit);
}
});
}
@Override
public Publisher fastPutIfAbsent(final K key, final V value, final long ttl, final TimeUnit ttlUnit, final long maxIdleTime,
final TimeUnit maxIdleUnit) {
return reactive(new Supplier>() {
@Override
public RFuture get() {
return mapCache.fastPutIfAbsentAsync(key, value, ttl, ttlUnit, maxIdleTime, maxIdleUnit);
}
});
}
}