@Test public void saveLastAccessChanged() { given(this.redisOperations.hasKey(anyString())).willReturn(Mono.just(true)); given(this.redisOperations.opsForHash()).willReturn(this.hashOperations); given(this.hashOperations.putAll(anyString(), any())).willReturn(Mono.just(true)); given(this.redisOperations.expire(anyString(), any())) .willReturn(Mono.just(true)); RedisSession session = this.repository.new RedisSession(this.cached); session.setLastAccessedTime(Instant.ofEpochMilli(12345678L)); Mono.just(session).subscribe(this.repository::save); verify(this.redisOperations).hasKey(anyString()); verify(this.redisOperations).opsForHash(); verify(this.hashOperations).putAll(anyString(), this.delta.capture()); verify(this.redisOperations).expire(anyString(), any()); verifyZeroInteractions(this.redisOperations); verifyZeroInteractions(this.hashOperations); assertThat(this.delta.getAllValues().get(0)) .isEqualTo(map(RedisOperationsSessionRepository.LAST_ACCESSED_ATTR, session.getLastAccessedTime().toEpochMilli())); }
@Test public void getSessionNotFound() { given(this.redisOperations.opsForHash()).willReturn(this.hashOperations); given(this.hashOperations.entries(anyString())).willReturn(Flux.empty()); given(this.redisOperations.delete(anyString())).willReturn(Mono.just(0L)); StepVerifier.create(this.repository.findById("test")).verifyComplete(); verify(this.redisOperations).opsForHash(); verify(this.hashOperations).entries(anyString()); verify(this.redisOperations).delete(anyString()); verifyZeroInteractions(this.redisOperations); verifyZeroInteractions(this.hashOperations); }
/** * Executes the given {@link RedisScript}. * * @param script must not be {@literal null}. * @return result value of the script {@link Flux#empty()} if {@link RedisScript#getResultType()} is {@literal null}, * likely indicating a throw-away status reply (i.e. "OK"). */ default <T> Flux<T> execute(RedisScript<T> script) { return execute(script, Collections.emptyList()); }
private Mono<Void> saveDelta() { if (this.delta.isEmpty()) { return Mono.empty(); } String sessionKey = getSessionKey(getId()); Mono<Boolean> update = ReactiveRedisOperationsSessionRepository.this.sessionRedisOperations .opsForHash().putAll(sessionKey, this.delta); Mono<Boolean> setTtl = ReactiveRedisOperationsSessionRepository.this.sessionRedisOperations .expire(sessionKey, getMaxInactiveInterval()); return update.and(setTtl).and((s) -> { this.delta.clear(); s.onComplete(); }).then(); }
@Test public void saveSessionNothingChanged() { given(this.redisOperations.hasKey(anyString())).willReturn(Mono.just(true)); given(this.redisOperations.expire(anyString(), any())) .willReturn(Mono.just(true)); RedisSession session = this.repository.new RedisSession( new MapSession(this.cached)); StepVerifier.create(this.repository.save(session)).verifyComplete(); verify(this.redisOperations).hasKey(anyString()); verifyZeroInteractions(this.redisOperations); verifyZeroInteractions(this.hashOperations); }
@Override public Mono<RedisSession> findById(String id) { String sessionKey = getSessionKey(id); // @formatter:off return this.sessionRedisOperations.opsForHash().entries(sessionKey) .collectMap((e) -> e.getKey().toString(), Map.Entry::getValue) .filter((map) -> !map.isEmpty()) .map(new SessionMapper(id)) .filter((session) -> !session.isExpired()) .map(RedisSession::new) .switchIfEmpty(Mono.defer(() -> deleteById(id).then(Mono.empty()))); // @formatter:on }
/** * Subscribe to the given Redis {@code channels} and emit {@link Message messages} received for those. * * @param channels must not be {@literal null}. * @return a hot sequence of {@link Message messages}. * @since 2.1 */ default Flux<? extends Message<String, V>> listenToChannel(String... channels) { Assert.notNull(channels, "Channels must not be null!"); return listenTo(Arrays.stream(channels).map(ChannelTopic::of).toArray(ChannelTopic[]::new)); }
public Mono<Boolean> deleteAll() { return this.reactiveRedisOperations.opsForList().delete("posts"); } }
/** * Use a {@link Flux} to iterate over keys. The resulting {@link Flux} acts as a cursor and issues {@code SCAN} * commands itself as long as the subscriber signals demand. * * @return the {@link Flux} emitting the {@literal keys} one by one or an {@link Flux#empty() empty flux} if none * exist. * @see <a href="http://redis.io/commands/scan">Redis Documentation: SCAN</a> * @since 2.1 */ default Flux<K> scan() { return scan(ScanOptions.NONE); }
@Override public Mono<Void> deleteById(String id) { String sessionKey = getSessionKey(id); return this.sessionRedisOperations.delete(sessionKey).then(); }
@Override public Mono<Void> save(RedisSession session) { Mono<Void> result = session.saveChangeSessionId().and(session.saveDelta()) .and((s) -> { session.isNew = false; s.onComplete(); }); if (session.isNew) { return result; } else { String sessionKey = getSessionKey( session.hasChangedSessionId() ? session.originalSessionId : session.getId()); return this.sessionRedisOperations.hasKey(sessionKey) .flatMap((exists) -> exists ? result : Mono.error(new IllegalStateException( "Session was invalidated"))); } }
@PostMapping("") public Mono<Long> save(@RequestBody Post post) { return this.reactiveRedisOperations.convertAndSend("posts", post ); }
@Test @SuppressWarnings("unchecked") public void getSessionFound() { given(this.redisOperations.opsForHash()).willReturn(this.hashOperations); String attribute1 = "attribute1"; String attribute2 = "attribute2"; verify(this.redisOperations).opsForHash(); verify(this.hashOperations).entries(anyString()); verifyZeroInteractions(this.redisOperations);
@Test public void saveNewSession() { given(this.redisOperations.opsForHash()).willReturn(this.hashOperations); given(this.hashOperations.putAll(anyString(), any())).willReturn(Mono.just(true)); given(this.redisOperations.expire(anyString(), any())) .willReturn(Mono.just(true)); StepVerifier .create(this.repository.createSession().doOnNext(this.repository::save)) .consumeNextWith((session) -> { verify(this.redisOperations).opsForHash(); verify(this.hashOperations).putAll(anyString(), this.delta.capture()); verify(this.redisOperations).expire(anyString(), any()); verifyZeroInteractions(this.redisOperations); verifyZeroInteractions(this.hashOperations); Map<String, Object> delta = this.delta.getAllValues().get(0); assertThat(delta.size()).isEqualTo(3); assertThat(delta.get( ReactiveRedisOperationsSessionRepository.CREATION_TIME_KEY)) .isEqualTo(session.getCreationTime().toEpochMilli()); assertThat(delta.get( ReactiveRedisOperationsSessionRepository.MAX_INACTIVE_INTERVAL_KEY)) .isEqualTo((int) Duration.ofSeconds( MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS) .getSeconds()); assertThat(delta.get( ReactiveRedisOperationsSessionRepository.LAST_ACCESSED_TIME_KEY)) .isEqualTo( session.getLastAccessedTime().toEpochMilli()); }).verifyComplete(); }
/** * Subscribe to the Redis channels matching the given {@code pattern} and emit {@link Message messages} received for * those. * * @param patterns must not be {@literal null}. * @return a hot sequence of {@link Message messages}. * @since 2.1 */ default Flux<? extends Message<String, V>> listenToPattern(String... patterns) { Assert.notNull(patterns, "Patterns must not be null!"); return listenTo(Arrays.stream(patterns).map(PatternTopic::of).toArray(PatternTopic[]::new)); }
public Flux<Post> findAll(){ return this.reactiveRedisOperations.opsForList().range("posts", 0, -1); }
/** * Use a {@link Flux} to iterate over keys. The resulting {@link Flux} acts as a cursor and issues {@code SCAN} * commands itself as long as the subscriber signals demand. * * @return the {@link Flux} emitting the {@literal keys} one by one or an {@link Flux#empty() empty flux} if none * exist. * @see <a href="http://redis.io/commands/scan">Redis Documentation: SCAN</a> * @since 2.1 */ default Flux<K> scan() { return scan(ScanOptions.NONE); }
@Test public void delete() { given(this.redisOperations.delete(anyString())).willReturn(Mono.just(1L)); StepVerifier.create(this.repository.deleteById("test")).verifyComplete(); verify(this.redisOperations).delete(anyString()); verifyZeroInteractions(this.redisOperations); verifyZeroInteractions(this.hashOperations); }
@Test public void saveSetAttribute() { given(this.redisOperations.hasKey(anyString())).willReturn(Mono.just(true)); given(this.redisOperations.opsForHash()).willReturn(this.hashOperations); given(this.hashOperations.putAll(anyString(), any())).willReturn(Mono.just(true)); given(this.redisOperations.expire(anyString(), any())) .willReturn(Mono.just(true)); String attrName = "attrName"; RedisSession session = this.repository.new RedisSession(this.cached); session.setAttribute(attrName, "attrValue"); Mono.just(session).subscribe(this.repository::save); verify(this.redisOperations).hasKey(anyString()); verify(this.redisOperations).opsForHash(); verify(this.hashOperations).putAll(anyString(), this.delta.capture()); verify(this.redisOperations).expire(anyString(), any()); verifyZeroInteractions(this.redisOperations); verifyZeroInteractions(this.hashOperations); assertThat(this.delta.getAllValues().get(0)).isEqualTo( map(RedisOperationsSessionRepository.getSessionAttrNameKey(attrName), session.getAttribute(attrName))); }
Mono<Void> deleteById(String id) { return template.<String, Post>opsForHash().remove("posts", id) .flatMap(p -> Mono.<Void>empty()); }