Skip to content

Commit 6ba371f

Browse files
authored
Version 2.1.0
* Provide a way to enqueue unique messages #27 * Provide a way to add HTTP proxy for external api calls #34 * Provide a way to fetch messages based on the id and queue name * Provide api to delete any enqueued messages #33 * Enqueue a list of Objects #37 * Do not delete queues if mode is PRODUCER #24 * Add csp meta data #38
1 parent 4c9c5c8 commit 6ba371f

File tree

180 files changed

+4703
-1671
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

180 files changed

+4703
-1671
lines changed

.travis.yml

+4
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ env:
1010
- ORG_GRADLE_PROJECT_sonatypeUsername=xxx
1111
- ORG_GRADLE_PROJECT_sonatypePassword=xxx
1212
- USER_NAME=rqueue
13+
- REDIS_RUNNING=true
14+
- CI_ENV=true
1315

1416
cache:
1517
directories:
@@ -30,6 +32,8 @@ before_script:
3032
- cd 9004 && redis-server ./redis.conf &
3133
- cd 9005 && redis-server ./redis.conf &
3234
- redis-cli --cluster create 127.0.0.1:9000 127.0.0.1:9001 127.0.0.1:9002 127.0.0.1:9003 127.0.0.1:9004 127.0.0.1:9005 --cluster-replicas 1 --cluster-yes
35+
- df -h
36+
- lscpu
3337

3438
jobs:
3539
include:

CHANGELOG.md

+12
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,17 @@
22

33
**NOTE**: The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
44

5+
## [2.1.0] - 16-Sep-2020
6+
### Added
7+
* Allow application to provide message id while enqueuing messages
8+
* Unique message enqueue
9+
* Api to check if message was enqueued or not
10+
* Api to delete single message
11+
* Proxy for outbound http connection
12+
* Enqueue list of objects and process them, like batch-processing
13+
14+
Fixes:
15+
* Registered queues should not be deleted when used in producer mode
516

617
## [2.0.4] - 2-Aug-2020
718

@@ -92,3 +103,4 @@
92103
[2.0.1]: https://repo1.maven.org/maven2/com/github/sonus21/rqueue/2.0.1-RELEASE
93104
[2.0.2]: https://repo1.maven.org/maven2/com/github/sonus21/rqueue/2.0.2-RELEASE
94105
[2.0.4]: https://repo1.maven.org/maven2/com/github/sonus21/rqueue/2.0.4-RELEASE
106+
[2.1.0]: https://repo1.maven.org/maven2/com/github/sonus21/rqueue/2.1.0-RELEASE

README.md

+20-18
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,22 @@
1313

1414
## Features
1515

16-
* A message can be delayed for an arbitrary period or delivered immediately.
17-
* Multiple messages can be consumed in parallel by different workers.
18-
* Message delivery: It's guaranteed that a message is consumed **at least once**. (Message would be consumed by a worker more than once due to the failure in the underlying worker/restart-process etc, otherwise exactly one delivery)
19-
* Support Redis cluster
20-
* Queue metrics
21-
* Different Redis connection for application and worker
22-
* Web interface for queue management and queue statistics
23-
* Automatic message serialization and deserialization
24-
* Queue concurrency
25-
* Group level queue priority(weighted and strict)
26-
* Sub queue priority(weighted and strict)
27-
* Task execution back off, exponential and fixed back off (default fixed back off)
28-
* Callbacks for different actions
29-
* Events 1. Bootstrap event 2. Task execution event.
16+
* **Message Scheduling** : A message can be scheduled for any arbitrary period
17+
* **Competing Consumers** multiple messages can be consumed in parallel by different workers.
18+
* **Message delivery**: It's guaranteed that a message is consumed **at least once**. (Message would be consumed by a worker more than once due to the failure in the underlying worker/restart-process etc, otherwise exactly one delivery)
19+
* **Redis cluster** : Redis cluster can be used with driver.
20+
* **Metrics** : In flight messages, waiting for consumption and delayed messages
21+
* **Web interface**: a web interface to manage a queue and queue insights including latency
22+
* **Automatic message serialization and deserialization**
23+
* **Concurrency**: Concurrency of any queue can be configured
24+
* **Queue Priority** :
25+
* Group level queue priority(weighted and strict)
26+
* Sub queue priority(weighted and strict)
27+
* **Execution Backoff** : Exponential and fixed back off (default fixed back off)
28+
* **Callbacks** : Callbacks for dead letter queue, discard etc
29+
* **Events** 1. Bootstrap event 2. Task execution event.
30+
* **Unique message** : Unique message processing for a queue based on the message id
31+
* **Redis connection**: A different redis setup can be used for Rqueue
3032

