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 CNSSubscription getSubscription(String arn) throws Exception { // read form index to get composite col-name CmbColumnSlice<String, String> slice = cassandraHandler.readColumnSlice( AbstractDurablePersistence.CNS_KEYSPACE, columnFamilySubscriptionsIndex, arn, null, null, 1, CMB_SERIALIZER.STRING_SERIALIZER, CMB_SERIALIZER.STRING_SERIALIZER, CMB_SERIALIZER.STRING_SERIALIZER); if (slice != null) { // get Column from main table String colName = slice.getColumns().get(0).getName(); CnsSubscriptionProtocol protocol = getEndpointAndProtoIndexValProtocol(colName); String endpoint = getEndpointAndProtoIndexValEndpoint(colName); CmbComposite columnName = cassandraHandler.getCmbComposite(endpoint, protocol.name()); CmbColumn<CmbComposite, String> column = cassandraHandler.readColumn( AbstractDurablePersistence.CNS_KEYSPACE, columnFamilySubscriptions, Util.getCnsTopicArn(arn), columnName, CMB_SERIALIZER.STRING_SERIALIZER, CMB_SERIALIZER.COMPOSITE_SERIALIZER, CMB_SERIALIZER.STRING_SERIALIZER); if (column != null) { CNSSubscription s = extractSubscriptionFromColumn(column, Util.getCnsTopicArn(arn)); s.checkIsValid(); return s; } } return null; }
/** * Enumerate all subs in a topic * * @param nextToken The ARN of the last sub-returned or null is first time call. * @param topicArn * @param protocol * @param pageSize * @param hidePendingArn * @return The list of subscriptions given a topic. Note: if nextToken is provided, the returned * list will not contain it for convenience * @throws Exception */ public List<CNSSubscription> listSubscriptionsByTopic( String nextToken, String topicArn, CnsSubscriptionProtocol protocol, int pageSize, boolean hidePendingArn) throws Exception { if (nextToken != null) { if (getSubscription(nextToken) == null) { throw new SubscriberNotFoundException("Subscriber not found for arn " + nextToken); } } // read from index to get composite-col-name corresponding to nextToken CmbComposite nextTokenComposite = null; if (nextToken != null) { CmbColumnSlice<String, String> slice = cassandraHandler.readColumnSlice( AbstractDurablePersistence.CNS_KEYSPACE, columnFamilySubscriptionsIndex, nextToken, null, null, 1, CMB_SERIALIZER.STRING_SERIALIZER, CMB_SERIALIZER.STRING_SERIALIZER, CMB_SERIALIZER.STRING_SERIALIZER); if (slice == null) { throw new IllegalArgumentException("Could not find any subscription with arn " + nextToken); } // get Column from main table String colName = slice.getColumns().get(0).getName(); CnsSubscriptionProtocol tokProtocol = getEndpointAndProtoIndexValProtocol(colName); String endpoint = getEndpointAndProtoIndexValEndpoint(colName); nextTokenComposite = cassandraHandler.getCmbComposite(endpoint, tokProtocol.name()); } List<CNSSubscription> l = new ArrayList<CNSSubscription>(); CNSTopic t = PersistenceFactory.getTopicPersistence().getTopic(topicArn); if (t == null) { throw new TopicNotFoundException("Resource not found."); } // read pageSize at a time CmbColumnSlice<CmbComposite, String> cols = cassandraHandler.readColumnSlice( AbstractDurablePersistence.CNS_KEYSPACE, columnFamilySubscriptions, topicArn, nextTokenComposite, null, pageSize, CMB_SERIALIZER.STRING_SERIALIZER, CMB_SERIALIZER.COMPOSITE_SERIALIZER, CMB_SERIALIZER.STRING_SERIALIZER); if (nextToken != null && cols.size() > 0) { cols.getColumns().remove(0); } while (l.size() < pageSize) { if (cols == null || cols.size() == 0) { return l; } for (CmbColumn<CmbComposite, String> col : cols.getColumns()) { CNSSubscription sub = extractSubscriptionFromColumn(col, topicArn); // ignore invalid subscriptions coming from Cassandra try { sub.checkIsValid(); } catch (CMBException ex) { logger.error("event=invalid_subscription " + sub.toString(), ex); continue; } if (protocol != null && protocol != sub.getProtocol()) { continue; } if (hidePendingArn) { if (sub.isConfirmed()) { l.add(sub); } else { sub.setArn("PendingConfirmation"); l.add(sub); } } else { l.add(sub); } if (l.size() == pageSize) { return l; } } nextTokenComposite = cols.getColumns().get(cols.size() - 1).getName(); cols = cassandraHandler.readColumnSlice( AbstractDurablePersistence.CNS_KEYSPACE, columnFamilySubscriptions, topicArn, nextTokenComposite, null, pageSize, CMB_SERIALIZER.STRING_SERIALIZER, CMB_SERIALIZER.COMPOSITE_SERIALIZER, CMB_SERIALIZER.STRING_SERIALIZER); if (cols.size() > 0) { cols.getColumns().remove(0); } } return l; }
private List<CNSSubscription> listSubscriptions( String nextToken, CnsSubscriptionProtocol protocol, String userId, boolean hidePendingArn) throws Exception { if (nextToken != null) { if (getSubscription(nextToken) == null) { throw new SubscriberNotFoundException("Subscriber not found for arn " + nextToken); } } // Algorithm is to keep reading in chunks of 100 till we've seen 500 from the nextToken-ARN List<CNSSubscription> l = new ArrayList<CNSSubscription>(); // read form index to get sub-arn while (l.size() < 100) { CmbColumnSlice<String, String> slice = cassandraHandler.readColumnSlice( AbstractDurablePersistence.CNS_KEYSPACE, columnFamilySubscriptionsUserIndex, userId, nextToken, null, 500, CMB_SERIALIZER.STRING_SERIALIZER, CMB_SERIALIZER.STRING_SERIALIZER, CMB_SERIALIZER.STRING_SERIALIZER); if (slice == null) { return l; } // get Column from main table List<CmbColumn<String, String>> cols = slice.getColumns(); if (nextToken != null) { cols.remove(0); } if (cols.size() == 0) { return l; } for (CmbColumn<String, String> col : cols) { String subArn = col.getName(); CNSSubscription subscription = getSubscription(subArn); if (subscription == null) { throw new IllegalStateException( "Subscriptions-user-index contains subscription-arn which doesn't exist in subscriptions-index. subArn:" + subArn); } // ignore invalid subscriptions coming from Cassandra try { subscription.checkIsValid(); } catch (CMBException ex) { logger.error("event=invalid_subscription " + subscription.toString(), ex); continue; } if (protocol != null && subscription.getProtocol() != protocol) { continue; } if (hidePendingArn) { if (subscription.isConfirmed()) { l.add(subscription); } else { subscription.setArn("PendingConfirmation"); l.add(subscription); } } else { l.add(subscription); } if (l.size() == 100) { return l; } } nextToken = cols.get(cols.size() - 1).getName(); } return l; }