private void deleteIndexesAll(List<CNSSubscription> subscriptionList) throws PersistenceException { List<String> subArnList = new LinkedList<String>(); List<String> userIdList = new LinkedList<String>(); List<String> tokenList = new LinkedList<String>(); for (CNSSubscription sub : subscriptionList) { subArnList.add(sub.getArn()); userIdList.add(sub.getUserId()); tokenList.add(sub.getToken()); } cassandraHandler.deleteBatch( AbstractDurablePersistence.CNS_KEYSPACE, columnFamilySubscriptionsIndex, subArnList, null, CMB_SERIALIZER.STRING_SERIALIZER, CMB_SERIALIZER.STRING_SERIALIZER); cassandraHandler.deleteBatch( AbstractDurablePersistence.CNS_KEYSPACE, columnFamilySubscriptionsUserIndex, userIdList, subArnList, CMB_SERIALIZER.STRING_SERIALIZER, CMB_SERIALIZER.STRING_SERIALIZER); cassandraHandler.deleteBatch( AbstractDurablePersistence.CNS_KEYSPACE, columnFamilySubscriptionsTokenIndex, tokenList, subArnList, CMB_SERIALIZER.STRING_SERIALIZER, CMB_SERIALIZER.STRING_SERIALIZER); }
private String getColumnValuesJSON(CNSSubscription s) throws JSONException { Writer writer = new StringWriter(); JSONWriter jw = new JSONWriter(writer); jw = jw.object(); if (s.getEndpoint() != null) { jw.key("endPoint").value(s.getEndpoint()); } if (s.getToken() != null) { jw.key("token").value(s.getToken()); } if (s.getArn() != null) { jw.key("subArn").value(s.getArn()); } if (s.getUserId() != null) { jw.key("userId").value(s.getUserId()); } if (s.getConfirmDate() != null) { jw.key("confirmDate").value(s.getConfirmDate().getTime() + ""); } if (s.getProtocol() != null) { jw.key("protocol").value(s.getProtocol().toString()); } if (s.getRequestDate() != null) { jw.key("requestDate").value(s.getRequestDate().getTime() + ""); } jw.key("authenticateOnSubscribe").value(s.isAuthenticateOnUnsubscribe() + ""); jw.key("isConfirmed").value(s.isConfirmed() + ""); jw.key("rawMessageDelivery").value(s.getRawMessageDelivery() + ""); jw.endObject(); return writer.toString(); }
private void insertOrUpdateSubsAndIndexes(final CNSSubscription subscription, Integer ttl) throws Exception { subscription.checkIsValid(); CmbComposite columnName = cassandraHandler.getCmbComposite( subscription.getEndpoint(), subscription.getProtocol().name()); cassandraHandler.update( AbstractDurablePersistence.CNS_KEYSPACE, columnFamilySubscriptions, subscription.getTopicArn(), columnName, getColumnValuesJSON(subscription), CMB_SERIALIZER.STRING_SERIALIZER, CMB_SERIALIZER.COMPOSITE_SERIALIZER, CMB_SERIALIZER.STRING_SERIALIZER, ttl); cassandraHandler.insertRow( AbstractDurablePersistence.CNS_KEYSPACE, subscription.getArn(), columnFamilySubscriptionsIndex, getIndexColumnValues(subscription.getEndpoint(), subscription.getProtocol()), CMB_SERIALIZER.STRING_SERIALIZER, CMB_SERIALIZER.STRING_SERIALIZER, CMB_SERIALIZER.STRING_SERIALIZER, ttl); cassandraHandler.insertRow( AbstractDurablePersistence.CNS_KEYSPACE, subscription.getUserId(), columnFamilySubscriptionsUserIndex, new HashMap<String, String>() { { put(subscription.getArn(), ""); } }, CMB_SERIALIZER.STRING_SERIALIZER, CMB_SERIALIZER.STRING_SERIALIZER, CMB_SERIALIZER.STRING_SERIALIZER, ttl); cassandraHandler.insertRow( AbstractDurablePersistence.CNS_KEYSPACE, subscription.getToken(), columnFamilySubscriptionsTokenIndex, new HashMap<String, String>() { { put(subscription.getArn(), ""); } }, CMB_SERIALIZER.STRING_SERIALIZER, CMB_SERIALIZER.STRING_SERIALIZER, CMB_SERIALIZER.STRING_SERIALIZER, ttl); }
@Override public void unsubscribeAll(String topicArn) throws Exception { int pageSize = 1000; String nextToken = null; List<CNSSubscription> subs = listSubscriptionsByTopic(nextToken, topicArn, null, pageSize, false); // Note: for pagination to work we need the nextToken's corresponding sub to not be deleted. CNSSubscription nextTokenSub = null; while (subs.size() > 0) { // if retrieve subscription is less than page size, delete all index. if (subs.size() < pageSize) { deleteIndexesAll(subs); break; } else { // keep the last subscription for pagination purpose. nextTokenSub = subs.get(subs.size() - 1); nextToken = nextTokenSub.getArn(); subs.remove(subs.size() - 1); deleteIndexesAll(subs); subs = listSubscriptionsByTopic(nextToken, topicArn, null, pageSize, false); deleteIndexes(nextTokenSub.getArn(), nextTokenSub.getUserId(), nextTokenSub.getToken()); } } // int subscriptionConfirmedNum = (int)cassandraHandler.getCounter(CNS_KEYSPACE, // columnFamilyTopicStats, topicArn, "subscriptionConfirmed", CMB_SERIALIZER.STRING_SERIALIZER, // CMB_SERIALIZER.STRING_SERIALIZER); // int subscriptionPendingNum = (int)cassandraHandler.getCounter(CNS_KEYSPACE, // columnFamilyTopicStats, topicArn, "subscriptionPending", CMB_SERIALIZER.STRING_SERIALIZER, // CMB_SERIALIZER.STRING_SERIALIZER); cassandraHandler.incrementCounter( AbstractDurablePersistence.CNS_KEYSPACE, columnFamilyTopicStats, topicArn, "subscriptionDeleted", 1, CMB_SERIALIZER.STRING_SERIALIZER, CMB_SERIALIZER.STRING_SERIALIZER); cassandraHandler.decrementCounter( AbstractDurablePersistence.CNS_KEYSPACE, columnFamilyTopicStats, topicArn, "subscriptionConfirmed", 1, CMB_SERIALIZER.STRING_SERIALIZER, CMB_SERIALIZER.STRING_SERIALIZER); cassandraHandler.decrementCounter( AbstractDurablePersistence.CNS_KEYSPACE, columnFamilyTopicStats, topicArn, "subscriptionPending", 1, CMB_SERIALIZER.STRING_SERIALIZER, CMB_SERIALIZER.STRING_SERIALIZER); cassandraHandler.delete( AbstractDurablePersistence.CNS_KEYSPACE, columnFamilySubscriptions, topicArn, null, CMB_SERIALIZER.STRING_SERIALIZER, CMB_SERIALIZER.STRING_SERIALIZER); }
@Override public CNSSubscription subscribe( String endpoint, CnsSubscriptionProtocol protocol, String topicArn, String userId) throws Exception { // subscription is unique by protocol + endpoint + topic final CNSSubscription subscription = new CNSSubscription(endpoint, protocol, topicArn, userId); CNSTopic t = PersistenceFactory.getTopicPersistence().getTopic(topicArn); if (t == null) { throw new TopicNotFoundException("Resource not found."); } // check if queue exists for cqs endpoints if (protocol.equals(CnsSubscriptionProtocol.cqs)) { CQSQueue queue = PersistenceFactory.getQueuePersistence() .getQueue(com.comcast.cqs.util.Util.getRelativeQueueUrlForArn(endpoint)); if (queue == null) { throw new CMBException( CMBErrorCodes.NotFound, "Queue with arn " + endpoint + " does not exist."); } } subscription.setArn(Util.generateCnsTopicSubscriptionArn(topicArn, protocol, endpoint)); // attempt to delete existing subscription /*Composite superColumnName = new Composite(subscription.getEndpoint(), subscription.getProtocol().name()); HSuperColumn<Composite, String, String> superCol = readColumnFromSuperColumnFamily(columnFamilySubscriptions, subscription.getTopicArn(), superColumnName, new StringSerializer(), new CompositeSerializer(), StringSerializer.get(), StringSerializer.get(), CMBProperties.getInstance().getReadConsistencyLevel()); if (superCol != null) { CNSSubscription exisitingSub = extractSubscriptionFromSuperColumn(superCol, topicArn); deleteIndexes(exisitingSub.getArn(), exisitingSub.getUserId(), exisitingSub.getToken()); deleteSuperColumn(subscriptionsTemplate, exisitingSub.getTopicArn(), superColumnName); }*/ // then set confirmation stuff and update cassandra CNSSubscription retrievedSubscription = getSubscription(subscription.getArn()); if (!CMBProperties.getInstance().getCNSRequireSubscriptionConfirmation()) { subscription.setConfirmed(true); subscription.setConfirmDate(new Date()); insertOrUpdateSubsAndIndexes(subscription, null); if (retrievedSubscription == null) { cassandraHandler.incrementCounter( AbstractDurablePersistence.CNS_KEYSPACE, columnFamilyTopicStats, subscription.getTopicArn(), "subscriptionConfirmed", 1, CMB_SERIALIZER.STRING_SERIALIZER, CMB_SERIALIZER.STRING_SERIALIZER); } } else { // protocols that cannot confirm subscriptions (e.g. redisPubSub) // get an automatic confirmation here if (!protocol.canConfirmSubscription()) { subscription.setConfirmed(true); subscription.setConfirmDate(new Date()); insertOrUpdateSubsAndIndexes(subscription, null); // auto confirm subscription to cqs queue by owner } else if (protocol.equals(CnsSubscriptionProtocol.cqs)) { String queueOwner = com.comcast.cqs.util.Util.getQueueOwnerFromArn(endpoint); if (queueOwner != null && queueOwner.equals(userId)) { subscription.setConfirmed(true); subscription.setConfirmDate(new Date()); insertOrUpdateSubsAndIndexes(subscription, null); if (retrievedSubscription == null) { cassandraHandler.incrementCounter( AbstractDurablePersistence.CNS_KEYSPACE, columnFamilyTopicStats, subscription.getTopicArn(), "subscriptionConfirmed", 1, CMB_SERIALIZER.STRING_SERIALIZER, CMB_SERIALIZER.STRING_SERIALIZER); } } else { // use cassandra ttl to implement expiration after 3 days insertOrUpdateSubsAndIndexes(subscription, 3 * 24 * 60 * 60); if (retrievedSubscription == null) { cassandraHandler.incrementCounter( AbstractDurablePersistence.CNS_KEYSPACE, columnFamilyTopicStats, subscription.getTopicArn(), "subscriptionPending", 1, CMB_SERIALIZER.STRING_SERIALIZER, CMB_SERIALIZER.STRING_SERIALIZER); } } } else { // use cassandra ttl to implement expiration after 3 days insertOrUpdateSubsAndIndexes(subscription, 3 * 24 * 60 * 60); if (retrievedSubscription == null) { cassandraHandler.incrementCounter( AbstractDurablePersistence.CNS_KEYSPACE, columnFamilyTopicStats, subscription.getTopicArn(), "subscriptionPending", 1, CMB_SERIALIZER.STRING_SERIALIZER, CMB_SERIALIZER.STRING_SERIALIZER); } } } CNSSubscriptionAttributes attributes = new CNSSubscriptionAttributes(topicArn, subscription.getArn(), userId); PersistenceFactory.getCNSAttributePersistence() .setSubscriptionAttributes(attributes, subscription.getArn()); return subscription; }