|
1 | 1 | package io.smallrye.reactive.messaging.rabbitmq.og; |
2 | 2 |
|
3 | 3 | import java.nio.charset.StandardCharsets; |
| 4 | +import java.util.concurrent.CompletableFuture; |
4 | 5 | import java.util.concurrent.CompletionStage; |
| 6 | +import java.util.concurrent.atomic.AtomicBoolean; |
5 | 7 | import java.util.function.BiFunction; |
6 | 8 | import java.util.function.Function; |
7 | | -import java.util.function.Supplier; |
8 | 9 |
|
9 | | -import org.eclipse.microprofile.reactive.messaging.Message; |
10 | 10 | import org.eclipse.microprofile.reactive.messaging.Metadata; |
11 | 11 |
|
12 | 12 | import com.rabbitmq.client.AMQP; |
|
27 | 27 | */ |
28 | 28 | public class IncomingRabbitMQMessage<T> implements ContextAwareMessage<T>, MetadataInjectableMessage<T> { |
29 | 29 |
|
| 30 | + private final AtomicBoolean acknowledged = new AtomicBoolean(false); |
| 31 | + |
30 | 32 | private final T payload; |
31 | 33 | private Metadata metadata; |
32 | 34 | private final RabbitMQAckHandler ackHandler; |
@@ -146,73 +148,45 @@ public java.util.Map<String, Object> getHeaders() { |
146 | 148 | } |
147 | 149 |
|
148 | 150 | @Override |
149 | | - public Supplier<CompletionStage<Void>> getAck() { |
150 | | - return () -> ackHandler.handle(this); |
| 151 | + public Function<Metadata, CompletionStage<Void>> getAckWithMetadata() { |
| 152 | + return this::ack; |
151 | 153 | } |
152 | 154 |
|
153 | 155 | @Override |
154 | | - public Function<Throwable, CompletionStage<Void>> getNack() { |
155 | | - return (failure) -> nackHandler.handle(this, null, failure); |
| 156 | + public BiFunction<Throwable, Metadata, CompletionStage<Void>> getNackWithMetadata() { |
| 157 | + return this::nack; |
156 | 158 | } |
157 | 159 |
|
158 | 160 | @Override |
159 | | - public BiFunction<Throwable, Metadata, CompletionStage<Void>> getNackWithMetadata() { |
160 | | - return this::nack; |
| 161 | + public CompletionStage<Void> ack(Metadata metadata) { |
| 162 | + if (acknowledged.compareAndSet(false, true)) { |
| 163 | + return ackHandler.handle(this) |
| 164 | + .whenComplete((v, t) -> { |
| 165 | + if (t != null) { |
| 166 | + acknowledged.set(false); |
| 167 | + } |
| 168 | + }); |
| 169 | + } |
| 170 | + return CompletableFuture.completedFuture(null); |
161 | 171 | } |
162 | 172 |
|
163 | | - /** |
164 | | - * Nack with metadata support. |
165 | | - * |
166 | | - * @param reason the reason for the nack |
167 | | - * @param metadata additional nack metadata |
168 | | - * @return a completion stage |
169 | | - */ |
170 | 173 | public CompletionStage<Void> nack(Throwable reason, Metadata metadata) { |
171 | | - return nackHandler.handle(this, metadata, reason); |
| 174 | + if (acknowledged.compareAndSet(false, true)) { |
| 175 | + return nackHandler.handle(this, metadata, reason) |
| 176 | + .whenComplete((v, t) -> { |
| 177 | + if (t != null) { |
| 178 | + acknowledged.set(false); |
| 179 | + } |
| 180 | + }); |
| 181 | + } |
| 182 | + return CompletableFuture.completedFuture(null); |
172 | 183 | } |
173 | 184 |
|
174 | 185 | @Override |
175 | 186 | public synchronized void injectMetadata(Object metadataObject) { |
176 | 187 | this.metadata = this.metadata.with(metadataObject); |
177 | 188 | } |
178 | 189 |
|
179 | | - /** |
180 | | - * Create a new message with a different payload but same metadata and ack/nack handlers. |
181 | | - * This is useful for transforming messages in a processing chain. |
182 | | - * |
183 | | - * @param <P> the new payload type |
184 | | - * @param newPayload the new payload |
185 | | - * @return a new message with the new payload |
186 | | - */ |
187 | | - public <P> Message<P> withPayload(P newPayload) { |
188 | | - return new Message<P>() { |
189 | | - @Override |
190 | | - public P getPayload() { |
191 | | - return newPayload; |
192 | | - } |
193 | | - |
194 | | - @Override |
195 | | - public Metadata getMetadata() { |
196 | | - return IncomingRabbitMQMessage.this.metadata; |
197 | | - } |
198 | | - |
199 | | - @Override |
200 | | - public Supplier<CompletionStage<Void>> getAck() { |
201 | | - return IncomingRabbitMQMessage.this.getAck(); |
202 | | - } |
203 | | - |
204 | | - @Override |
205 | | - public Function<Throwable, CompletionStage<Void>> getNack() { |
206 | | - return IncomingRabbitMQMessage.this.getNack(); |
207 | | - } |
208 | | - |
209 | | - @Override |
210 | | - public BiFunction<Throwable, Metadata, CompletionStage<Void>> getNackWithMetadata() { |
211 | | - return IncomingRabbitMQMessage.this.getNackWithMetadata(); |
212 | | - } |
213 | | - }; |
214 | | - } |
215 | | - |
216 | 190 | /** |
217 | 191 | * Default converter from byte array to String using UTF-8. |
218 | 192 | */ |
|
0 commit comments