code: public <T> void transactAsync(final DbCodeTypedTx<T> code, Handler<AsyncResult<T>> resultHandler) {
      VertxUtil.executeBlocking(executor, future -> {
        try {
          T returnValue = null;
          Transaction tx = new TransactionImpl();
          tx.setRollbackOnError(true);
          tx.setRollbackOnly(false);
          boolean complete = false;
          try {
            returnValue = code.run(this, tx);
            complete = true;
          } catch (ThreadDeath | DatabaseException t) {
            throw t;
          } catch (Throwable t) {
            throw new DatabaseException("Error during transaction", t);
          } finally {
            if ((!complete && tx.isRollbackOnError()) || tx.isRollbackOnly()) {
              rollbackAndClose();
            } else {
              commitAndClose();
            }
          }
          future.complete(returnValue);
        } catch (ThreadDeath t) {
          throw t;
        } catch (Throwable t) {
          future.fail(t);
        }
      }, resultHandler);
    }
docs: Execute a transaction on a Vert.x worker thread, with default semantics (commit if
  the code completes successfully, or rollback if it throws an error). The provided
  result handler will be call after the commit or rollback, and will run on the event
  loop thread (the same thread that is calling this method).