/* * Copyright 2010-2011 Ning, Inc. * * Ning 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.killbill.notificationq.dao; import com.google.common.collect.Collections2; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; import org.killbill.CreatorName; import org.killbill.TestSetup; import org.killbill.queue.api.PersistentQueueEntryLifecycleState; import org.killbill.queue.dao.QueueSqlDao; import org.skife.jdbi.v2.Transaction; import org.skife.jdbi.v2.TransactionStatus; import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import javax.annotation.Nullable; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.UUID; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; public class TestNotificationSqlDao extends TestSetup { private static final String hostname = "Yop"; private static final long SEARCH_KEY_2 = 37; private NotificationSqlDao dao; @BeforeClass(groups = "slow") public void beforeClass() throws Exception { super.beforeClass(); dao = getDBI().onDemand(NotificationSqlDao.class); } @Test(groups = "slow") public void testBasic() throws InterruptedException { final long searchKey1 = 1242L; final String ownerId = UUID.randomUUID().toString(); final String eventJson = UUID.randomUUID().toString(); final DateTime effDt = new DateTime(); final NotificationEventModelDao notif = new NotificationEventModelDao(hostname, clock.getUTCNow(), eventJson.getClass().getName(), eventJson, UUID.randomUUID(), searchKey1, SEARCH_KEY_2, UUID.randomUUID(), effDt, "testBasic"); dao.insertEntry(notif, notificationQueueConfig.getTableName()); Thread.sleep(1000); final DateTime now = new DateTime(); final List<NotificationEventModelDao> notifications = dao.getReadyEntries(now.toDate(), 3, hostname, notificationQueueConfig.getTableName()); assertNotNull(notifications); assertEquals(notifications.size(), 1); final long nbEntries = dao.getNbReadyEntries(now.toDate(), hostname, notificationQueueConfig.getTableName()); assertEquals(nbEntries, 1); NotificationEventModelDao notification = notifications.get(0); assertEquals(notification.getEventJson(), eventJson); validateDate(notification.getEffectiveDate(), effDt); assertEquals(notification.getProcessingOwner(), null); assertEquals(notification.getProcessingState(), PersistentQueueEntryLifecycleState.AVAILABLE); assertEquals(notification.getNextAvailableDate(), null); final DateTime nextAvailable = now.plusMinutes(5); final int res = dao.claimEntry(notification.getRecordId(), now.toDate(), ownerId, nextAvailable.toDate(), notificationQueueConfig.getTableName()); assertEquals(res, 1); dao.claimEntry(notification.getRecordId(), now.toDate(), ownerId, nextAvailable.toDate(), notificationQueueConfig.getTableName()); notification = dao.getByRecordId(notification.getRecordId(), notificationQueueConfig.getTableName()); assertEquals(notification.getEventJson(), eventJson); validateDate(notification.getEffectiveDate(), effDt); assertEquals(notification.getProcessingOwner(), ownerId); assertEquals(notification.getProcessingState(), PersistentQueueEntryLifecycleState.IN_PROCESSING); validateDate(notification.getNextAvailableDate(), nextAvailable); final DateTime processedTime = clock.getUTCNow(); NotificationEventModelDao notificationHistory = new NotificationEventModelDao(notification, CreatorName.get(), processedTime, PersistentQueueEntryLifecycleState.PROCESSED); dao.insertEntry(notificationHistory, notificationQueueConfig.getHistoryTableName()); notificationHistory = dao.getByRecordId(notification.getRecordId(), notificationQueueConfig.getHistoryTableName()); assertEquals(notificationHistory.getEventJson(), eventJson); validateDate(notificationHistory.getEffectiveDate(), effDt); assertEquals(notificationHistory.getProcessingOwner(), CreatorName.get()); assertEquals(notificationHistory.getProcessingState(), PersistentQueueEntryLifecycleState.PROCESSED); validateDate(notificationHistory.getNextAvailableDate(), processedTime); dao.removeEntry(notification.getRecordId(), notificationQueueConfig.getTableName()); notification = dao.getByRecordId(notification.getRecordId(), notificationQueueConfig.getTableName()); assertNull(notification); } @Test(groups = "slow") public void testBatchOperations() throws InterruptedException { final long searchKey1 = 1242L; final String ownerId = UUID.randomUUID().toString(); final String eventJson = UUID.randomUUID().toString(); final DateTime effDt = new DateTime(); NotificationEventModelDao notif1 = new NotificationEventModelDao(hostname, clock.getUTCNow(), eventJson.getClass().getName(), eventJson, UUID.randomUUID(), searchKey1, SEARCH_KEY_2, UUID.randomUUID(), effDt, "testBasic1"); final List<NotificationEventModelDao> entries = new ArrayList<NotificationEventModelDao>(); notif1 = insertEntry(notif1, notificationQueueConfig.getTableName()); entries.add(notif1); NotificationEventModelDao notif2 = new NotificationEventModelDao(hostname, clock.getUTCNow(), eventJson.getClass().getName(), eventJson, UUID.randomUUID(), searchKey1, SEARCH_KEY_2, UUID.randomUUID(), effDt, "testBasic2"); notif2 = insertEntry(notif2, notificationQueueConfig.getTableName()); entries.add(notif2); NotificationEventModelDao notif3 = new NotificationEventModelDao(hostname, clock.getUTCNow(), eventJson.getClass().getName(), eventJson, UUID.randomUUID(), searchKey1, SEARCH_KEY_2, UUID.randomUUID(), effDt, "testBasic3"); notif3 = insertEntry(notif3, notificationQueueConfig.getTableName()); entries.add(notif3); final Collection<Long> entryIds = Collections2.transform(entries, new com.google.common.base.Function<NotificationEventModelDao, Long>() { @Nullable @Override public Long apply(@Nullable final NotificationEventModelDao input) { return input.getRecordId(); } }); dao.removeEntries(entryIds, notificationQueueConfig.getTableName()); for (final Long entry : entryIds) { final NotificationEventModelDao result = dao.getByRecordId(entry, notificationQueueConfig.getTableName()); assertNull(result); } dao.insertEntries(entries, notificationQueueConfig.getHistoryTableName()); for (final Long entry : entryIds) { final NotificationEventModelDao result = dao.getByRecordId(entry, notificationQueueConfig.getHistoryTableName()); assertNotNull(result); } } private NotificationEventModelDao insertEntry(final NotificationEventModelDao input, final String tableName) { return dao.inTransaction(new Transaction<NotificationEventModelDao, QueueSqlDao<NotificationEventModelDao>>() { @Override public NotificationEventModelDao inTransaction(final QueueSqlDao<NotificationEventModelDao> transactional, final TransactionStatus status) throws Exception { transactional.insertEntry(input, tableName); return transactional.getByRecordId(transactional.getLastInsertId(), notificationQueueConfig.getTableName()); } }); } private void validateDate(DateTime input, DateTime expected) { if (input == null && expected != null) { Assert.fail("Got input date null"); } if (input != null && expected == null) { Assert.fail("Was expecting null date"); } expected = truncateAndUTC(expected); input = truncateAndUTC(input); Assert.assertEquals(input, expected); } private DateTime truncateAndUTC(final DateTime input) { if (input == null) { return null; } final DateTime result = input.minus(input.getMillisOfSecond()); return result.toDateTime(DateTimeZone.UTC); } }