@Override public <T extends OverdueCheckNotificationKey> void clearOverdueCheckNotifications(final UUID accountId, final String overdueQueueName, final Class<T> clazz, final InternalCallContext context) { try { final NotificationQueue checkOverdueQueue = notificationQueueService.getNotificationQueue(DefaultOverdueService.OVERDUE_SERVICE_NAME, overdueQueueName); transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<Void>() { @Override public Void inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory) throws Exception { final Collection<NotificationEventWithMetadata<T>> futureNotifications = getFutureNotificationsForAccountInTransaction(entitySqlDaoWrapperFactory, checkOverdueQueue, accountId, clazz, context); for (final NotificationEventWithMetadata<T> notification : futureNotifications) { checkOverdueQueue.removeNotificationFromTransaction(entitySqlDaoWrapperFactory.getSqlDao(), notification.getRecordId()); } return null; } }); } catch (NoSuchNotificationQueue e) { log.error("Attempting to clear items from a non-existent queue (DefaultOverdueCheck).", e); } }
@Override public void initialize() throws NotificationQueueAlreadyExists { final NotificationQueueHandler notificationQueueHandler = new NotificationQueueHandler() { @Override public void handleReadyNotification(final NotificationEvent notificationKey, final DateTime eventDate, final UUID userToken, final Long accountRecordId, final Long tenantRecordId) { try { if (!(notificationKey instanceof NextBillingDateNotificationKey)) { log.error("Invoice service received an unexpected event type {}", notificationKey.getClass().getName()); return; } final NextBillingDateNotificationKey key = (NextBillingDateNotificationKey) notificationKey; try { final SubscriptionBase subscription = subscriptionApi.getSubscriptionFromId(key.getUuidKey(), callContextFactory.createInternalTenantContext(tenantRecordId, accountRecordId)); if (subscription == null) { log.warn("Next Billing Date Notification Queue handled spurious notification (key: " + key + ")"); } else { processEvent(key.getUuidKey(), eventDate, userToken, accountRecordId, tenantRecordId); } } catch (SubscriptionBaseApiException e) { log.warn("Next Billing Date Notification Queue handled spurious notification (key: " + key + ")", e); } } catch (IllegalArgumentException e) { log.error("The key returned from the NextBillingNotificationQueue is not a valid UUID", e); } } }; nextBillingQueue = notificationQueueService.createNotificationQueue(DefaultInvoiceService.INVOICE_SERVICE_NAME, NEXT_BILLING_DATE_NOTIFIER_QUEUE, notificationQueueHandler); }
@Override public void stop() { if (overdueQueue != null) { overdueQueue.stopQueue(); try { notificationQueueService.deleteNotificationQueue(overdueQueue.getServiceName(), overdueQueue.getQueueName()); } catch (NoSuchNotificationQueue e) { log.error("Error deleting a queue by its own name - this should never happen", e); } } }
@Override public void startQueue() { notificationQueueService.startQueue(); isStarted = true; }
private void waitForNotificationToComplete(final HttpServletRequest request, final Long timeoutSec) { final TenantContext tenantContext = context.createContext(request); final Long tenantRecordId = recordIdApi.getRecordId(tenantContext.getTenantId(), ObjectType.TENANT, tenantContext); final List<NotificationQueue> queues = notificationQueueService.getNotificationQueues(); int nbTryLeft = timeoutSec != null ? timeoutSec.intValue() : 0; try { boolean areAllNotificationsProcessed = false; while (!areAllNotificationsProcessed && nbTryLeft > 0) { areAllNotificationsProcessed = areAllNotificationsProcessed(queues, tenantRecordId); if (!areAllNotificationsProcessed) { Thread.sleep(MILLIS_IN_SEC); nbTryLeft--; } } ; } catch (InterruptedException ignore) { } }
@Override public <T extends OverdueCheckNotificationKey> void insertOverdueNotification(final UUID accountId, final DateTime futureNotificationTime, final String overdueQueueName, final T notificationKey, final InternalCallContext context) { try { final NotificationQueue overdueQueue = notificationQueueService.getNotificationQueue(DefaultOverdueService.OVERDUE_SERVICE_NAME, overdueQueueName); transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<Void>() { @Override public Void inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory) throws Exception { // Check if we already have notifications for that key final Class<T> clazz = (Class<T>) notificationKey.getClass(); final Collection<NotificationEventWithMetadata<T>> futureNotifications = getFutureNotificationsForAccountInTransaction(entitySqlDaoWrapperFactory, overdueQueue, accountId, clazz, context); boolean shouldInsertNewNotification = cleanupFutureNotificationsFormTransaction(entitySqlDaoWrapperFactory, futureNotifications, futureNotificationTime, overdueQueue); if (shouldInsertNewNotification) { log.debug("Queuing overdue check notification. Account id: {}, timestamp: {}", accountId.toString(), futureNotificationTime.toString()); overdueQueue.recordFutureNotificationFromTransaction(entitySqlDaoWrapperFactory.getSqlDao(), futureNotificationTime, notificationKey, context.getUserToken(), context.getAccountRecordId(), context.getTenantRecordId()); } else { log.debug("Skipping queuing overdue check notification. Account id: {}, timestamp: {}", accountId.toString(), futureNotificationTime.toString()); } return null; } }); } catch (NoSuchNotificationQueue e) { log.error("Attempting to put items on a non-existent queue (DefaultOverdueCheck).", e); return; } }
@Override public void initialize(final String svcName) throws NotificationQueueAlreadyExists { retryQueue = notificationQueueService.createNotificationQueue(svcName, getQueueName(), new NotificationQueueHandler() { @Override public void handleReadyNotification(final NotificationEvent notificationKey, final DateTime eventDateTime, final UUID userToken, final Long accountRecordId, final Long tenantRecordId) { if (!(notificationKey instanceof PaymentRetryNotificationKey)) { log.error("Payment service got an unexpected notification type {}", notificationKey.getClass().getName()); return; } final PaymentRetryNotificationKey key = (PaymentRetryNotificationKey) notificationKey; final InternalCallContext callContext = internalCallContextFactory.createInternalCallContext(tenantRecordId, accountRecordId, PAYMENT_RETRY_SERVICE, CallOrigin.INTERNAL, UserType.SYSTEM, userToken); retry(key.getUuidKey(), callContext); } }); }
@Override public void stop() throws NoSuchNotificationQueue { if (nextBillingQueue != null) { nextBillingQueue.stopQueue(); notificationQueueService.deleteNotificationQueue(nextBillingQueue.getServiceName(), nextBillingQueue.getQueueName()); } }
private void recordFutureNotification(final DateTime effectiveDate, final NotificationEvent notificationEvent, final InternalCallContext context) { try { final NotificationQueue subscriptionEventQueue = notificationQueueService.getNotificationQueue(DefaultEntitlementService.ENTITLEMENT_SERVICE_NAME, DefaultEntitlementService.NOTIFICATION_QUEUE_NAME); subscriptionEventQueue.recordFutureNotification(effectiveDate, notificationEvent, context.getUserToken(), context.getAccountRecordId(), context.getTenantRecordId()); } catch (NoSuchNotificationQueue e) { throw new RuntimeException(e); } catch (IOException e) { throw new RuntimeException(e); } } }
@Override public void initialize() { final OverdueNotifier myself = this; final NotificationQueueHandler notificationQueueHandler = new NotificationQueueHandler() { @Override public void handleReadyNotification(final NotificationEvent notificationKey, final DateTime eventDate, final UUID userToken, final Long accountRecordId, final Long tenantRecordId) { myself.handleReadyNotification(notificationKey, eventDate, userToken, accountRecordId, tenantRecordId); } }; try { overdueQueue = notificationQueueService.createNotificationQueue(DefaultOverdueService.OVERDUE_SERVICE_NAME, getQueueName(), notificationQueueHandler); } catch (NotificationQueueAlreadyExists e) { throw new RuntimeException(e); } }
@Override public void stop() throws NoSuchNotificationQueue { if (retryQueue != null) { retryQueue.stopQueue(); notificationQueueService.deleteNotificationQueue(retryQueue.getServiceName(), retryQueue.getQueueName()); } }
private void recordFutureNotification(final DateTime effectiveDate, final NotificationEvent notificationEvent, final InternalCallContext context) { try { final NotificationQueue subscriptionEventQueue = notificationQueueService.getNotificationQueue(DefaultEntitlementService.ENTITLEMENT_SERVICE_NAME, DefaultEntitlementService.NOTIFICATION_QUEUE_NAME); subscriptionEventQueue.recordFutureNotification(effectiveDate, notificationEvent, context.getUserToken(), context.getAccountRecordId(), context.getTenantRecordId()); } catch (NoSuchNotificationQueue e) { throw new RuntimeException(e); } catch (IOException e) { throw new RuntimeException(e); } } }
@LifecycleHandlerType(LifecycleLevel.INIT_SERVICE) public void initialize() { try { final NotificationQueueHandler queueHandler = new NotificationQueueHandler() { @Override public void handleReadyNotification(final NotificationEvent inputKey, final DateTime eventDateTime, final UUID fromNotificationQueueUserToken, final Long accountRecordId, final Long tenantRecordId) { final InternalCallContext internalCallContext = internalCallContextFactory.createInternalCallContext(tenantRecordId, accountRecordId, "EntitlementQueue", CallOrigin.INTERNAL, UserType.SYSTEM, fromNotificationQueueUserToken); if (inputKey instanceof EntitlementNotificationKey) { final UUID tenantId = nonEntityDao.retrieveIdFromObject(tenantRecordId, ObjectType.TENANT); processEntitlementNotification((EntitlementNotificationKey) inputKey, tenantId, internalCallContext); } else if (inputKey instanceof BlockingTransitionNotificationKey) { processBlockingNotification((BlockingTransitionNotificationKey) inputKey, internalCallContext); } else if (inputKey != null) { log.error("Entitlement service received an unexpected event type {}" + inputKey.getClass()); } else { log.error("Entitlement service received an unexpected null event"); } } }; entitlementEventQueue = notificationQueueService.createNotificationQueue(ENTITLEMENT_SERVICE_NAME, NOTIFICATION_QUEUE_NAME, queueHandler); } catch (final NotificationQueueAlreadyExists e) { throw new RuntimeException(e); } }
@LifecycleHandlerType(LifecycleLevel.STOP_SERVICE) public void stop() throws NoSuchNotificationQueue { if (entitlementEventQueue != null) { entitlementEventQueue.stopQueue(); notificationQueueService.deleteNotificationQueue(entitlementEventQueue.getServiceName(), entitlementEventQueue.getQueueName()); } } }
@Override public void insertNextBillingNotification(final UUID accountId, final UUID subscriptionId, final DateTime futureNotificationTime, final UUID userToken) { final InternalCallContext context = createCallContext(accountId, userToken); final NotificationQueue nextBillingQueue; try { nextBillingQueue = notificationQueueService.getNotificationQueue(DefaultInvoiceService.INVOICE_SERVICE_NAME, DefaultNextBillingDateNotifier.NEXT_BILLING_DATE_NOTIFIER_QUEUE); log.info("Queuing next billing date notification at {} for subscriptionId {}", futureNotificationTime.toString(), subscriptionId.toString()); nextBillingQueue.recordFutureNotification(futureNotificationTime, new NextBillingDateNotificationKey(subscriptionId), context.getUserToken(), context.getAccountRecordId(), context.getTenantRecordId()); } catch (NoSuchNotificationQueue e) { log.error("Attempting to put items on a non-existent queue (NextBillingDateNotifier).", e); } catch (IOException e) { log.error("Failed to serialize notificationKey for subscriptionId {}", subscriptionId); } }
final Map<NotificationEvent, Boolean> expectedNotifications = new TreeMap<NotificationEvent, Boolean>(); final NotificationQueue queue = queueService.createNotificationQueue("test-svc", "many", new NotificationQueueHandler() {
@Override public void insertNextBillingNotificationFromTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory, final UUID accountId, final UUID subscriptionId, final DateTime futureNotificationTime, final UUID userToken) { final InternalCallContext context = createCallContext(accountId, userToken); final NotificationQueue nextBillingQueue; try { nextBillingQueue = notificationQueueService.getNotificationQueue(DefaultInvoiceService.INVOICE_SERVICE_NAME, DefaultNextBillingDateNotifier.NEXT_BILLING_DATE_NOTIFIER_QUEUE); log.info("Queuing next billing date notification at {} for subscriptionId {}", futureNotificationTime.toString(), subscriptionId.toString()); nextBillingQueue.recordFutureNotificationFromTransaction(entitySqlDaoWrapperFactory.getSqlDao(), futureNotificationTime, new NextBillingDateNotificationKey(subscriptionId), context.getUserToken(), context.getAccountRecordId(), context.getTenantRecordId()); } catch (NoSuchNotificationQueue e) { log.error("Attempting to put items on a non-existent queue (NextBillingDateNotifier).", e); } catch (IOException e) { log.error("Failed to serialize notificationKey for subscriptionId {}", subscriptionId); } }
final Map<NotificationEvent, Boolean> expectedNotificationsBarney = new TreeMap<NotificationEvent, Boolean>(); final NotificationQueue queueFred = queueService.createNotificationQueue("UtilTest", "Fred", new NotificationQueueHandler() { @Override public void handleReadyNotification(final NotificationEvent eventJson, final DateTime eventDateTime, final UUID userToken, final Long searchKey1, final Long searchKey2) { final NotificationQueue queueBarney = queueService.createNotificationQueue("UtilTest", "Barney", new NotificationQueueHandler() { @Override public void handleReadyNotification(final NotificationEvent eventJson, final DateTime eventDateTime, final UUID userToken, final Long searchKey1, final Long searchKey2) {
@Override @BeforeMethod(groups = "slow") public void beforeMethod() throws Exception { super.beforeMethod(); entitySqlDaoTransactionalJdbiWrapper = new EntitySqlDaoTransactionalJdbiWrapper(dbi, clock, cacheControllerDispatcher, nonEntityDao); overdueQueue = notificationQueueService.getNotificationQueue(DefaultOverdueService.OVERDUE_SERVICE_NAME, OverdueCheckNotifier.OVERDUE_CHECK_NOTIFIER_QUEUE); Assert.assertTrue(overdueQueue.isStarted()); testReferenceTime = clock.getUTCNow(); }
final NotificationQueue queue = queueService.createNotificationQueue("test-svc", "foo", new NotificationQueueHandler() {