DMF health check (#577)

* DMF support PING message for health checks.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Device simulator supports PING.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Code cleanup.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Revert accidental checkin.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Fix tests.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Simplify API.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Remove simulator dead letter.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Remove dead code. 

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Reduce code.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Add message for one more error case.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
This commit is contained in:
Kai Zimmermann
2017-09-15 12:50:27 +02:00
committed by GitHub
parent 2818c8505a
commit da13bd79d9
18 changed files with 245 additions and 133 deletions

View File

@@ -264,8 +264,8 @@ public class AmqpConfiguration {
*/
@Bean
@ConditionalOnMissingBean
public AmqpSenderService amqpSenderServiceBean() {
return new DefaultAmqpSenderService(rabbitTemplate());
public AmqpMessageSenderService amqpSenderServiceBean() {
return new DefaultAmqpMessageSenderService(rabbitTemplate());
}
@Bean
@@ -325,7 +325,7 @@ public class AmqpConfiguration {
@Bean
@ConditionalOnMissingBean(AmqpMessageDispatcherService.class)
public AmqpMessageDispatcherService amqpMessageDispatcherService(final RabbitTemplate rabbitTemplate,
final AmqpSenderService amqpSenderService, final ArtifactUrlHandler artifactUrlHandler,
final AmqpMessageSenderService amqpSenderService, final ArtifactUrlHandler artifactUrlHandler,
final SystemSecurityContext systemSecurityContext, final SystemManagement systemManagement,
final TargetManagement targetManagement) {
return new AmqpMessageDispatcherService(rabbitTemplate, amqpSenderService, artifactUrlHandler,

View File

@@ -39,6 +39,7 @@ import org.eclipse.hawkbit.util.IpUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.cloud.bus.ServiceMatcher;
@@ -47,7 +48,7 @@ import org.springframework.context.event.EventListener;
/**
* {@link AmqpMessageDispatcherService} create all outgoing AMQP messages and
* delegate the messages to a {@link AmqpSenderService}.
* delegate the messages to a {@link AmqpMessageSenderService}.
*
* Additionally the dispatcher listener/subscribe for some target events e.g.
* assignment.
@@ -58,7 +59,7 @@ public class AmqpMessageDispatcherService extends BaseAmqpService {
private static final Logger LOG = LoggerFactory.getLogger(AmqpMessageDispatcherService.class);
private final ArtifactUrlHandler artifactUrlHandler;
private final AmqpSenderService amqpSenderService;
private final AmqpMessageSenderService amqpSenderService;
private final SystemSecurityContext systemSecurityContext;
private final SystemManagement systemManagement;
private final TargetManagement targetManagement;
@@ -83,10 +84,10 @@ public class AmqpMessageDispatcherService extends BaseAmqpService {
* to check in cluster case if the message is from the same
* cluster node
*/
public AmqpMessageDispatcherService(final RabbitTemplate rabbitTemplate, final AmqpSenderService amqpSenderService,
final ArtifactUrlHandler artifactUrlHandler, final SystemSecurityContext systemSecurityContext,
final SystemManagement systemManagement, final TargetManagement targetManagement,
final ServiceMatcher serviceMatcher) {
public AmqpMessageDispatcherService(final RabbitTemplate rabbitTemplate,
final AmqpMessageSenderService amqpSenderService, final ArtifactUrlHandler artifactUrlHandler,
final SystemSecurityContext systemSecurityContext, final SystemManagement systemManagement,
final TargetManagement targetManagement, final ServiceMatcher serviceMatcher) {
super(rabbitTemplate);
this.artifactUrlHandler = artifactUrlHandler;
this.amqpSenderService = amqpSenderService;
@@ -143,6 +144,16 @@ public class AmqpMessageDispatcherService extends BaseAmqpService {
amqpSenderService.sendMessage(message, targetAdress);
}
void sendPingReponseToDmfReceiver(final Message ping, final String tenant) {
final Message message = MessageBuilder.withBody(String.valueOf(System.currentTimeMillis()).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_TEXT_PLAIN)
.setCorrelationId(ping.getMessageProperties().getCorrelationId())
.setHeader(MessageHeaderKey.TYPE, MessageType.PING_RESPONSE).setHeader(MessageHeaderKey.TENANT, tenant)
.build();
amqpSenderService.sendMessage(message, ping.getMessageProperties().getReplyTo());
}
/**
* Method to send a message to a RabbitMQ Exchange after the assignment of
* the Distribution set to a Target has been canceled.

View File

@@ -115,20 +115,25 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
* @return the rpc message back to supplier.
*/
public Message onMessage(final Message message, final String type, final String tenant, final String virtualHost) {
checkContentTypeJson(message);
final SecurityContext oldContext = SecurityContextHolder.getContext();
try {
final MessageType messageType = MessageType.valueOf(type);
switch (messageType) {
case THING_CREATED:
checkContentTypeJson(message);
setTenantSecurityContext(tenant);
registerTarget(message, virtualHost);
break;
case EVENT:
checkContentTypeJson(message);
setTenantSecurityContext(tenant);
final String topicValue = getStringHeaderKey(message, MessageHeaderKey.TOPIC, "EventTopic is null");
final EventTopic eventTopic = EventTopic.valueOf(topicValue);
handleIncomingEvent(message, eventTopic);
handleIncomingEvent(message);
break;
case PING:
if (isCorrelationIdNotEmpty(message)) {
amqpMessageDispatcherService.sendPingReponseToDmfReceiver(message, tenant);
}
break;
default:
logAndThrowMessageError(message, "No handle method was found for the given message type.");
@@ -206,8 +211,8 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
* @param topic
* the topic of the event.
*/
private void handleIncomingEvent(final Message message, final EventTopic topic) {
switch (topic) {
private void handleIncomingEvent(final Message message) {
switch (EventTopic.valueOf(getStringHeaderKey(message, MessageHeaderKey.TOPIC, "EventTopic is null"))) {
case UPDATE_ACTION_STATUS:
updateActionStatus(message);
break;

View File

@@ -12,13 +12,14 @@ import java.net.URI;
import javax.validation.constraints.NotNull;
import org.eclipse.hawkbit.util.IpUtil;
import org.springframework.amqp.core.Message;
/**
* Interface to send a amqp message.
*/
@FunctionalInterface
public interface AmqpSenderService {
public interface AmqpMessageSenderService {
/**
* Send the given message to the given uri. The uri contains the (virtual)
@@ -29,18 +30,24 @@ public interface AmqpSenderService {
* @param replyTo
* the reply to uri
*/
void sendMessage(@NotNull Message message, @NotNull URI replyTo);
default void sendMessage(@NotNull final Message message, @NotNull final URI replyTo) {
if (!IpUtil.isAmqpUri(replyTo)) {
return;
}
/**
* Extract the exchange from the uri. Default implementation removes the
* first /.
*
* @param amqpUri
* the amqp uri
* @return the exchange.
*/
default String extractExchange(final URI amqpUri) {
return amqpUri.getPath().substring(1);
sendMessage(message, replyTo.getPath().substring(1));
}
/**
* Send the given message to the given host and exchange.
*
* @param message
* the amqp message
* @param exchange
* to send to
* @param virtualHost
* to send to
*/
void sendMessage(@NotNull final Message message, @NotNull final String exchange);
}

View File

@@ -8,11 +8,9 @@
*/
package org.eclipse.hawkbit.amqp;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.UUID;
import org.eclipse.hawkbit.util.IpUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
@@ -24,30 +22,27 @@ import org.springframework.amqp.rabbit.support.CorrelationData;
* message to the configured spring rabbitmq connections. The exchange is
* extracted from the uri.
*/
public class DefaultAmqpSenderService implements AmqpSenderService {
private static final Logger LOGGER = LoggerFactory.getLogger(DefaultAmqpSenderService.class);
private final RabbitTemplate internalAmqpTemplate;
public class DefaultAmqpMessageSenderService extends BaseAmqpService implements AmqpMessageSenderService {
private static final Logger LOGGER = LoggerFactory.getLogger(DefaultAmqpMessageSenderService.class);
/**
* Constructor.
*
* @param internalAmqpTemplate
* the amqp template
* @param rabbitTemplate
* the AMQP template
*/
public DefaultAmqpSenderService(final RabbitTemplate internalAmqpTemplate) {
this.internalAmqpTemplate = internalAmqpTemplate;
public DefaultAmqpMessageSenderService(final RabbitTemplate rabbitTemplate) {
super(rabbitTemplate);
}
@Override
public void sendMessage(final Message message, final URI replyTo) {
if (!IpUtil.isAmqpUri(replyTo)) {
return;
}
public void sendMessage(final Message message, final String exchange) {
final String correlationId = UUID.randomUUID().toString();
final String exchange = extractExchange(replyTo);
message.getMessageProperties().setCorrelationId(correlationId.getBytes(StandardCharsets.UTF_8));
if (isCorrelationIdEmpty(message)) {
message.getMessageProperties().setCorrelationId(correlationId.getBytes(StandardCharsets.UTF_8));
}
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Sending message {} to exchange {} with correlationId {}", message, exchange, correlationId);
@@ -55,7 +50,12 @@ public class DefaultAmqpSenderService implements AmqpSenderService {
LOGGER.debug("Sending message to exchange {} with correlationId {}", exchange, correlationId);
}
internalAmqpTemplate.send(exchange, null, message, new CorrelationData(correlationId));
getRabbitTemplate().send(exchange, null, message, new CorrelationData(correlationId));
}
protected static boolean isCorrelationIdEmpty(final Message message) {
return message.getMessageProperties().getCorrelationId() == null
|| message.getMessageProperties().getCorrelationId().length <= 0;
}
}