ARTEMIS-2082 Reset buffer valid flag after re-encoding the message
Once a re-encode of the message is done the buffer is not being marked as valid and so subsequent checks on the buffer are all assuming the message data is not valid and re-encoding over and over. This can lead to poor performance in some cases and corrupted data in others.
This commit is contained in:
parent
4507d7783f
commit
e065e3e960
|
@ -694,7 +694,8 @@ public class AMQPMessage extends RefCountMessage {
|
|||
getProtonMessage().encode(new NettyWritable(buffer));
|
||||
byte[] bytes = new byte[buffer.writerIndex()];
|
||||
buffer.readBytes(bytes);
|
||||
this.data = ReadableBuffer.ByteBufferReader.wrap(ByteBuffer.wrap(bytes));
|
||||
data = ReadableBuffer.ByteBufferReader.wrap(ByteBuffer.wrap(bytes));
|
||||
bufferValid = true;
|
||||
} finally {
|
||||
buffer.release();
|
||||
}
|
||||
|
|
|
@ -16,9 +16,9 @@
|
|||
*/
|
||||
package org.apache.activemq.artemis.tests.integration.amqp;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.activemq.artemis.api.core.SimpleString;
|
||||
import org.apache.activemq.artemis.core.server.Queue;
|
||||
import org.apache.activemq.artemis.tests.util.Wait;
|
||||
import org.apache.activemq.transport.amqp.client.AmqpClient;
|
||||
|
@ -339,11 +339,10 @@ public class AmqpExpiredMessageTest extends AmqpClientTestSupport {
|
|||
message.setDurable(true);
|
||||
message.setText("Test-Message");
|
||||
message.setDeliveryAnnotation("shouldDisappear", 1);
|
||||
message.setAbsoluteExpiryTime(System.currentTimeMillis() + 1000);
|
||||
message.setAbsoluteExpiryTime(System.currentTimeMillis() + 250);
|
||||
sender.send(message);
|
||||
|
||||
org.apache.activemq.artemis.core.server.Queue dlq = server.locateQueue(SimpleString.toSimpleString(getDeadLetterAddress()));
|
||||
|
||||
Queue dlq = getProxyToQueue(getDeadLetterAddress());
|
||||
assertTrue("Message not movied to DLQ", Wait.waitFor(() -> dlq.getMessageCount() > 0, 5000, 500));
|
||||
|
||||
connection.close();
|
||||
|
@ -361,11 +360,61 @@ public class AmqpExpiredMessageTest extends AmqpClientTestSupport {
|
|||
receiver.flow(20);
|
||||
|
||||
message = receiver.receive(5, TimeUnit.SECONDS);
|
||||
Assert.assertNotNull(message);
|
||||
Assert.assertEquals(getQueueName(), message.getMessageAnnotation(org.apache.activemq.artemis.api.core.Message.HDR_ORIGINAL_ADDRESS.toString()));
|
||||
Assert.assertNull(message.getDeliveryAnnotation("shouldDisappear"));
|
||||
Assert.assertNull(receiver.receiveNoWait());
|
||||
assertNotNull(message);
|
||||
assertEquals(getQueueName(), message.getMessageAnnotation(org.apache.activemq.artemis.api.core.Message.HDR_ORIGINAL_ADDRESS.toString()));
|
||||
assertNull(message.getDeliveryAnnotation("shouldDisappear"));
|
||||
assertNull(receiver.receiveNoWait());
|
||||
} finally {
|
||||
connection.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test(timeout = 60000)
|
||||
public void testDLQdMessageCanBeRedeliveredMultipleTimes() throws Throwable {
|
||||
AmqpClient client = createAmqpClient();
|
||||
AmqpConnection connection = client.connect();
|
||||
|
||||
try {
|
||||
AmqpSession session = connection.createSession();
|
||||
AmqpSender sender = session.createSender(getQueueName());
|
||||
|
||||
AmqpMessage message = new AmqpMessage();
|
||||
message.setDurable(true);
|
||||
message.setTimeToLive(250);
|
||||
message.setText("Test-Message");
|
||||
message.setMessageId(UUID.randomUUID().toString());
|
||||
message.setApplicationProperty("key", "value");
|
||||
|
||||
sender.send(message);
|
||||
|
||||
Queue dlqView = getProxyToQueue(getDeadLetterAddress());
|
||||
assertTrue("Message not movied to DLQ", Wait.waitFor(() -> dlqView.getMessageCount() > 0, 5000, 200));
|
||||
|
||||
// Read and Modify the message for redelivery repeatedly
|
||||
AmqpReceiver receiver = session.createReceiver(getDeadLetterAddress());
|
||||
receiver.flow(20);
|
||||
|
||||
message = receiver.receive(5, TimeUnit.SECONDS);
|
||||
assertNotNull(message);
|
||||
assertEquals(0, message.getWrappedMessage().getDeliveryCount());
|
||||
|
||||
message.modified(true, false);
|
||||
|
||||
message = receiver.receive(5, TimeUnit.SECONDS);
|
||||
assertNotNull(message);
|
||||
assertEquals(1, message.getWrappedMessage().getDeliveryCount());
|
||||
|
||||
message.modified(true, false);
|
||||
|
||||
message = receiver.receive(5, TimeUnit.SECONDS);
|
||||
assertNotNull(message);
|
||||
assertEquals(2, message.getWrappedMessage().getDeliveryCount());
|
||||
|
||||
message.modified(true, false);
|
||||
|
||||
message = receiver.receive(5, TimeUnit.SECONDS);
|
||||
assertNotNull(message);
|
||||
assertEquals(3, message.getWrappedMessage().getDeliveryCount());
|
||||
} finally {
|
||||
connection.close();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.artemis.tests.integration.amqp;
|
||||
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.DeliveryMode;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Queue;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.TextMessage;
|
||||
|
||||
import org.apache.activemq.artemis.api.core.RoutingType;
|
||||
import org.apache.activemq.artemis.api.core.SimpleString;
|
||||
import org.apache.activemq.artemis.core.server.ActiveMQServer;
|
||||
import org.apache.activemq.artemis.core.server.impl.AddressInfo;
|
||||
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
|
||||
import org.apache.activemq.artemis.junit.Wait;
|
||||
import org.junit.Test;
|
||||
|
||||
public class JMSTransactedRedeliveryBugTest extends JMSClientTestSupport {
|
||||
|
||||
private static final String INITIAL_QUEUE_NAME = "InitialQueue";
|
||||
private static final String FINAL_QUEUE_NAME = "FinalQueue";
|
||||
|
||||
private static final SimpleString INITIAL_QUEUE_SS = new SimpleString(INITIAL_QUEUE_NAME);
|
||||
private static final SimpleString FINAL_QUEUE_SS = new SimpleString(FINAL_QUEUE_NAME);
|
||||
|
||||
@Override
|
||||
protected void addConfiguration(ActiveMQServer server) {
|
||||
server.getAddressSettingsRepository().addMatch(INITIAL_QUEUE_NAME, new AddressSettings().setExpiryAddress(FINAL_QUEUE_SS));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createAddressAndQueues(ActiveMQServer server) throws Exception {
|
||||
super.createAddressAndQueues(server);
|
||||
server.addAddressInfo(new AddressInfo(INITIAL_QUEUE_SS, RoutingType.ANYCAST));
|
||||
server.createQueue(INITIAL_QUEUE_SS, RoutingType.ANYCAST, INITIAL_QUEUE_SS, null, true, false, -1, false, true);
|
||||
server.addAddressInfo(new AddressInfo(FINAL_QUEUE_SS, RoutingType.ANYCAST));
|
||||
server.createQueue(FINAL_QUEUE_SS, RoutingType.ANYCAST, FINAL_QUEUE_SS, null, true, false, -1, false, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getJmsConnectionURIOptions() {
|
||||
return "amqp.traceFrames=true";
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAMQPProducerAMQPConsumer() throws Exception {
|
||||
Connection producerConnection = createConnection();
|
||||
Connection consumerConnection = createConnection();
|
||||
|
||||
try {
|
||||
Session producerSession = producerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
Queue producerQueue = producerSession.createQueue(INITIAL_QUEUE_NAME);
|
||||
MessageProducer producer = producerSession.createProducer(producerQueue);
|
||||
|
||||
TextMessage sentMessage = producerSession.createTextMessage();
|
||||
sentMessage.setStringProperty("something", "KEY");
|
||||
sentMessage.setText("how are you");
|
||||
producer.send(sentMessage, DeliveryMode.PERSISTENT, 4, 10);
|
||||
|
||||
// Simulate a small pause, else both messages could be consumed if
|
||||
// consumer is fast enough
|
||||
Wait.assertTrue("Message should have expired", () -> getProxyToQueue(FINAL_QUEUE_NAME).getMessageCount() == 1);
|
||||
|
||||
Session consumerSession = consumerConnection.createSession(true, Session.SESSION_TRANSACTED);
|
||||
Queue consumerQueue = consumerSession.createQueue(FINAL_QUEUE_NAME);
|
||||
MessageConsumer consumer = consumerSession.createConsumer(consumerQueue);
|
||||
|
||||
Message msg = consumer.receive(1_000);
|
||||
assertNotNull(msg);
|
||||
assertEquals("1", msg.getStringProperty("JMSXDeliveryCount"));
|
||||
assertEquals("KEY", msg.getStringProperty("something"));
|
||||
assertEquals("how are you", ((TextMessage) msg).getText());
|
||||
|
||||
consumerSession.rollback();
|
||||
|
||||
msg = consumer.receive(1_000);
|
||||
assertNotNull(msg);
|
||||
assertEquals("2", msg.getStringProperty("JMSXDeliveryCount"));
|
||||
assertEquals("KEY", msg.getStringProperty("something"));
|
||||
assertEquals("how are you", ((TextMessage) msg).getText());
|
||||
|
||||
consumerSession.rollback();
|
||||
|
||||
msg = consumer.receive(1_000);
|
||||
assertNotNull(msg);
|
||||
assertEquals("3", msg.getStringProperty("JMSXDeliveryCount"));
|
||||
assertEquals("KEY", msg.getStringProperty("something"));
|
||||
assertEquals("how are you", ((TextMessage) msg).getText());
|
||||
|
||||
consumerSession.rollback();
|
||||
|
||||
msg = consumer.receive(1_000);
|
||||
assertNotNull(msg);
|
||||
assertEquals("4", msg.getStringProperty("JMSXDeliveryCount"));
|
||||
assertEquals("KEY", msg.getStringProperty("something"));
|
||||
assertEquals("how are you", ((TextMessage) msg).getText());
|
||||
|
||||
consumerSession.rollback();
|
||||
|
||||
msg = consumer.receive(1_000);
|
||||
assertNotNull(msg);
|
||||
assertEquals("5", msg.getStringProperty("JMSXDeliveryCount"));
|
||||
assertEquals("KEY", msg.getStringProperty("something"));
|
||||
assertEquals("how are you", ((TextMessage) msg).getText());
|
||||
|
||||
consumerSession.commit();
|
||||
|
||||
consumer.close();
|
||||
} finally {
|
||||
producerConnection.close();
|
||||
consumerConnection.close();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue