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

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); } }); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy