Adding the redis listener via spring-data-redis-reactive.

The listeners need to be configured in the RedisConfig class via Beans. These beans can then invoke complex business logic based on requirements.
This commit is contained in:
Arpit Mohan 2019-10-07 08:18:54 +00:00
parent ccf2be5e6c
commit ad22e1a406
7 changed files with 144 additions and 6 deletions

View File

@ -6,6 +6,7 @@
image: docker:latest
services:
- docker:dind
- redis
cache:
paths:
@ -28,7 +29,7 @@ maven-build:
image: maven:3-jdk-11-slim
stage: build
script:
- mvn package -B -Dspring.profiles.active=local
- mvn package -B -Dspring.profiles.active=$SPRING_PROFILES_ACTIVE
artifacts:
paths:
- appsmith-server/target/*.jar

View File

@ -76,6 +76,10 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>

View File

@ -0,0 +1,74 @@
package com.appsmith.server.configurations;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory;
import org.springframework.data.redis.connection.ReactiveSubscription;
import org.springframework.data.redis.core.ReactiveRedisOperations;
import org.springframework.data.redis.core.ReactiveRedisTemplate;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.data.redis.listener.ReactiveRedisMessageListenerContainer;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
@Slf4j
public class RedisConfig {
/**
* This is the topic to which we will publish & subscribe to. We can have multiple topics based on the messages
* that we wish to broadcast. Starting with a single one for now.
* @return
*/
@Bean
ChannelTopic topic() {
return new ChannelTopic("appsmith:queue");
}
@Bean
public ReactiveRedisTemplate<String, String> reactiveRedisTemplate(ReactiveRedisConnectionFactory factory) {
return new ReactiveRedisTemplate<>(factory, RedisSerializationContext.string());
}
/**
* This is the listener that will receive all the messages from the Redis channel topic configured in topic().
* Adding dummy implementation with log message for now, but can be extended to include more complex behaviour
*
* @param factory
* @return
*/
@Bean
ReactiveRedisMessageListenerContainer container(ReactiveRedisConnectionFactory factory) {
ReactiveRedisMessageListenerContainer container = new ReactiveRedisMessageListenerContainer(factory);
container
// The receive function can subscribe to multiple topics as well. Can also subscribe via regex pattern
// to multiple channels
.receive(topic())
// Extract the message from the incoming object. By default it's String serialization. The receive() fxn
// can also configure different serialization classes based on requirements
.map(ReactiveSubscription.Message::getMessage)
// Actual processing of the message.
.map(msg -> {
log.info("**** In the redis subscribe **** : {}", msg);
return msg;
})
// Required to subscribe else this chain is never invoked
.subscribe();
return container;
}
@Bean
ReactiveRedisOperations<String, String> reactiveRedisOperations(ReactiveRedisConnectionFactory factory) {
Jackson2JsonRedisSerializer<String> serializer = new Jackson2JsonRedisSerializer<>(String.class);
RedisSerializationContext.RedisSerializationContextBuilder<String, String> builder =
RedisSerializationContext.newSerializationContext(new StringRedisSerializer());
RedisSerializationContext<String, String> context = builder.value(serializer).build();
return new ReactiveRedisTemplate<>(factory, context);
}
}

View File

