All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.reactivecommons.async.commons.DLQDiscardNotifier Maven / Gradle / Ivy

There is a newer version: 5.2.2
Show newest version
package org.reactivecommons.async.commons;

import com.fasterxml.jackson.databind.JsonNode;
import io.cloudevents.CloudEvent;
import io.cloudevents.core.builder.CloudEventBuilder;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.java.Log;
import org.reactivecommons.api.domain.DomainEvent;
import org.reactivecommons.api.domain.DomainEventBus;
import org.reactivecommons.async.commons.communications.Message;
import org.reactivecommons.async.commons.converters.MessageConverter;
import org.reactivecommons.async.commons.exceptions.MessageConversionException;
import reactor.core.publisher.Mono;

import java.util.logging.Level;

import static java.lang.String.format;
import static org.reactivecommons.async.commons.converters.json.JacksonMessageConverter.APPLICATION_CLOUD_EVENT_JSON;

@Log
@AllArgsConstructor
public class DLQDiscardNotifier implements DiscardNotifier {
    private final DomainEventBus eventBus;
    private final MessageConverter messageConverter;

    @Override
    public Mono notifyDiscard(Message message) {
        try {
            return notify(message).onErrorResume(this::onError);
        } catch (Exception e) {
            return onError(e);
        }
    }

    private Mono notify(Message message) {
        if (isCloudEvent(message)) {
            CloudEvent cloudEvent = messageConverter.readCloudEvent(message);
            String dlqType = cloudEvent.getType() + ".dlq";
            CloudEvent forDlq = CloudEventBuilder.from(cloudEvent)
                    .withType(dlqType)
                    .build();
            return Mono.from(eventBus.emit(forDlq));
        }
        try {
            JsonSkeleton node = messageConverter.readValue(message, JsonSkeleton.class);
            return Mono.from(eventBus.emit(createEvent(node)));
        } catch (MessageConversionException e) {
            return notifyUnreadableMessage(message, e);
        }
    }

    private Mono notifyUnreadableMessage(Message message, MessageConversionException e) {
        String bodyString;
        try {
            bodyString = new String(message.getBody());
        } catch (Exception ex) {
            bodyString = "Opaque binary Message, unable to decode: " + ex.getMessage();
        }
        log.log(Level.SEVERE, format("Unable to interpret discarded message: %s", bodyString), e);
        DomainEvent event = new DomainEvent<>("corruptData.dlq", "corruptData", bodyString);
        return Mono.from(eventBus.emit(event));
    }

    private Mono onError(Throwable e) {
        log.log(Level.SEVERE, "FATAL!! unable to notify Discard of message!!", e);
        return Mono.empty();
    }

    private DomainEvent createEvent(JsonSkeleton skeleton) {
        if (skeleton.isCommand()) {
            return new DomainEvent<>(skeleton.name + ".dlq", skeleton.commandId, skeleton.data);
        } else if (skeleton.isEvent()) {
            return new DomainEvent<>(skeleton.name + ".dlq", skeleton.eventId, skeleton.data);
        } else if (skeleton.isQuery()) {
            return new DomainEvent<>(skeleton.resource + ".dlq", skeleton.resource + "query", skeleton.queryData);
        } else {
            throw new MessageConversionException("Fail to math message type");
        }
    }

    private boolean isCloudEvent(Message message) {
        return message.getProperties().getContentType() != null
                && message.getProperties().getContentType().contains(APPLICATION_CLOUD_EVENT_JSON);
    }

    @Data
    private static class JsonSkeleton {
        private String name;
        private String resource;
        private String eventId;
        private JsonNode data;
        private JsonNode queryData;
        private String commandId;

        public boolean isEvent() {
            return !empty(eventId) && !empty(name) && data != null;
        }

        public boolean isCommand() {
            return !empty(commandId) && !empty(name) && data != null;
        }

        public boolean isQuery() {
            return !empty(resource) && queryData != null;
        }

        private boolean empty(String str) {
            return str == null || str.trim().isEmpty();
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy