/* * Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com * The software in this package is published under the terms of the CPAL v1.0 * license, a copy of which has been included with this distribution in the * LICENSE.txt file. */ package org.mule.runtime.core.util.queue; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNull.notNullValue; import static org.hamcrest.core.IsNull.nullValue; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mule.runtime.api.message.Message.of; import org.mule.runtime.core.api.Event; import org.mule.runtime.core.api.context.MuleContextBuilder; import org.mule.runtime.core.config.DefaultMuleConfiguration; import org.mule.runtime.core.util.journal.queue.LocalTxQueueTransactionJournal; import org.mule.runtime.core.util.journal.queue.LocalTxQueueTransactionRecoverer; import org.mule.runtime.core.util.xa.ResourceManagerException; import org.mule.tck.junit4.AbstractMuleContextTestCase; import java.io.Serializable; import org.apache.commons.lang.NotImplementedException; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; public class LocalTxQueueTransactionRecovererTestCase extends AbstractMuleContextTestCase { public static final String QUEUE_NAME = "inQueue"; private static final int TIMEOUT = 10; @Rule public TemporaryFolder temporaryFolder = new TemporaryFolder(); private LocalTxQueueTransactionJournal txLog; private DefaultQueueStore inQueue; private PersistentQueueTransactionContext persistentTransactionContext; private LocalTxQueueTransactionRecoverer queueTransactionRecoverer; @Override protected void doSetUp() throws Exception { ((DefaultMuleConfiguration) muleContext.getConfiguration()).setWorkingDirectory(temporaryFolder.getRoot().getAbsolutePath()); txLog = new LocalTxQueueTransactionJournal(temporaryFolder.getRoot().getAbsolutePath(), muleContext); inQueue = new DefaultQueueStore(QUEUE_NAME, muleContext, new DefaultQueueConfiguration(0, true)); persistentTransactionContext = new PersistentQueueTransactionContext(txLog, createQueueProvider(inQueue)); queueTransactionRecoverer = new LocalTxQueueTransactionRecoverer(txLog, createQueueProvider(inQueue)); } @Override protected void configureMuleContext(MuleContextBuilder contextBuilder) { DefaultMuleConfiguration muleConfiguration = new DefaultMuleConfiguration(); muleConfiguration.setWorkingDirectory(temporaryFolder.getRoot().getAbsolutePath()); contextBuilder.setMuleConfiguration(muleConfiguration); } @Test public void pollAndFailThenRecover() throws Exception { inQueue.offer(testEvent(), 0, TIMEOUT); Serializable value = persistentTransactionContext.poll(inQueue, 100000); assertThat(inQueue.poll(TIMEOUT), nullValue()); assertThat(value, notNullValue()); txLog.close(); txLog = new LocalTxQueueTransactionJournal(temporaryFolder.getRoot().getAbsolutePath(), muleContext); queueTransactionRecoverer.recover(); Event muleEvent = (Event) inQueue.poll(TIMEOUT); assertThat(muleEvent, notNullValue()); assertThat(testEvent().getContext().getId(), equalTo(muleEvent.getContext().getId())); } @Test public void pollAndFailThenRecoverWithTwoElements() throws Exception { final String MESSAGE_CONTENT_2 = TEST_PAYLOAD + "2"; Event testEvent2 = eventBuilder().message(of(MESSAGE_CONTENT_2)).build(); inQueue.offer(testEvent(), 0, TIMEOUT); inQueue.offer(testEvent2, 0, TIMEOUT); Serializable value = persistentTransactionContext.poll(inQueue, 100000); assertThat(inQueue.getSize(), is(1)); assertThat(value, notNullValue()); txLog.close(); txLog = new LocalTxQueueTransactionJournal(temporaryFolder.getRoot().getAbsolutePath(), muleContext); queueTransactionRecoverer.recover(); Event muleEvent = (Event) inQueue.poll(TIMEOUT); assertThat(muleEvent, notNullValue()); assertThat(muleEvent.getMessage().getPayload().getValue().toString(), is(MESSAGE_CONTENT_2)); // recovered element should be // last muleEvent = (Event) inQueue.poll(TIMEOUT); assertThat(muleEvent, notNullValue()); assertThat(muleEvent.getMessage().getPayload().getValue().toString(), is(TEST_PAYLOAD)); // recovered element } @Test public void failBetweenLogEntryWriteAndRealPoolThenRecover() throws Exception { inQueue.offer(testEvent(), 0, TIMEOUT); persistentTransactionContext.poll(inQueue, TIMEOUT); txLog.close(); txLog = new LocalTxQueueTransactionJournal(temporaryFolder.getRoot().getAbsolutePath(), muleContext); queueTransactionRecoverer.recover(); Event muleEvent = (Event) inQueue.poll(TIMEOUT); assertThat(muleEvent, notNullValue()); assertThat(testEvent().getContext().getId(), equalTo(muleEvent.getContext().getId())); muleEvent = (Event) inQueue.poll(TIMEOUT); assertThat(muleEvent, nullValue()); } private QueueProvider createQueueProvider(final DefaultQueueStore queue) { return new QueueProvider() { @Override public QueueStore getQueue(String queueName) { throw new NotImplementedException(); } @Override public RecoverableQueueStore getRecoveryQueue(String queueName) { return queue; } }; } @Test public void offerAndFailThenRecover() throws Exception { final DefaultQueueStore outQueue = new DefaultQueueStore(QUEUE_NAME, muleContext, new DefaultQueueConfiguration(0, true)); persistentTransactionContext = new PersistentQueueTransactionContext(txLog, createQueueProvider(outQueue)); persistentTransactionContext.offer(outQueue, testEvent(), TIMEOUT); assertThat(outQueue.poll(TIMEOUT), nullValue()); txLog.close(); txLog = new LocalTxQueueTransactionJournal(temporaryFolder.getRoot().getAbsolutePath(), muleContext); queueTransactionRecoverer = new LocalTxQueueTransactionRecoverer(txLog, createQueueProvider(outQueue)); queueTransactionRecoverer.recover(); Serializable muleEvent = outQueue.poll(TIMEOUT); assertThat(muleEvent, nullValue()); } @Test public void offerAndFailBetweenRealOfferAndCommitThenRecover() throws Exception { txLog = new TestTransactionLogger(temporaryFolder.getRoot().getAbsolutePath(), muleContext).failDuringLogCommit(); final DefaultQueueStore outQueue = new DefaultQueueStore(QUEUE_NAME, muleContext, new DefaultQueueConfiguration(0, true)); persistentTransactionContext = new PersistentQueueTransactionContext(txLog, createQueueProvider(outQueue)); persistentTransactionContext.offer(outQueue, testEvent(), TIMEOUT); try { persistentTransactionContext.doCommit(); fail(); } catch (ResourceManagerException e) { // expected } txLog.close(); txLog = new TestTransactionLogger(temporaryFolder.getRoot().getAbsolutePath(), muleContext); queueTransactionRecoverer = new LocalTxQueueTransactionRecoverer(txLog, createQueueProvider(outQueue)); queueTransactionRecoverer.recover(); Serializable muleEvent = outQueue.poll(TIMEOUT); assertThat(muleEvent, nullValue()); } }