@ -4,6 +4,8 @@ import com.appsmith.server.domains.User;
import com.appsmith.server.services.SessionUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ReactiveRedisTemplate;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@ -18,9 +20,17 @@ public class IndexController {
private final SessionUserService service;
private final ReactiveRedisTemplate<String, String> reactiveTemplate;
private final ChannelTopic topic;
@Autowired
public IndexController(SessionUserService service) {
public IndexController(SessionUserService service,
ReactiveRedisTemplate<String, String> reactiveTemplate,
ChannelTopic topic) {
this.service = service;
this.reactiveTemplate = reactiveTemplate;
this.topic = topic;
}
@GetMapping
@ -30,4 +40,14 @@ public class IndexController {
.map(Principal::getName)
.map(name -> String.format("Hello %s", name));
}
/*
* This function is primarily for testing if we can publish to Redis successfully. If yes, the response should be
* non-zero value number of subscribers who've successfully gotten the published message
*/
@GetMapping("/redisPub")
public Mono<Long> pubRedisMessage() {
return reactiveTemplate.convertAndSend(topic.getTopic(), "This is a test message");
}
}

View File

@ -1,17 +1,34 @@
#Mongo properties
spring.data.mongodb.database=mobtools
spring.data.mongodb.host=mongo
spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
#spring.data.mongodb.username=
#spring.data.mongodb.password=
# Log properties
logging.level.root=info
logging.level.com.appsmith=debug
logging.pattern.console=%X - %m%n
# JDBC Postgres properties
jdbc.postgres.driver=org.postgresql.Driver
jdbc.postgres.url=jdbc:postgresql://localhost/mobtools
jdbc.postgres.username=postgres
jdbc.postgres.password=root
#Spring security
spring.security.oauth2.client.registration.google.client-id=869021686091-9b84bbf7ea683t1aaefqnmefcnmk6fq6.apps.googleusercontent.com
spring.security.oauth2.client.registration.google.client-secret=9dvITt4OayEY1HfeY8bHX74p
# Accounts from specific domains are allowed to login
oauth2.allowed-domains=appsmith.com
oauth2.allowed-domains=appsmith.com
# Segment & Rollbar Properties
# These properties are intentionally set to random values so that events are not sent to either of them during local development
segment.writeKey=random-value
com.rollbar.access-token=random-value
com.rollbar.environment=development
# Redis Properties
spring.redis.host=redis
spring.redis.port=6379

View File

@ -4,21 +4,31 @@ spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
#spring.data.mongodb.username=
#spring.data.mongodb.password=
# Log properties
logging.level.root=info
logging.level.com.appsmith=debug
logging.pattern.console=%X - %m%n
# JDBC Postgres properties
jdbc.postgres.driver=org.postgresql.Driver
jdbc.postgres.url=jdbc:postgresql://localhost/mobtools
jdbc.postgres.username=postgres
jdbc.postgres.password=root
#Spring security
spring.security.oauth2.client.registration.google.client-id=869021686091-9b84bbf7ea683t1aaefqnmefcnmk6fq6.apps.googleusercontent.com
spring.security.oauth2.client.registration.google.client-secret=9dvITt4OayEY1HfeY8bHX74p
# Accounts from specific domains are allowed to login
oauth2.allowed-domains=appsmith.com
# Segment & Rollbar Properties
# These properties are intentionally set to random values so that events are not sent to either of them during local development
segment.writeKey=random-value
com.rollbar.access-token=random-value
com.rollbar.environment=development
com.rollbar.environment=development
# Redis Properties
spring.redis.host=127.0.0.1
spring.redis.port=6379

View File

@ -2,20 +2,32 @@
spring.data.mongodb.database=mobtools
spring.data.mongodb.uri=mongodb+srv://admin:Y9PuxM52gcP3Dgfo@mobtools-test-cluster-swrsq.mongodb.net/mobtools?retryWrites=true
spring.data.mongodb.authentication-database=admin
# Log properties
logging.level.root=info
logging.level.com.appsmith=debug
logging.pattern.console=%X - %m%n
# JDBC Postgres properties
jdbc.postgres.driver=org.postgresql.Driver
jdbc.postgres.url=jdbc:postgresql://ec2-54-247-85-251.eu-west-1.compute.amazonaws.com/d266aalso50024
jdbc.postgres.username=pornlzmggggpgk
jdbc.postgres.password=09275163cd7e737baf4c210b5e8db8ed88ddb7a0ee9acc82416fd75346ea4bbb
#Spring security
spring.security.oauth2.client.registration.google.client-id=869021686091-9b84bbf7ea683t1aaefqnmefcnmk6fq6.apps.googleusercontent.com
spring.security.oauth2.client.registration.google.client-secret=9dvITt4OayEY1HfeY8bHX74p
# Accounts from specific domains are allowed to login
oauth2.allowed-domains=appsmith.com
# Segment & Rollbar Properties
segment.writeKey=FIRLqUgMYuTlyS6yqOE2hBGZs5umkWhr
com.rollbar.access-token=b91c4d5b9cac444088f4db9216ed6f42
com.rollbar.environment=development
com.rollbar.environment=development
# Redis Properties
spring.redis.host=ec2-99-80-39-26.eu-west-1.compute.amazonaws.com
spring.redis.port=19989
spring.redis.user=h
spring.redis.password=p46c3e6d77c32e6f1026f16ae781911d8a2631ece413406a75fc31b0cfb9edb03