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

org.springframework.data.redis.connection.lettuce.LettuceReactiveClusterSetCommands Maven / Gradle / Ivy

There is a newer version: 3.2.5
Show newest version
/*
 * Copyright 2016-2018 the original author or authors.
 *
 * 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.springframework.data.redis.connection.lettuce;

import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import org.reactivestreams.Publisher;
import org.springframework.data.redis.connection.ClusterSlotHashUtil;
import org.springframework.data.redis.connection.ReactiveClusterSetCommands;
import org.springframework.data.redis.connection.ReactiveRedisConnection.BooleanResponse;
import org.springframework.data.redis.connection.ReactiveRedisConnection.CommandResponse;
import org.springframework.data.redis.connection.ReactiveRedisConnection.NumericResponse;
import org.springframework.util.Assert;

/**
 * @author Christoph Strobl
 * @author Mark Paluch
 * @since 2.0
 */
class LettuceReactiveClusterSetCommands extends LettuceReactiveSetCommands implements ReactiveClusterSetCommands {

	/**
	 * Create new {@link LettuceReactiveClusterSetCommands}.
	 *
	 * @param connection must not be {@literal null}.
	 */
	LettuceReactiveClusterSetCommands(LettuceReactiveRedisConnection connection) {
		super(connection);
	}

	/* (non-Javadoc)
	 * @see org.springframework.data.redis.connection.lettuce.LettuceReactiveSetCommands#sUnion(org.reactivestreams.Publisher)
	 */
	@Override
	public Flux>> sUnion(Publisher commands) {

		return getConnection().execute(cmd -> Flux.from(commands).concatMap(command -> {

			Assert.notNull(command.getKeys(), "Keys must not be null!");

			if (ClusterSlotHashUtil.isSameSlotForAllKeys(command.getKeys())) {
				return super.sUnion(Mono.just(command));
			}

			Flux result = Flux.merge(command.getKeys().stream().map(cmd::smembers).collect(Collectors.toList()))
					.distinct();

			return Mono.just(new CommandResponse<>(command, result));
		}));
	}

	/* (non-Javadoc)
	 * @see org.springframework.data.redis.connection.lettuce.LettuceReactiveSetCommands#sUnionStore(org.reactivestreams.Publisher)
	 */
	@Override
	public Flux> sUnionStore(Publisher commands) {

		return getConnection().execute(cmd -> Flux.from(commands).concatMap(command -> {

			Assert.notNull(command.getKeys(), "Source keys must not be null!");
			Assert.notNull(command.getKey(), "Destination key must not be null!");

			List keys = new ArrayList<>(command.getKeys());
			keys.add(command.getKey());

			if (ClusterSlotHashUtil.isSameSlotForAllKeys(keys)) {
				return super.sUnionStore(Mono.just(command));
			}

			return sUnion(Mono.just(SUnionCommand.keys(command.getKeys()))).next().flatMap(values -> {
				Mono result = cmd.sadd(command.getKey(), values.getOutput().toStream().toArray(ByteBuffer[]::new));
				return result.map(value -> new NumericResponse<>(command, value));
			});
		}));
	}

	/* (non-Javadoc)
	 * @see org.springframework.data.redis.connection.lettuce.LettuceReactiveSetCommands#sInter(org.reactivestreams.Publisher)
	 */
	@Override
	public Flux>> sInter(Publisher commands) {

		return getConnection().execute(cmd -> Flux.from(commands).concatMap(command -> {

			Assert.notNull(command.getKeys(), "Keys must not be null!");

			if (ClusterSlotHashUtil.isSameSlotForAllKeys(command.getKeys())) {
				return super.sInter(Mono.just(command));
			}

			Mono> sourceSet = cmd.smembers(command.getKeys().get(0)).distinct().collectList();

			List>> intersectingSets = new ArrayList<>();

			for (int i = 1; i < command.getKeys().size(); i++) {
				intersectingSets.add(cmd.smembers(command.getKeys().get(i)).distinct().collectList());
			}

			Flux> result = Flux.zip(sourceSet, Flux.merge(intersectingSets).collectList(),
					(source, intersectings) -> {

						for (List intersecting : intersectings) {
							source.retainAll(intersecting);
						}
				return source;
			});

			return Mono.just(new CommandResponse<>(command, result.concatMap(v -> Flux.fromStream(v.stream()))));
		}));
	}