3133
## Getting Started
3234

@@ -37,14 +39,14 @@
3739
* Add dependency
3840
* Gradle
3941
```groovy
40-
implementation 'com.github.sonus21:rqueue-spring-boot-starter:2.0.4-RELEASE'
42+
implementation 'com.github.sonus21:rqueue-spring-boot-starter:2.1.0-RELEASE'
4143
```
4244
* Maven
4345
```xml
4446
<dependency>
4547
<groupId>com.github.sonus21</groupId>
4648
<artifactId>rqueue-spring-boot-starter</artifactId>
47-
<version>2.0.4-RELEASE</version>
49+
<version>2.1.0-RELEASE</version>
4850
</dependency>
4951
```
5052
@@ -53,14 +55,14 @@
5355
* Add Dependency
5456
* Gradle
5557
```groovy
56-
implementation 'com.github.sonus21:rqueue-spring:2.0.4-RELEASE'
58+
implementation 'com.github.sonus21:rqueue-spring:2.1.0-RELEASE'
5759
```
5860
* Maven
5961
```xml
6062
<dependency>
6163
<groupId>com.github.sonus21</groupId>
6264
<artifactId>rqueue-spring</artifactId>
63-
<version>2.0.4-RELEASE</version>
65+
<version>2.1.0-RELEASE</version>
6466
</dependency>
6567
```
6668

build.gradle

