4
4
import com .rabbitmq .client .ConnectionFactory ;
5
5
import lombok .AccessLevel ;
6
6
import lombok .NoArgsConstructor ;
7
- import lombok .SneakyThrows ;
8
7
import lombok .extern .java .Log ;
9
8
import org .reactivecommons .api .domain .DomainEventBus ;
10
9
import org .reactivecommons .async .commons .DLQDiscardNotifier ;
50
49
import java .security .cert .CertificateException ;
51
50
import java .time .Duration ;
52
51
import java .util .Arrays ;
52
+ import java .util .concurrent .ConcurrentHashMap ;
53
+ import java .util .concurrent .ConcurrentMap ;
53
54
import java .util .logging .Level ;
54
55
55
56
@ Log
56
57
@ NoArgsConstructor (access = AccessLevel .PRIVATE )
57
58
public final class RabbitMQSetupUtils {
58
- private static final String LISTENER_TYPE = "listener" ;
59
- private static final String TOPOLOGY_TYPE = "topology" ;
60
- private static final String SENDER_TYPE = "sender" ;
59
+ private static final String SHARED_TYPE = "shared" ;
61
60
private static final String DEFAULT_PROTOCOL ;
62
61
public static final int START_INTERVAL = 300 ;
63
62
public static final int MAX_BACKOFF_INTERVAL = 3000 ;
64
63
64
+ private static final ConcurrentMap <RabbitProperties , ConnectionFactory > FACTORY_CACHE = new ConcurrentHashMap <>();
65
+ private static final ConcurrentMap <ConnectionFactory , Mono <Connection >> CONNECTION_CACHE = new ConcurrentHashMap <>();
66
+
65
67
static {
66
68
String protocol = "TLSv1.1" ;
67
69
try {
@@ -78,17 +80,23 @@ public final class RabbitMQSetupUtils {
78
80
DEFAULT_PROTOCOL = protocol ;
79
81
}
80
82
81
- @ SneakyThrows
82
83
public static ConnectionFactoryProvider connectionFactoryProvider (RabbitProperties properties ) {
83
- final ConnectionFactory factory = new ConnectionFactory ();
84
- PropertyMapper map = PropertyMapper .get ();
85
- map .from (properties ::determineHost ).whenNonNull ().to (factory ::setHost );
86
- map .from (properties ::determinePort ).to (factory ::setPort );
87
- map .from (properties ::determineUsername ).whenNonNull ().to (factory ::setUsername );
88
- map .from (properties ::determinePassword ).whenNonNull ().to (factory ::setPassword );
89
- map .from (properties ::determineVirtualHost ).whenNonNull ().to (factory ::setVirtualHost );
90
- factory .useNio ();
91
- setUpSSL (factory , properties );
84
+ final ConnectionFactory factory = FACTORY_CACHE .computeIfAbsent (properties , props -> {
85
+ try {
86
+ ConnectionFactory newFactory = new ConnectionFactory ();
87
+ PropertyMapper map = PropertyMapper .get ();
88
+ map .from (props ::determineHost ).whenNonNull ().to (newFactory ::setHost );
89
+ map .from (props ::determinePort ).to (newFactory ::setPort );
90
+ map .from (props ::determineUsername ).whenNonNull ().to (newFactory ::setUsername );
91
+ map .from (props ::determinePassword ).whenNonNull ().to (newFactory ::setPassword );
92
+ map .from (props ::determineVirtualHost ).whenNonNull ().to (newFactory ::setVirtualHost );
93
+ newFactory .useNio ();
94
+ setUpSSL (newFactory , props );
95
+ return newFactory ;
96
+ } catch (Exception e ) {
97
+ throw new RuntimeException ("Error creating ConnectionFactory: " , e );
98
+ }
99
+ });
92
100
return () -> factory ;
93
101
}
94
102
@@ -107,7 +115,7 @@ public static ReactiveMessageSender createMessageSender(ConnectionFactoryProvide
107
115
108
116
public static ReactiveMessageListener createMessageListener (ConnectionFactoryProvider provider , AsyncProps props ) {
109
117
final Mono <Connection > connection =
110
- createConnectionMono (provider .getConnectionFactory (), props .getAppName (), LISTENER_TYPE );
118
+ createConnectionMono (provider .getConnectionFactory (), props .getAppName ());
111
119
final Receiver receiver = RabbitFlux .createReceiver (new ReceiverOptions ().connectionMono (connection ));
112
120
final Sender sender = RabbitFlux .createSender (new SenderOptions ().connectionMono (connection ));
113
121
@@ -119,8 +127,7 @@ public static ReactiveMessageListener createMessageListener(ConnectionFactoryPro
119
127
120
128
public static TopologyCreator createTopologyCreator (AsyncProps props ) {
121
129
ConnectionFactoryProvider provider = connectionFactoryProvider (props .getConnectionProperties ());
122
- final Mono <Connection > connection = createConnectionMono (provider .getConnectionFactory (),
123
- props .getAppName (), TOPOLOGY_TYPE );
130
+ final Mono <Connection > connection = createConnectionMono (provider .getConnectionFactory (), props .getAppName ());
124
131
final Sender sender = RabbitFlux .createSender (new SenderOptions ().connectionMono (connection ));
125
132
return new TopologyCreator (sender , props .getQueueType ());
126
133
}
@@ -134,8 +141,7 @@ public static DiscardNotifier createDiscardNotifier(ReactiveMessageSender sender
134
141
135
142
private static SenderOptions reactiveCommonsSenderOptions (String appName , ConnectionFactoryProvider provider ,
136
143
RabbitProperties rabbitProperties ) {
137
- final Mono <Connection > senderConnection = createConnectionMono (provider .getConnectionFactory (), appName ,
138
- SENDER_TYPE );
144
+ final Mono <Connection > senderConnection = createConnectionMono (provider .getConnectionFactory (), appName );
139
145
final ChannelPoolOptions channelPoolOptions = new ChannelPoolOptions ();
140
146
final PropertyMapper map = PropertyMapper .get ();
141
147
@@ -153,18 +159,20 @@ private static SenderOptions reactiveCommonsSenderOptions(String appName, Connec
153
159
.transform (Utils ::cache ));
154
160
}
155
161
156
- private static Mono <Connection > createConnectionMono (ConnectionFactory factory , String connectionPrefix ,
157
- String connectionType ) {
158
- log .info ("Creating connection mono to RabbitMQ Broker in host '" + factory .getHost () + "' with " +
159
- "type: " + connectionType );
160
- return Mono .fromCallable (() -> factory .newConnection (connectionPrefix + " " + connectionType ))
161
- .doOnError (err ->
162
- log .log (Level .SEVERE , "Error creating connection to RabbitMQ Broker in host '" +
163
- factory .getHost () + "'. Starting retry process..." , err )
164
- )
165
- .retryWhen (Retry .backoff (Long .MAX_VALUE , Duration .ofMillis (START_INTERVAL ))
166
- .maxBackoff (Duration .ofMillis (MAX_BACKOFF_INTERVAL )))
167
- .cache ();
162
+ private static Mono <Connection > createConnectionMono (ConnectionFactory factory , String appName ) {
163
+ return CONNECTION_CACHE .computeIfAbsent (factory , f -> {
164
+ log .info ("Creating connection mono to RabbitMQ Broker in host '" + f .getHost () + "'" );
165
+ return Mono .fromCallable (() -> f .newConnection (
166
+ appName + "-" + InstanceIdentifier .getInstanceId (SHARED_TYPE , "" )
167
+ ))
168
+ .doOnError (err ->
169
+ log .log (Level .SEVERE , "Error creating connection to RabbitMQ Broker in host '"
170
+ + f .getHost () + "'. Starting retry process..." , err )
171
+ )
172
+ .retryWhen (Retry .backoff (Long .MAX_VALUE , Duration .ofMillis (START_INTERVAL ))
173
+ .maxBackoff (Duration .ofMillis (MAX_BACKOFF_INTERVAL )))
174
+ .cache ();
175
+ });
168
176
}
169
177
170
178
// SSL based on RabbitConnectionFactoryBean
0 commit comments