	/* (non-Javadoc)
	 * @see org.springframework.data.redis.connection.lettuce.LettuceReactiveSetCommands#sInterStore(org.reactivestreams.Publisher)
	 */
	@Override
	public Flux> sInterStore(Publisher commands) {

		return getConnection().execute(cmd -> Flux.from(commands).concatMap(command -> {

			Assert.notNull(command.getKeys(), "Source keys must not be null!");
			Assert.notNull(command.getKey(), "Destination key must not be null!");

			List keys = new ArrayList<>(command.getKeys());
			keys.add(command.getKey());

			if (ClusterSlotHashUtil.isSameSlotForAllKeys(keys)) {
				return super.sInterStore(Mono.just(command));
			}

			return sInter(Mono.just(SInterCommand.keys(command.getKeys()))).next().flatMap(values -> {
				Mono result = cmd.sadd(command.getKey(), values.getOutput().toStream().toArray(ByteBuffer[]::new));
				return result.map(value -> new NumericResponse<>(command, value));
			});
		}));
	}

	/* (non-Javadoc)
	 * @see org.springframework.data.redis.connection.lettuce.LettuceReactiveSetCommands#sDiff(org.reactivestreams.Publisher)
	 */
	@Override
	public Flux>> sDiff(Publisher commands) {

		return getConnection().execute(cmd -> Flux.from(commands).concatMap(command -> {

			Assert.notNull(command.getKeys(), "Keys must not be null!");

			if (ClusterSlotHashUtil.isSameSlotForAllKeys(command.getKeys())) {
				return super.sDiff(Mono.just(command));
			}

			Mono> sourceSet = cmd.smembers(command.getKeys().get(0)).distinct().collectList();

			List>> intersectingSets = new ArrayList<>();

			for (int i = 1; i < command.getKeys().size(); i++) {
				intersectingSets.add(cmd.smembers(command.getKeys().get(i)).distinct().collectList());
			}

			Flux> result = Flux.zip(sourceSet, Flux.merge(intersectingSets).collectList(),
					(source, intersectings) -> {

						for (List intersecting : intersectings) {
							source.removeAll(intersecting);
						}

				return source;
			});

			return Mono.just(new CommandResponse<>(command, result.concatMap(v -> Flux.fromStream(v.stream()))));

		}));
	}

	/* (non-Javadoc)
	 * @see org.springframework.data.redis.connection.lettuce.LettuceReactiveSetCommands#sDiffStore(org.reactivestreams.Publisher)
	 */
	@Override
	public Flux> sDiffStore(Publisher commands) {

		return getConnection().execute(cmd -> Flux.from(commands).concatMap(command -> {

			Assert.notNull(command.getKeys(), "Source keys must not be null!");
			Assert.notNull(command.getKey(), "Destination key must not be null!");

			List keys = new ArrayList<>(command.getKeys());
			keys.add(command.getKey());

			if (ClusterSlotHashUtil.isSameSlotForAllKeys(keys)) {
				return super.sDiffStore(Mono.just(command));
			}

			return sDiff(Mono.just(SDiffCommand.keys(command.getKeys()))).next().flatMap(values -> {
				Mono result = cmd.sadd(command.getKey(), values.getOutput().toStream().toArray(ByteBuffer[]::new));
				return result.map(value -> new NumericResponse<>(command, value));
			});
		}));
	}

	/* (non-Javadoc)
	 * @see org.springframework.data.redis.connection.lettuce.LettuceReactiveSetCommands#sMove(org.reactivestreams.Publisher)
	 */
	@Override
	public Flux> sMove(Publisher commands) {

		return getConnection().execute(cmd -> Flux.from(commands).concatMap(command -> {

			Assert.notNull(command.getKey(), "Source key must not be null!");
			Assert.notNull(command.getDestination(), "Destination key must not be null!");

			if (ClusterSlotHashUtil.isSameSlotForAllKeys(command.getKey(), command.getDestination())) {
				return super.sMove(Mono.just(command));
			}

			Mono result = cmd.exists(command.getKey())
					.flatMap(nrKeys -> nrKeys == 0 ? Mono.empty() : cmd.sismember(command.getKey(), command.getValue()))
					.flatMap(exists -> {

						if (!exists) {
							return Mono.just(Boolean.FALSE);
						}
						return cmd.sismember(command.getDestination(), command.getValue()).flatMap(existsInTarget -> {

							Mono tmp = cmd.srem(command.getKey(), command.getValue()).map(nrRemoved -> nrRemoved > 0);
							if (!existsInTarget) {
								return tmp.flatMap(removed -> cmd.sadd(command.getDestination(), command.getValue())
										.map(LettuceConverters::toBoolean));
							}
							return tmp;
						});

					});

			return result.defaultIfEmpty(Boolean.FALSE).map(value -> new BooleanResponse<>(command, value));
		}));
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy