package net.kencochrane.raven.connection;

import net.kencochrane.raven.event.LoggedEvent;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Asynchronous usage of a connection.
 * <p>
 * Instead of synchronously sending each event to a connection, use a ThreadPool to establish the connection
 * and submit the event.
 * </p>
 */
public class AsyncConnection implements Connection {
    /**
     * Connection used to actually send the events.
     */
    private final Connection actualConnection;
    // TODO: Allow the user to change to a custom executor?
    private final ExecutorService executorService = Executors.newCachedThreadPool();

    /**
     * Create a connection which will rely on an executor to send events.
     *
     * @param actualConnection connection used to send the events.
     */
    public AsyncConnection(Connection actualConnection) {
        this.actualConnection = actualConnection;
    }

    @Override
    public void send(LoggedEvent event) {
        // TODO: Consider adding an option to wait when it's full?
        executorService.execute(new LoggedEventSubmitter(event));
    }

    /**
     * Simple runnable using the {@link #send(net.kencochrane.raven.event.LoggedEvent)} method of the
     * {@link #actualConnection}.
     */
    private final class LoggedEventSubmitter implements Runnable {
        private final LoggedEvent event;

        private LoggedEventSubmitter(LoggedEvent event) {
            this.event = event;
        }

        @Override
        public void run() {
            actualConnection.send(event);
        }
    }
}

@@ -168,16 +168,174 @@
 ecutors;
+%0Aimport java.util.concurrent.ThreadFactory;%0Aimport java.util.concurrent.atomic.AtomicInteger;%0Aimport java.util.logging.Level;%0Aimport java.util.logging.Logger;
 %0A%0A/**%0A *
@@ -577,16 +577,117 @@
 ction %7B%0A
+    private static final Logger logger = Logger.getLogger(AsyncConnection.class.getCanonicalName());%0A
     /**%0A
@@ -935,16 +935,41 @@
 eadPool(
+new DaemonThreadFactory()
 );%0A%0A    
@@ -1435,24 +1435,976 @@
 t));%0A    %7D%0A%0A
+    private static final class DaemonThreadFactory implements ThreadFactory %7B%0A        private static final AtomicInteger poolNumber = new AtomicInteger(1);%0A        private final ThreadGroup group;%0A        private final AtomicInteger threadNumber = new AtomicInteger(1);%0A        private final String namePrefix;%0A%0A        private DaemonThreadFactory() %7B%0A            SecurityManager s = System.getSecurityManager();%0A            group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();%0A            namePrefix = %22pool-%22 + poolNumber.getAndIncrement() + %22-thread-%22;%0A        %7D%0A%0A        public Thread newThread(Runnable r) %7B%0A            Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);%0A            if (!t.isDaemon())%0A                t.setDaemon(true);%0A            if (t.getPriority() != Thread.NORM_PRIORITY)%0A                t.setPriority(Thread.NORM_PRIORITY);%0A            return t;%0A        %7D%0A    %7D%0A%0A
     /**%0A    
@@ -2795,24 +2795,46 @@
 oid run() %7B%0A
+            try %7B%0A    
             
@@ -2863,16 +2863,171 @@
 event);%0A
+            %7D catch (Exception e) %7B%0A                logger.log(Level.SEVERE, %22An exception occurred while sending the event to Sentry.%22, e);%0A            %7D%0A
         

Use a DaemonThreadFactory for AsyncConnection