@Test public void useTransactionTest() throws Exception { // Performing admin operations to create dataset instance // keyValueTable is a system dataset module Id.DatasetInstance myTableInstance = Id.DatasetInstance.from(namespace, "myTable"); dsFramework.addInstance("keyValueTable", myTableInstance, DatasetProperties.EMPTY); Assert.assertTrue(feedManager.createFeed(FEED1)); try { Cancellable cancellable = notificationService.subscribe( FEED1, new NotificationHandler<String>() { private int received = 0; @Override public Type getNotificationType() { return String.class; } @Override public void received( final String notification, NotificationContext notificationContext) { notificationContext.execute( new TxRunnable() { @Override public void run(DatasetContext context) throws Exception { KeyValueTable table = context.getDataset("myTable"); table.write("foo", String.format("%s-%d", notification, received++)); } }, TxRetryPolicy.maxRetries(5)); } }); TimeUnit.SECONDS.sleep(2); try { notificationService.publish(FEED1, "foobar"); // Waiting for the subscriber to receive that notification TimeUnit.SECONDS.sleep(2); KeyValueTable table = dsFramework.getDataset(myTableInstance, DatasetDefinition.NO_ARGUMENTS, null); Assert.assertNotNull(table); Transaction tx1 = txManager.startShort(100); table.startTx(tx1); Assert.assertEquals("foobar-0", Bytes.toString(table.read("foo"))); Assert.assertTrue(table.commitTx()); txManager.canCommit(tx1, table.getTxChanges()); txManager.commit(tx1); table.postTxCommit(); } finally { cancellable.cancel(); } } finally { dsFramework.deleteInstance(myTableInstance); feedManager.deleteFeed(FEED1); } }
public static void startServices(Injector injector) throws Exception { notificationService = injector.getInstance(NotificationService.class); notificationService.startAndWait(); feedManager = injector.getInstance(NotificationFeedManager.class); dsFramework = injector.getInstance(DatasetFramework.class); txManager = injector.getInstance(TransactionManager.class); txManager.startAndWait(); dsOpService = injector.getInstance(DatasetOpExecutor.class); dsOpService.startAndWait(); datasetService = injector.getInstance(DatasetService.class); datasetService.startAndWait(); }
@Test public void feedNotCreatedTest() throws Exception { try { // Try subscribing to a feed before creating it notificationService.subscribe( FEED1, new NotificationHandler<String>() { @Override public Type getNotificationType() { return String.class; } @Override public void received(String notification, NotificationContext notificationContext) { // No-op } }); Assert.fail("Should throw NotificationFeedNotFoundException."); } catch (NotificationFeedNotFoundException e) { // Expected } }
@Test public void twoFeedsPublishOneFeedSubscribeTest() throws Exception { // Test two publishers on two different feeds, but only one subscriber subscribing to one of the // feeds final int messagesCount = 15; Assert.assertTrue(feedManager.createFeed(FEED1)); Assert.assertTrue(feedManager.createFeed(FEED2)); try { // Create a subscribing process final AtomicInteger receiveCount = new AtomicInteger(0); final AtomicBoolean assertionOk = new AtomicBoolean(true); Cancellable cancellable = notificationService.subscribe( FEED1, new NotificationHandler<String>() { @Override public Type getNotificationType() { return String.class; } @Override public void received(String notification, NotificationContext notificationContext) { LOG.debug("Received notification payload: {}", notification); try { Assert.assertEquals("fake-payload-" + receiveCount.get(), notification); receiveCount.incrementAndGet(); } catch (Throwable t) { assertionOk.set(false); Throwables.propagate(t); } } }); // Give the subscriber some time to prepare for published messages before starting the // publisher TimeUnit.MILLISECONDS.sleep(500); Runnable publisherRunnable1 = new Runnable() { @Override public void run() { try { Random r = new Random(); for (int j = 0; j < messagesCount; j++) { notificationService.publish(FEED1, String.format("fake-payload-%d", j)); TimeUnit.MILLISECONDS.sleep(r.nextInt(200)); } } catch (Throwable e) { Throwables.propagate(e); } } }; Thread publisherThread1 = new Thread(publisherRunnable1); publisherThread1.start(); Runnable publisherRunnable2 = new Runnable() { @Override public void run() { try { Random r = new Random(); for (int j = 0; j < messagesCount; j++) { notificationService.publish(FEED2, String.format("fake-payload2-%d", j)); TimeUnit.MILLISECONDS.sleep(r.nextInt(200)); } } catch (Throwable e) { Throwables.propagate(e); } } }; Thread publisherThread2 = new Thread(publisherRunnable2); publisherThread2.start(); publisherThread1.join(); publisherThread2.join(); TimeUnit.MILLISECONDS.sleep(2000); cancellable.cancel(); Assert.assertTrue(assertionOk.get()); Assert.assertEquals(messagesCount, receiveCount.get()); } finally { feedManager.deleteFeed(FEED1); feedManager.deleteFeed(FEED2); } }
@Test public void multipleFeedsOneSubscriber() throws Exception { // One subscriber subscribes to two feeds final int messagesCount = 15; Assert.assertTrue(feedManager.createFeed(FEED1)); Assert.assertTrue(feedManager.createFeed(FEED2)); try { // Create a subscribing process final AtomicBoolean assertionOk = new AtomicBoolean(true); final int[] receiveCounts = new int[2]; List<Cancellable> cancellables = Lists.newArrayList(); cancellables.add( notificationService.subscribe( FEED1, new NotificationHandler<SimpleNotification>() { @Override public Type getNotificationType() { return SimpleNotification.class; } @Override public void received( SimpleNotification notification, NotificationContext notificationContext) { LOG.debug("Received notification payload: {}", notification); try { Assert.assertEquals( "fake-payload-" + receiveCounts[0], notification.getPayload()); receiveCounts[0]++; } catch (Throwable t) { assertionOk.set(false); Throwables.propagate(t); } } })); cancellables.add( notificationService.subscribe( FEED2, new NotificationHandler<String>() { @Override public Type getNotificationType() { return String.class; } @Override public void received(String notification, NotificationContext notificationContext) { LOG.debug("Received notification payload: {}", notification); try { Assert.assertEquals("fake-payload-" + receiveCounts[1], notification); receiveCounts[1]++; } catch (Throwable t) { assertionOk.set(false); Throwables.propagate(t); } } })); // Give the subscriber some time to prepare for published messages before starting the // publisher TimeUnit.MILLISECONDS.sleep(500); Runnable publisherRunnable1 = new Runnable() { @Override public void run() { try { Random r = new Random(); for (int j = 0; j < messagesCount; j++) { notificationService.publish( FEED1, new SimpleNotification(0, String.format("fake-payload-%d", j))); TimeUnit.MILLISECONDS.sleep(r.nextInt(200)); } } catch (Throwable e) { Throwables.propagate(e); } } }; Thread publisherThread1 = new Thread(publisherRunnable1); publisherThread1.start(); Runnable publisherRunnable2 = new Runnable() { @Override public void run() { try { Random r = new Random(); for (int j = 0; j < messagesCount; j++) { notificationService.publish(FEED2, String.format("fake-payload-%d", j)); TimeUnit.MILLISECONDS.sleep(r.nextInt(200)); } } catch (Throwable e) { Throwables.propagate(e); } } }; Thread publisherThread2 = new Thread(publisherRunnable2); publisherThread2.start(); publisherThread1.join(); publisherThread2.join(); TimeUnit.MILLISECONDS.sleep(2000); for (Cancellable cancellable : cancellables) { cancellable.cancel(); } Assert.assertTrue(assertionOk.get()); for (int i : receiveCounts) { Assert.assertEquals(messagesCount, i); } } finally { feedManager.deleteFeed(FEED1); feedManager.deleteFeed(FEED2); } }
@Test public void multiplePublishersOneSubscriberTest() throws Exception { /* This configuration should not happen, as, by design, we want only one publisher to publisher the changes attached to a resource. But since the low level APIs allow it, this should still be tested. */ final int messagesCount = 15; int publishersCount = 5; Assert.assertTrue(feedManager.createFeed(FEED1)); try { // Create a subscribing process final AtomicBoolean assertionOk = new AtomicBoolean(true); final int[] receiveCounts = new int[publishersCount]; Cancellable cancellable = notificationService.subscribe( FEED1, new NotificationHandler<SimpleNotification>() { @Override public Type getNotificationType() { return SimpleNotification.class; } @Override public void received( SimpleNotification notification, NotificationContext notificationContext) { LOG.debug("Received notification payload: {}", notification); try { Assert.assertEquals( "fake-payload-" + receiveCounts[notification.getPublisherId()], notification.getPayload()); receiveCounts[notification.getPublisherId()]++; } catch (Throwable t) { assertionOk.set(false); Throwables.propagate(t); } } }); // Give the subscriber some time to prepare for published messages before starting the // publisher TimeUnit.MILLISECONDS.sleep(500); List<Thread> publisherThreads = Lists.newArrayList(); for (int i = 0; i < publishersCount; i++) { final int k = i; Runnable publisherRunnable = new Runnable() { @Override public void run() { try { Random r = new Random(); for (int j = 0; j < messagesCount; j++) { notificationService.publish( FEED1, new SimpleNotification(k, String.format("fake-payload-%d", j))); TimeUnit.MILLISECONDS.sleep(r.nextInt(200)); } } catch (Throwable e) { Throwables.propagate(e); } } }; Thread publisherThread = new Thread(publisherRunnable); publisherThread.start(); publisherThreads.add(publisherThread); } for (Thread t : publisherThreads) { t.join(); } TimeUnit.MILLISECONDS.sleep(2000); cancellable.cancel(); Assert.assertTrue(assertionOk.get()); for (int i : receiveCounts) { Assert.assertEquals(messagesCount, i); } } finally { feedManager.deleteFeed(FEED1); } }
@Test public void onePublisherMultipleSubscribersTest() throws Exception { final int messagesCount = 20; int subscribersCount = 10; Assert.assertTrue(feedManager.createFeed(FEED1)); try { Runnable publisherRunnable = new Runnable() { @Override public void run() { try { for (int i = 0; i < messagesCount; i++) { notificationService.publish(FEED1, String.format("fake-payload-%d", i)); TimeUnit.MILLISECONDS.sleep(100); } } catch (Throwable e) { Throwables.propagate(e); } } }; Thread publisherThread = new Thread(publisherRunnable); final int[] receiveCounts = new int[subscribersCount]; final AtomicBoolean assertionOk = new AtomicBoolean(true); List<Cancellable> cancellables = Lists.newArrayList(); for (int i = 0; i < subscribersCount; i++) { final int j = i; Cancellable cancellable = notificationService.subscribe( FEED1, new NotificationHandler<String>() { @Override public Type getNotificationType() { return String.class; } @Override public void received( String notification, NotificationContext notificationContext) { LOG.debug("Received notification payload: {}", notification); try { Assert.assertEquals("fake-payload-" + receiveCounts[j], notification); receiveCounts[j]++; } catch (Throwable t) { assertionOk.set(false); Throwables.propagate(t); } } }); cancellables.add(cancellable); } // Give the subscriber some time to prepare for published messages before starting the // publisher TimeUnit.MILLISECONDS.sleep(500); publisherThread.start(); publisherThread.join(); TimeUnit.MILLISECONDS.sleep(2000); for (Cancellable cancellable : cancellables) { cancellable.cancel(); } Assert.assertTrue(assertionOk.get()); for (int i : receiveCounts) { Assert.assertEquals(messagesCount, i); } } finally { feedManager.deleteFeed(FEED1); } }
@Test public void onePublisherOneSubscriberTest() throws Exception { final int messagesCount = 20; Assert.assertTrue(feedManager.createFeed(FEED1)); try { // Create a subscribing process final AtomicInteger receiveCount = new AtomicInteger(0); final AtomicBoolean assertionOk = new AtomicBoolean(true); Cancellable cancellable = notificationService.subscribe( FEED1, new NotificationHandler<String>() { @Override public Type getNotificationType() { return String.class; } @Override public void received(String notification, NotificationContext notificationContext) { LOG.debug("Received notification payload: {}", notification); try { Assert.assertEquals("fake-payload-" + receiveCount.get(), notification); receiveCount.incrementAndGet(); } catch (Throwable t) { assertionOk.set(false); Throwables.propagate(t); } } }); // Runnable to publish notifications on behalf of the publisher entity Runnable publisherRunnable = new Runnable() { @Override public void run() { try { for (int i = 0; i < messagesCount; i++) { notificationService.publish(FEED1, String.format("fake-payload-%d", i)); TimeUnit.MILLISECONDS.sleep(100); } } catch (Throwable e) { Throwables.propagate(e); } } }; Thread publisherThread = new Thread(publisherRunnable); // Give the subscriber some time to prepare for published messages before starting the // publisher TimeUnit.MILLISECONDS.sleep(500); publisherThread.start(); publisherThread.join(); TimeUnit.MILLISECONDS.sleep(2000); cancellable.cancel(); Assert.assertTrue(assertionOk.get()); Assert.assertEquals(messagesCount, receiveCount.get()); } finally { feedManager.deleteFeed(FEED1); try { feedManager.getFeed(FEED1); Assert.fail("Should throw NotificationFeedNotFoundException."); } catch (NotificationFeedNotFoundException e) { // Expected } } }
public static void stopServices() throws Exception { notificationService.stopAndWait(); datasetService.stopAndWait(); dsOpService.stopAndWait(); txManager.stopAndWait(); }