package com.github.susom.database;

import java.util.Map;

import org.slf4j.MDC;

import io.vertx.core.AsyncResult;
import io.vertx.core.Future;
import io.vertx.core.Handler;
import io.vertx.core.Vertx;
import io.vertx.core.WorkerExecutor;

/**
 * This is a convenience class to work-around issues with using the SLF4J
 * MDC class. It provides versions of async functionality that preserve
 * the MDC across the event and worker threads.
 *
 * @author garricko
 */
public class VertxUtil {
  /**
   * Equivalent to {@link Vertx#executeBlocking(Handler, Handler)},
   * but preserves the {@link MDC} correctly.
   */
  public static <T> void executeBlocking(Vertx vertx, Handler<Future<T>> future, Handler<AsyncResult<T>> handler) {
    executeBlocking(vertx, future, true, handler);
  }

  /**
   * Equivalent to {@link Vertx#executeBlocking(Handler, boolean, Handler)},
   * but preserves the {@link MDC} correctly.
   */
  public static <T> void executeBlocking(Vertx vertx, Handler<Future<T>> future, boolean ordered,
                                         Handler<AsyncResult<T>> handler) {
    Map mdc = MDC.getCopyOfContextMap();

    vertx.<T>executeBlocking(f -> {
      try {
        if (mdc != null) {
          MDC.setContextMap(mdc);
        }
        future.handle(f);
      } finally {
        MDC.clear();
      }
    }, ordered, h -> {
      try {
        if (mdc != null) {
          MDC.setContextMap(mdc);
        }
        handler.handle(h);
      } finally {
        MDC.clear();
      }
    });
  }

  /**
   * Equivalent to {@link Vertx#executeBlocking(Handler, Handler)},
   * but preserves the {@link MDC} correctly.
   */
  public static <T> void executeBlocking(WorkerExecutor executor, Handler<Future<T>> future, Handler<AsyncResult<T>> handler) {
    executeBlocking(executor, future, true, handler);
  }

  /**
   * Equivalent to {@link Vertx#executeBlocking(Handler, boolean, Handler)},
   * but preserves the {@link MDC} correctly.
   */
  public static <T> void executeBlocking(WorkerExecutor executor, Handler<Future<T>> future, boolean ordered,
                                         Handler<AsyncResult<T>> handler) {
    Map mdc = MDC.getCopyOfContextMap();

    executor.<T>executeBlocking(f -> {
      try {
        if (mdc != null) {
          MDC.setContextMap(mdc);
        }
        future.handle(f);
      } finally {
        MDC.clear();
      }
    }, ordered, h -> {
      try {
        if (mdc != null) {
          MDC.setContextMap(mdc);
        }
        handler.handle(h);
      } finally {
        MDC.clear();
      }
    });
  }
}

@@ -484,16 +484,736 @@
 xUtil %7B%0A
+  /**%0A   * Wrap a Handler in a way that will preserve the SLF4J MDC context.%0A   * The context from the current thread at the time of this method call%0A   * will be cached and restored within the wrapper at the time the%0A   * handler is invoked.%0A   */%0A  public static %3CT%3E Handler%3CT%3E mdc(Handler%3CT%3E handler) %7B%0A    Map mdc = MDC.getCopyOfContextMap();%0A%0A    return t -%3E %7B%0A      Map restore = MDC.getCopyOfContextMap();%0A      try %7B%0A        if (mdc == null) %7B%0A          MDC.clear();%0A        %7D else %7B%0A          MDC.setContextMap(mdc);%0A        %7D%0A        handler.handle(t);%0A      %7D finally %7B%0A        if (restore == null) %7B%0A          MDC.clear();%0A        %7D else %7B%0A          MDC.setContextMap(restore);%0A        %7D%0A      %7D%0A    %7D;%0A  %7D%0A%0A
   /**%0A  
@@ -1270,32 +1270,32 @@
 ler, Handler)%7D,%0A
-
    * but preserv
@@ -1815,50 +1815,8 @@
 ) %7B%0A
-    Map mdc = MDC.getCopyOfContextMap();%0A%0A
     
@@ -1821,19 +1821,16 @@
   vertx.
-%3CT%3E
 executeB
@@ -1841,356 +1841,42 @@
 ing(
-f -%3E %7B%0A      try %7B%0A        if (mdc != null) %7B%0A          MDC.setContextMap(mdc);%0A        %7D%0A        future.handle(f);%0A      %7D finally %7B%0A        MDC.clear();%0A      %7D%0A    %7D, ordered, h -%3E %7B%0A      try %7B%0A        if (mdc != null) %7B%0A          MDC.setContextMap(mdc);%0A        %7D%0A        handler.handle(h);%0A      %7D finally %7B%0A        MDC.clear();%0A      %7D%0A    %7D
+mdc(future), ordered, mdc(handler)
 );%0A 
@@ -2517,50 +2517,8 @@
 ) %7B%0A
-    Map mdc = MDC.getCopyOfContextMap();%0A%0A
     
@@ -2526,19 +2526,16 @@
 xecutor.
-%3CT%3E
 executeB
@@ -2546,356 +2546,42 @@
 ing(
-f -%3E %7B%0A      try %7B%0A        if (mdc != null) %7B%0A          MDC.setContextMap(mdc);%0A        %7D%0A        future.handle(f);%0A      %7D finally %7B%0A        MDC.clear();%0A      %7D%0A    %7D, ordered, h -%3E %7B%0A      try %7B%0A        if (mdc != null) %7B%0A          MDC.setContextMap(mdc);%0A        %7D%0A        handler.handle(h);%0A      %7D finally %7B%0A        MDC.clear();%0A      %7D%0A    %7D
+mdc(future), ordered, mdc(handler)
 );%0A 

Make MDC handling in Vert.x more robust