private void removeAllSubscriptions(final Subscription subscription) { LOGGER.debug("Removing all subscriptions for listener {}", subscription.getSourceEntityId()); final MessageListenerImpl listener = listeners.get(subscription.getSourceEntityId()); if (listener != null) { listenerContainer.removeMessageListener(listener); // listener is removed from the active listeners list listeners.remove(subscription.getSourceEntityId()); } // Finally, the subscription is removed from Redis jedisTemplate.del(keysBuilder.getSubscriptionKey(subscription.getSourceEntityId())); LOGGER.debug("Subscriptions removed for listener {} ", subscription.getSourceEntityId()); }
@Override public List<Subscription> get(final Subscription subscription) { // Las subscripciones de una entidad estan registradas bajo la clave subs:idEntity en Redis // El valor asociado a la clave es una hash de pares <channel, notificationParam> // donde cada channel representa una subscripción activa de esa entidad. LOGGER.debug("Retrieving active subscriptions for entity {}", subscription.getSourceEntityId()); final String key = keysBuilder.getSubscriptionKey(subscription.getSourceEntityId()); final Map<String, String> subscriptions = jedisTemplate.hGetAll(key); final List<Subscription> subscriptionList = buildEntitySubscriptions(subscription, subscriptions); LOGGER.debug("Entity {} has {} active subscriptions", subscription.getSourceEntityId(), subscriptionList.size()); return subscriptionList; }
private List<Subscription> buildEntitySubscriptions(final Subscription subscription, final Map<String, String> subscriptions) { final List<Subscription> subscriptionList = new ArrayList<Subscription>(); if (!CollectionUtils.isEmpty(subscriptions)) { final Iterator<String> it = subscriptions.keySet().iterator(); final SubscribeType filterType = subscription.getType(); while (it.hasNext()) { final String field = it.next(); if (filterType == null || ChannelUtils.isTopicOfType(field, filterType)) { subscriptionList.add(ChannelUtils.getSubscription(subscription.getSourceEntityId(), field, subscriptions.get(field))); } } } return subscriptionList; }
private void removeSubscription(final Subscription subscription) { final Topic topic = ChannelUtils.getChannel(subscription); LOGGER.debug("Removing subscription to channel {} for listener {} ", topic.getTopic(), subscription.getSourceEntityId()); final MessageListenerImpl listener = listeners.get(subscription.getSourceEntityId()); if (listener != null) { listenerContainer.removeMessageListener(listener, topic); listener.removeSubscription(topic); } // Finally, the subscription to the topic is removed from Redis jedisTemplate.hDel(keysBuilder.getSubscriptionKey(subscription.getSourceEntityId()), topic.getTopic()); LOGGER.debug("Removed subscription from listener {} to channel {}", subscription.getSourceEntityId(), topic.getTopic()); }
private void removeSubscriptionsOfOneType(final Subscription subscription) { // Por ejemplo, puede ser borrar todas las subscripciones de tipo alarm del listener. // Esto implica en Redis recuperar primero todas las subscripciones de ese tipo y despues borrar // via un hdel // En el container se trata de recuperar todas las subscripciones que existen (holders) y para // cada una, si se trata de una subscripcion del tipo indicado se pasa a eliminar el listener // de su lista de listeners. LOGGER.debug("Removing all subscriptions of type {} for listener {}", subscription.getType(), subscription.getSourceEntityId()); // Recuperamos todos los canales a los cuales esta subscrito el listener. final Set<String> topics = jedisTemplate.hKeys(keysBuilder.getSubscriptionKey(subscription.getSourceEntityId())); final List<String> topicsToRemove = ChannelUtils.filterTopicsOfType(topics, subscription.getType()); // Y para cada uno, eliminamos la subscripcion activa del listener final MessageListenerImpl listener = listeners.get(subscription.getSourceEntityId()); for (final String topicName : topicsToRemove) { if (listener != null) { final Topic topic = ChannelUtils.buildTopic(topicName); listenerContainer.removeMessageListener(listener, topic); listener.removeSubscription(topic); } } LOGGER.debug("Number of subscriptions to remove in Redis: {}", topicsToRemove.size()); if (!CollectionUtils.isEmpty(topicsToRemove)) { // Por ultimo, eliminamos en Redis de la hash de subscripciones todas aquellas que // corresponden a canales del tipo indicado: jedisTemplate.hDel(keysBuilder.getSubscriptionKey(subscription.getSourceEntityId()), topicsToRemove.toArray(new String[0])); } LOGGER.debug("Subscriptions of type {} removed for listener {} ", subscription.getType(), subscription.getSourceEntityId()); }
@Override public void subscribe(final Subscription subscription) { // The first step is to validate that the resource to which the subscription refers exists in // Sentilo. Otherwise an error is thrown checkTargetResourceState(subscription); // Al subscribirse, no sólo se debe habilitar el listener correspondiente, sino que tb se debe // persistir en Redis la subscripcion para la entidad de turno. De esta manera se podrán // iniciar los listeners asociados a las subscripciones ya existentes cuando se arranque // este modulo. // Estos registros en Redis serán del tipo Hash y habrá uno para cada entidad. // Es decir, para cada entidad que este subscrita a algun canal tendremos en Redis // una Hash con key igual a subs:<entityId> y N entradas <field, value> donde: // - field: cada campo de la hash corresponderá a una subscripcion , por lo que el nombre del // campo identificará el canal al cual se está subscrito <event_type>/element_id, donde // element_id es el identificador del recurso al cual se esta subscrito. // - value: el value del campo contiene la informacion necesaria para realizar la notificacion // via HTTP Callback (estos datos son el endpoint, la secretKey a utilizar, politica de // reintentos, ...) final Topic topic = ChannelUtils.getChannel(subscription); // Habilitamos listener activateSubscription(subscription.getSourceEntityId(), topic, subscription.getNotificationParams()); // Persistimos en Redis la subscripcion jedisTemplate.hSet(keysBuilder.getSubscriptionKey(subscription.getSourceEntityId()), topic.getTopic(), converter.marshal(subscription.getNotificationParams())); LOGGER.info("Listener {} subscribed to channel {}", subscription.getSourceEntityId(), topic.getTopic()); }