@SuppressWarnings({"checkstyle:NPathComplexity", "checkstyle:CyclomaticComplexity"})
  @Override
  public void shutdown() {
    log.info("ksqlDB shutdown called");

    try {
      pullQueryMetrics.ifPresent(PullQueryExecutorMetrics::close);
    } catch (final Exception e) {
      log.error("Exception while waiting for pull query metrics to close", e);
    }

    try {
      scalablePushQueryMetrics.ifPresent(ScalablePushQueryMetrics::close);
    } catch (final Exception e) {
      log.error("Exception while waiting for scalable push query metrics to close", e);
    }

    localCommands.ifPresent(lc -> {
      try {
        lc.close();
      } catch (final Exception e) {
        log.error("Exception while closing local commands", e);
      }
    });

    try {
      ksqlEngine.close();
    } catch (final Exception e) {
      log.error("Exception while waiting for Ksql Engine to close", e);
    }

    try {
      commandRunner.close();
    } catch (final Exception e) {
      log.error("Exception while waiting for CommandRunner thread to complete", e);
    }

    try {
      serviceContext.close();
    } catch (final Exception e) {
      log.error("Exception while closing services", e);
    }

    try {
      securityExtension.close();
    } catch (final Exception e) {
      log.error("Exception while closing security extension", e);
    }

    if (apiServer != null) {
      apiServer.stop();
      apiServer = null;
    }

    if (vertx != null) {
      try {
        final CountDownLatch latch = new CountDownLatch(1);
        vertx.close(ar -> latch.countDown());
        latch.await();
      } catch (InterruptedException e) {
        log.error("Exception while closing vertx", e);
      }
    }

    if (oldApiWebsocketExecutor != null) {
      oldApiWebsocketExecutor.shutdown();
    }

    shutdownAdditionalAgents();

    log.info("ksqlDB shutdown complete");
  }
@Test
  public void shouldCloseSecurityExtensionOnClose() {
    // When:
    app.shutdown();

    // Then:
    verify(securityExtension).close();
  }