Package com.bimbr.clisson.client

Source Code of com.bimbr.clisson.client.AsyncHttpRecorder$HttpInvocation

package com.bimbr.clisson.client;

import static com.bimbr.clisson.util.Arguments.nonEmpty;
import static com.bimbr.clisson.util.Arguments.nonNull;
import static com.bimbr.clisson.util.Arguments.positive;

import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.bimbr.clisson.protocol.Event;
import com.bimbr.clisson.protocol.Json;
import com.bimbr.util.Clock;

/**
* A {@link Recorder} that asynchronously sends the events to the server over HTTP. Allows the calling code to continue
* execution immediately without the need to wait for Clisson server to respond. This implementation uses an internal
* buffer to store the messages to be submitted. When the buffer fills up subsequent calls to submission methods will
* succeed, but will log errors reporting that the submission had to be dropped.
*
* @author mmakowski
* @since 1.0.0
*/
final class AsyncHttpRecorder implements Recorder {
    private static final Logger logger = LoggerFactory.getLogger(AsyncHttpRecorder.class);
   
    private final String      sourceId;
    private final HttpInvoker invoker;
    private final Clock       clock;
    private final BlockingQueue<HttpInvocation> invocationBuffer;
   
    /**
     * @param sourceId the id of the component that is the source of events
     * @param invoker the {@link HttpInvoker} used to communicate with the server
     * @paran bufferSize the size of internal buffer
     * @param clock the {@link Clock} used to generate event timestamp
     */
    AsyncHttpRecorder(final String      sourceId,
                      final HttpInvoker invoker,
                      final int         bufferSize,
                      final Clock       clock) {
        this.sourceId = nonEmpty(sourceId, "sourceId");
        this.invoker = nonNull(invoker, "invoker");
        this.invocationBuffer = new ArrayBlockingQueue<HttpInvocation>(positive(bufferSize, "bufferSize"));
        this.clock = nonNull(clock, "clock");
        startHttpInvocationThread();
    }
   
    /**
     * @see Recorder#checkpoint(String, String)
     */
    public void checkpoint(final String messageId, final String description) {
        final Set<String> messageIds = new TreeSet<String>();
        messageIds.add(messageId);
        event(messageIds, messageIds, description);
    }

    /**
     * @see Recorder#event(Set, Set, String)
     */
    public void event(final Set<String> inputMessageIds, final Set<String> outputMessageIds, final String description) {
        event(new Event(sourceId, clock.getTime(), inputMessageIds, outputMessageIds, description));
    }
   
    /**
     * @see Recorder#event(Event)
     */
    public void event(final Event event) {
        final boolean enqueued = invocationBuffer.offer(new EventSubmission(event));
        if (!enqueued) {
            logger.error("buffer capacity of " + invocationBuffer.size() + " has been reached; unable to enqueue new invocations, dropping " + event);
        }
    }

    private void startHttpInvocationThread() {
        logger.debug("staring HTTP invoker thread...");
        final Thread invocationThread = new Thread(new BufferProcessor(), "clisson-http-invoker");
        invocationThread.setDaemon(true);
        invocationThread.start();
        logger.debug("HTTP invoker thread started");
    }
   
    private static interface HttpInvocation {
        void invoke(HttpInvoker invoker);
    }
    private static final class EventSubmission implements HttpInvocation {
        private final Event event;
       
        public EventSubmission(final Event event) {
            this.event = event;
        }
       
        public void invoke(HttpInvoker invoker) {
            invoker.post("/event", Json.jsonFor(event));
        }
    }
   
    private final class BufferProcessor implements Runnable {
        public void run() {
            while (true) {
                try {
                    invocationBuffer.take().invoke(invoker);
                } catch (Exception e) {
                    logger.error("error while invoking Clisson server over HTTP", e);
                }
            }
        }
    }
}
TOP

Related Classes of com.bimbr.clisson.client.AsyncHttpRecorder$HttpInvocation

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.