@EntityProperty(mutable = true, indexed = true) public State getState() { if (getErrorMessage() != null) { return State.FAILED; } else if (getCanceled() == Boolean.TRUE) { return State.CANCELED; } else if (getFinished() != null) { return State.FINISHED; } else if (getStarted() != null && getDeliver() == null) { return State.STARTED; } else if (isExpired()) { return State.EXPIRED; } else if (getDeliver() != null || getQueued() != null) { return State.SCHEDULED; } return State.CREATED; }
@Override public void sendNotification(String providerId, Object payload, Notification notification, TaskTracker tracker) throws Exception { Map<String,Object> map = (Map<String, Object>) payload; if(!map.containsKey(ttlKey) && notification.getExpire() != null){ // ttl provided to GCM is in seconds. calculate the difference from now long ttlSeconds = notification.getExpireTTLSeconds(); // max ttl for gcm is 4 weeks - https://developers.google.com/cloud-messaging/http-server-ref ttlSeconds = ttlSeconds <= 2419200 ? ttlSeconds : 2419200; map.put(ttlKey, (int)ttlSeconds);//needs to be int } if(!map.containsKey(priorityKey) && notification.getPriority() != null){ map.put(priorityKey, notification.getPriority()); } Batch batch = getBatch( map ); batch.add(providerId, tracker); }
@JsonIgnore public long getExpireTTLSeconds() { long ttlSeconds = (getExpireTimeMillis() - System.currentTimeMillis()) / 1000; return ttlSeconds > 0 ? ttlSeconds : 0; }
private boolean isOkToSend(Notification notification) { if (notification.getCanceled() == Boolean.TRUE) { if (logger.isDebugEnabled()) { logger.debug("Notification {} canceled. Not sending.", notification.getUuid()); } return false; } if (notification.isExpired()) { if (logger.isDebugEnabled()) { logger.debug("Notification {} expired. Not sending.", notification.getUuid()); } return false; } return true; }
if (notification.getCanceled() == Boolean.TRUE) { if (logger.isDebugEnabled()) { logger.debug("notification " + notification.getUuid() + " canceled"); final PathQuery<Device> pathQuery = notification.getPathQuery().buildPathQuery(); //devices query final AtomicInteger deviceCount = new AtomicInteger(); //count devices so you can make a judgement on batching final ConcurrentLinkedQueue<String> errorMessages = new ConcurrentLinkedQueue<>(); //build up list of issues final HashMap<Object, ProviderAdapter> notifierMap = getAdapterMap(); if (logger.isTraceEnabled()) { logger.trace("notification {} start query", notification.getUuid()); logger.trace("Notification {} started processing", notification.getUuid()); if( notification.getUseGraph()){ iterator = pathQuery.graphIterator(em); }else{ final Map<String, Object> payloads = notification.getPayloads(); logger.trace("Provider query for notification {} device {} took {} ms", notification.getUuid(), deviceRef.getUuid(), (System.currentTimeMillis() - now)); ApplicationQueueMessage message = new ApplicationQueueMessage(appId, notification.getUuid(), deviceRef.getUuid(), notifierKey, notifierId); if (notification.getQueued() == null) { notification.setQueued(System.currentTimeMillis()); final Map<String, Object> filters = notification.getFilters();
protected Notification notificationWaitForComplete(Notification notification) throws Exception { int retry = 18; // 3 mins 18 * 10 seconds while (-- retry > 0) { logger.info("notificationWaitForComplete {} retry {}", notification.getUuid(), retry); app.waitForQueueDrainAndRefreshIndex(10000); notification = app.getEntityManager().get(notification.getUuid(), Notification.class); if (notification.getFinished() != null) { return notification; } } fail("Notification failed to complete error message " + notification.getErrorMessage()); return null; }
if (notification.getStarted() == null || notification.getStarted() == 0) { long now = System.currentTimeMillis(); notification.setStarted(System.currentTimeMillis()); Map<String, Object> properties = new HashMap<String, Object>(2); properties.put("started", notification.getStarted()); properties.put("state", notification.getState()); notification.addProperties(properties); if (logger.isTraceEnabled()) { logger.trace("ApplicationQueueMessage: notification {} properties updated in duration {} ms", notification.getUuid(), System.currentTimeMillis() - now); notificationQueueManager.queueNotification(notification, null); if (logger.isTraceEnabled()) { logger.trace("NotificationService: notification {} post queue duration {} ms ", notification.getUuid(), System.currentTimeMillis() - now);
} else if (notification.getFinished() != null) { throw new ForbiddenServiceOperationException(request, "Notification immutable once sent."); } else if (notification.getStarted() != null) { if (payload.getProperty("canceled") != Boolean.TRUE) { throw new ForbiddenServiceOperationException(request, if (!deliver.equals(notification.getDeliver())) { notificationQueueManager.queueNotification((Notification) response, null);
@Test public void twoBatchNotification() throws Exception { app.clear(); String payload = "Hello, World!"; Map<String, String> payloads = new HashMap<String, String>(1); payloads.put(notifier.getUuid().toString(), payload); app.put("payloads", payloads); app.put("queued", System.currentTimeMillis()); app.put("debug", true); Entity e = app.testRequest(ServiceAction.POST, 1, "devices", "notifications").getEntity(); app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid()); Notification notification = app.getEntityManager().get(e.getUuid(), Notification.class); assertEquals( notification.getPayloads().get(notifier.getUuid().toString()), payload); // reduce Batch size to 1 Field field = GCMAdapter.class.getDeclaredField("BATCH_SIZE"); field.setAccessible(true); int multicastSize = field.getInt(GCMAdapter.class); try { field.setInt(GCMAdapter.class, 1); // perform push // notification = notificationWaitForComplete(notification); checkReceipts(notification, 2); } finally { field.setInt(GCMAdapter.class, multicastSize); } }
public boolean scheduleQueueJob(Notification notification, boolean forceSchedule) throws Exception { boolean scheduleInFuture = notification.getDeliver() != null; long scheduleAt = (notification.getDeliver() != null) ? notification.getDeliver() : 0; long soonestPossible = System.currentTimeMillis() + SCHEDULER_GRACE_PERIOD; if (scheduleAt < soonestPossible) { scheduleAt = soonestPossible; scheduleInFuture = false; } boolean scheduled = scheduleInFuture || forceSchedule; if(scheduled) { JobData jobData = new JobData(); jobData.setProperty("applicationId", sm.getApplicationId()); jobData.setProperty("notificationId", notification.getUuid()); jobData.setProperty("deliver", notification.getDeliver()); SchedulerService scheduler = getSchedulerService(); scheduler.createJob("queueJob", scheduleAt, jobData); if (logger.isTraceEnabled()) { logger.trace("notification {} scheduled for queuing", notification.getUuid()); } } return scheduled; } private SchedulerService getSchedulerService() {
@Test public void scheduledNotification() throws Exception { // create push notification // app.clear(); String payload = getPayload(); Map<String, String> payloads = new HashMap<String, String>(1); payloads.put(notifier.getUuid().toString(), payload); app.put("payloads", payloads); app.put("deliver", System.currentTimeMillis() + 240000); app.put("debug",true); Entity e = app.testRequest(ServiceAction.POST, 1,"devices",device1.getUuid(), "notifications") .getEntity(); app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid()); Notification notification = app.getEntityManager().get(e.getUuid(), Notification.class); assertEquals( notification.getPayloads().get(notifier.getUuid().toString()), payload); // delay until the scheduler has time to run Thread.sleep(500); notification = app.getEntityManager().get(e.getUuid(), Notification.class); assertEquals(Notification.State.SCHEDULED, notification.getState()); }
@Test public void singlePushNotificationHighPriority() throws Exception { app.clear(); String payload = "Hello, World!"; Map<String, String> payloads = new HashMap<String, String>(1); payloads.put(notifier.getUuid().toString(), payload); app.put("payloads", payloads); app.put("queued", System.currentTimeMillis()); app.put("debug", true); app.put("expire", System.currentTimeMillis() + 300000); // add 5 minutes to current time app.put("priority", "high"); Entity e = app.testRequest(ServiceAction.POST, 1, "devices", device1.getUuid(), "notifications").getEntity(); app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid()); Notification notification = app.getEntityManager().get(e.getUuid(), Notification.class); assertEquals( notification.getPayloads().get(notifier.getUuid().toString()), payload); // perform push // notification = notificationWaitForComplete(notification); assertEquals("high", notification.getPriority()); checkReceipts(notification, 1); }
final Map<String, Object> payloads = notification.getPayloads(); final Map<String, Object> translatedPayloads = translatePayloads(payloads, notifierMap); if (logger.isTraceEnabled()) { logger.trace("sending notification for device {} for Notification: {}", deviceUUID, notification.getUuid()); if(notification.getSaveReceipts()){ new Receipt( notification.getUuid(), message.getNotifierId(), payload, deviceUUID ); tracker = new TaskTracker( providerAdapter.getNotifier(), taskManager, receipt, deviceUUID ); if (payload == null) { if (logger.isDebugEnabled()) { logger.debug("selected device {} for notification {} doesn't have a valid payload. skipping.", deviceUUID, notification.getUuid()); } finally { if (logger.isTraceEnabled()) { logger.trace("sending to device {} for Notification: {} duration {} ms", deviceUUID, notification.getUuid(), (System.currentTimeMillis() - now));
notification.getPayloads().get(notifier.getUuid().toString()), payload ); notification = (Notification)results.getEntitiesMap().get(notification.getUuid()).toTypedEntity(); assertEquals(0, notification.getDeviceProcessedCount()); results = app.getEntityManager().searchCollection(app.getEntityManager().getApplicationRef(), "notifications", query); Entity entity = results.getEntitiesMap().get(notification.getUuid()); assertNotNull(entity);
@Test public void singlePushNotificationMultipleDevices() throws Exception { app.clear(); String payload = "Hello, World!"; Map<String, String> payloads = new HashMap<String, String>(1); payloads.put(notifier.getUuid().toString(), payload); app.put("payloads", payloads); app.put("queued", System.currentTimeMillis()); app.put("debug", true); app.put("expire", System.currentTimeMillis() + 300000); // add 5 minutes to current time Entity e = app.testRequest(ServiceAction.POST, 1, "devices", "*", "notifications").getEntity(); app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid()); Notification notification = app.getEntityManager().get(e.getUuid(), Notification.class); assertEquals( notification.getPayloads().get(notifier.getUuid().toString()), payload); // perform push // notification = notificationWaitForComplete(notification); checkReceipts(notification, 2); }
public void scheduleBatchJob(Notification notification, long delay) throws Exception { JobData jobData = new JobData(); jobData.setProperty("applicationId", sm.getApplicationId()); jobData.setProperty("notificationId", notification.getUuid()); jobData.setProperty("deliver", notification.getDeliver()); long soonestPossible = System.currentTimeMillis() + SCHEDULER_GRACE_PERIOD + delay; SchedulerService scheduler = getSchedulerService(); scheduler.createJob("notificationBatchJob", soonestPossible, jobData); if (logger.isTraceEnabled()) { logger.trace("notification {} batch scheduled for delivery", notification.getUuid()); } } public boolean scheduleQueueJob(Notification notification) throws Exception {
@Test public void scheduledNotificationAndEnsureSend() throws Exception { // create push notification // app.clear(); String payload = getPayload(); Map<String, String> payloads = new HashMap<String, String>(1); payloads.put(notifier.getUuid().toString(), payload); app.put("payloads", payloads); app.put("deliver", System.currentTimeMillis() + 2000); app.put("debug",true); Entity e = app.testRequest(ServiceAction.POST, 1,"devices",device1.getUuid(), "notifications") .getEntity(); app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid()); Notification notification = app.getEntityManager().get(e.getUuid(), Notification.class); assertEquals( notification.getPayloads().get(notifier.getUuid().toString()), payload); // delay until the scheduler has time to run Notification.State notificationState = Notification.State.SCHEDULED; int retry = 60; do { logger.info("Sleeping while the scheduler does its work " + retry); Thread.sleep(1000); notificationState = app.getEntityManager().get(e.getUuid(), Notification.class).getState(); } while (Notification.State.FINISHED != notificationState && --retry >= 0 ); assertEquals(Notification.State.FINISHED, notificationState); }
@Test public void singlePushNotificationWithInvalidPriority() throws Exception { app.clear(); String payload = "Hello, World!"; Map<String, String> payloads = new HashMap<String, String>(1); payloads.put(notifier.getUuid().toString(), payload); app.put("payloads", payloads); app.put("queued", System.currentTimeMillis()); app.put("debug", true); app.put("expire", System.currentTimeMillis() + 300000); // add 5 minutes to current time app.put("priority", "not_a_priority"); Entity e = app.testRequest(ServiceAction.POST, 1, "devices", device1.getUuid(), "notifications").getEntity(); app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid()); Notification notification = app.getEntityManager().get(e.getUuid(), Notification.class); assertEquals( notification.getPayloads().get(notifier.getUuid().toString()), payload); // perform push // notification = notificationWaitForComplete(notification); // if priority is invalid, it should default to normal assertEquals("normal", notification.getPriority()); checkReceipts(notification, 1); }
@Test public void singlePushNotificationWithMapPayload() throws Exception { app.clear(); String payload = "{\"message\":\"Hello, World!\", \"campaign\":\"Hello Campaign\"}"; Map<String, String> payloads = new HashMap<String, String>(1); payloads.put(notifier.getUuid().toString(), payload); app.put("payloads", payloads); app.put("queued", System.currentTimeMillis()); app.put("debug", true); app.put("expire", System.currentTimeMillis() + 300000); // add 5 minutes to current time Entity e = app.testRequest(ServiceAction.POST, 1, "devices", device1.getUuid(), "notifications").getEntity(); app.testRequest(ServiceAction.GET, 1, "notifications", e.getUuid()); Notification notification = app.getEntityManager().get(e.getUuid(), Notification.class); assertEquals( notification.getPayloads().get(notifier.getUuid().toString()), payload); // perform push // notification = notificationWaitForComplete(notification); checkReceipts(notification, 1); }