+13-14
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ allprojects {
1111
apply plugin: 'signing'
1212
apply plugin: 'jacoco'
1313
apply plugin: 'nebula.optional-base'
14+
1415
sourceCompatibility = 1.8
1516
targetCompatibility = 1.8
1617

@@ -36,10 +37,9 @@ ext {
3637
sl4jVersion = '1.7.28'
3738

3839
// testing
39-
junitVersion = '4.12'
40-
mockitoVersion = '3.1.0'
40+
jupiterVersion = '5.5.0'
41+
mockitoVersion = '3.5.0'
4142
hamcrestVersion = '2.2'
42-
powerMockVersion = '2.0.5'
4343
jacocoVersion = '0.8.4'
4444
embeddedRedisVersion = '0.7.2'
4545
h2Version = '1.4.194'
@@ -67,7 +67,7 @@ ext {
6767

6868
subprojects {
6969
group = 'com.github.sonus21'
70-
version = '2.0.4-RELEASE'
70+
version = '2.1.0-RELEASE'
7171

7272
dependencies {
7373
// https://mvnrepository.com/artifact/org.springframework/spring-messaging
@@ -84,22 +84,21 @@ subprojects {
8484
testCompile group: 'ch.qos.logback', name: 'logback-core', version: "${logbackVersion}"
8585
// https://mvnrepository.com/artifact/ch.qos.logback/logback-classic
8686
testCompile group: 'ch.qos.logback', name: 'logback-classic', version: "${logbackVersion}"
87-
testCompile group: 'junit', name: 'junit', version: "${junitVersion}"
88-
// https://mvnrepository.com/artifact/org.mockito/mockito-core
89-
testCompile group: 'org.mockito', name: 'mockito-core', version: "${mockitoVersion}"
90-
// https://mvnrepository.com/artifact/org.hamcrest/hamcrest-library
91-
testCompile group: 'org.hamcrest', name: 'hamcrest-library', version: "${hamcrestVersion}"
87+
testRuntime group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: "${jupiterVersion}"
88+
testCompile group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: "${jupiterVersion}"
89+
// https://mvnrepository.com/artifact/org.mockito/mockito-inline
90+
testCompile group: 'org.mockito', name: 'mockito-inline', version: "${mockitoVersion}"
91+
testCompile group: 'org.mockito', name: 'mockito-junit-jupiter', version: "${mockitoVersion}"
92+
// https://mvnrepository.com/artifact/org.hamcrest/hamcrest
93+
testCompile group: 'org.hamcrest', name: 'hamcrest', version: "${hamcrestVersion}"
9294
// https://mvnrepository.com/artifact/org.apache.commons/commons-lang3
9395
testCompile group: 'org.apache.commons', name: 'commons-lang3', version: "${lang3Version}"
9496
testCompile("org.springframework.boot:spring-boot-test:${springBootVersion}")
95-
// https://mvnrepository.com/artifact/org.powermock/powermock-module-junit4
96-
testCompile group: 'org.powermock', name: 'powermock-module-junit4', version: "${powerMockVersion}"
97-
98-
// https://mvnrepository.com/artifact/org.powermock/powermock-api-mockito2
99-
testCompile group: 'org.powermock', name: 'powermock-api-mockito2', version: "${powerMockVersion}"
97+
testCompile group: 'org.junit-pioneer', name: 'junit-pioneer', version: '0.9.0'
10098

10199
configurations {
102100
all*.exclude module: 'spring-boot-starter-logging'
101+
all*.exclude module: 'junit'
103102
}
104103
}
105104
}

rqueue-common-test/build.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ dependencies {
2323
// https://mvnrepository.com/artifact/javax.annotation/javax.annotation-api
2424
compile group: 'javax.annotation', name: 'javax.annotation-api', version: "${javaxAnnotationVersion}"
2525

26-
compile group: 'junit', name: 'junit', version: "${junitVersion}"
26+
compile group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: "${jupiterVersion}"
2727

2828
compile group: 'org.apache.commons', name: 'commons-lang3', version: "${lang3Version}"
2929

rqueue-common-test/src/main/java/com/github/sonus21/rqueue/test/MessageListener.java

+12
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package com.github.sonus21.rqueue.test;
1818

19+
import com.fasterxml.jackson.core.JsonProcessingException;
1920
import com.github.sonus21.rqueue.annotation.RqueueListener;
2021
import com.github.sonus21.rqueue.core.RqueueMessage;
2122
import com.github.sonus21.rqueue.listener.RqueueMessageHeaders;
@@ -29,6 +30,8 @@
2930
import com.github.sonus21.rqueue.test.dto.Sms;
3031
import com.github.sonus21.rqueue.test.service.ConsumedMessageService;
3132
import com.github.sonus21.rqueue.test.service.FailureManager;
33+
import java.util.List;
34+
import java.util.UUID;
3235
import lombok.NonNull;
3336
import lombok.RequiredArgsConstructor;
3437
import lombok.extern.slf4j.Slf4j;
@@ -163,4 +166,13 @@ public void onMessageReservationRequestDeadLetterQueue(ReservationRequest reques
163166
log.info("ReservationRequest Dead Letter Queue{}", request);
164167
consumedMessageService.save(request, "reservation-request-dlq");
165168
}
169+
170+
@RqueueListener(value = "${list.email.queue.name}", active = "${list.email.queue.enabled}")
171+
public void onMessageEmailList(List<Email> emailList) throws JsonProcessingException {
172+
log.info("onMessageEmailList {}", emailList);
173+
String consumedId = UUID.randomUUID().toString();
174+
for (Email email : emailList) {
175+
consumedMessageService.save(email, consumedId);
176+
}
177+
}
166178
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
/*
2+
* Copyright 2020 Sonu Kumar
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.github.sonus21.rqueue.test.application;
18+
19+
import com.fasterxml.jackson.databind.ObjectMapper;
20+
import java.io.BufferedReader;
21+
import java.io.InputStreamReader;
22+
import java.util.ArrayList;
23+
import java.util.LinkedList;
24+
import java.util.List;
25+
import java.util.concurrent.ExecutorService;
26+
import java.util.concurrent.Executors;
27+
import javax.sql.DataSource;
28+
import lombok.AllArgsConstructor;
29+
import org.slf4j.Logger;
30+
import org.slf4j.LoggerFactory;
31+
import org.springframework.beans.factory.annotation.Value;
32+
import org.springframework.context.annotation.Bean;
33+
import org.springframework.data.redis.connection.RedisNode;
34+
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
35+
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
36+
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
37+
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
38+
import redis.embedded.RedisServer;
39+
40+
public abstract class ApplicationBasicConfiguration {
41+
private static final Logger monitorLogger = LoggerFactory.getLogger("monitor");
42+
protected RedisServer redisServer;
43+
protected ExecutorService executorService;
44+
protected List<RProcess> processes;
45+
@Value("${mysql.db.name}")
46+
protected String dbName;
47+
@Value("${spring.redis.port}")
48+
protected int redisPort;
49+
@Value("${spring.redis.host}")
50+
protected String redisHost;
51+
@Value("${use.system.redis:false}")
52+
protected boolean useSystemRedis;
53+
@Value("${monitor.thread.count:0}")
54+
protected int monitorThreads;
55+
56+
protected void init() {
57+
if (monitorThreads > 0) {
58+
executorService = Executors.newFixedThreadPool(monitorThreads);
59+
processes = new ArrayList<>();
60+
}
61+
if (useSystemRedis) {
62+
return;
63+
}
64+
if (redisServer == null) {
65+
redisServer = new RedisServer(redisPort);
66+
redisServer.start();
67+
}
68+
}
69+
70+
protected void destroy() {
71+
if (redisServer != null) {
72+
redisServer.stop();
73+
}
74+
75+
if (processes != null) {
76+
for (RProcess rProcess : processes) {
77+
rProcess.process.destroy();
78+
monitorLogger.info("RedisNode {} ", rProcess.redisNode);
79+
for (String line : rProcess.out) {
80+
monitorLogger.info("{}", line);
81+
}
82+
}
83+
}
84+
if (executorService != null) {
85+
executorService.shutdown();
86+
}
87+
}
88+
89+
protected void monitor(String host, int port) {
90+
executorService.submit(
91+
() -> {
92+
try {
93+
Process process =
94+
Runtime.getRuntime()
95+
.exec("redis-cli " + " -h " + host + " -p " + port + " monitor");
96+
List<String> lines = new LinkedList<>();
97+
RProcess rProcess = new RProcess(process, new RedisNode(host, port), lines);
98+
processes.add(rProcess);
99+
BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
100+
String s;
101+
while ((s = br.readLine()) != null) {
102+
lines.add(s);
103+
}
104+
process.waitFor();
105+
} catch (Exception e) {
106+
monitorLogger.error("Process call failed", e);
107+
}
108+
});
109+
}
110+
111+
@Bean
112+
public DataSource dataSource() {
113+
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
114+
return builder.setType(EmbeddedDatabaseType.H2).setName(dbName).build();
115+
}
116+
117+
@Bean
118+
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
119+
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
120+
vendorAdapter.setGenerateDdl(true);
121+
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
122+
factory.setJpaVendorAdapter(vendorAdapter);
123+
factory.setPackagesToScan("com.github.sonus21.rqueue.test.entity");
124+
factory.setDataSource(dataSource);
125+
return factory;
126+
}
127+
128+
@Bean
129+
public ObjectMapper objectMapper() {
130+
return new ObjectMapper();
131+
}
132+
133+
@AllArgsConstructor
134+
public static class RProcess {
135+
Process process;
136+
RedisNode redisNode;
137+
List<String> out;
138+
}
139+
}

0 commit comments

Comments
 (0)