在启动生命周期中优雅地退出 quarkus

Gracefully exiting quarkus during startup lifecycle

relevant zulip chat

我想弄清楚在 quarkus 中应用程序启动期间应该如何优雅地失败。

  1. 我尝试将其添加到应用程序启动代码中。如果我 运行 其中一个单元测试,现在不会调用它。只有在我直接启动应用程序时才会调用它。我希望 return 一个非零值来反对抛出异常。这可能是推荐的方法。我不确定。
    public class MyApp implements QuarkusApplication {

        @Override
        public int run(String... args) throws Exception {
            System.out.println("Do startup logic here");
            Quarkus.waitForExit();
            return 0;
        }
  1. 我还尝试从 onStart 生命周期事件中引发异常。但似乎 quarkus 一直在继续执行
   void onStart(@Observes StartupEvent ev) {               
        LOGGER.info("The application is starting...");
    }

    void onStop(@Observes ShutdownEvent ev) {               
        LOGGER.info("The application is stopping...");
    }

我不确定这是功能请求还是错误,或者我遗漏了什么,这是正常行为。

编辑1: 明确一点:

@Startup
@ApplicationScoped
public class StarterBean {
    private static final Logger LOGGER = Logger.getLogger("");

    public StarterBean() {
        throw new RuntimeException("failed misrably");
    }
}

当我 运行 使用“./gradlew quarkusDev` 时,我在控制台中看到异常,但该应用程序从未存在。我认为它应该存在。它确实在单元测试期间退出并且正确失败。我尝试在 onStart 中移动异常,但这也没有帮助。我还尝试了 Startup、ApplicationScoped 或两者的组合

编辑 2:

我通过构建 uber jar 并 运行 对其进行了测试。引发异常会退出应用程序。同样可以想象,当 运行 在 docker 容器中时,应用程序也会退出。我很困惑为什么 gradle 任务从来不存在。所以为此我想我会接受答案。非常感谢您的帮助!

我不确定这里是否有满足所有要求的 nice 答案(如果我错了,很高兴得到纠正。)不确定你到底想做什么实现,但有一些可能值得探索的选项:

  • Quarkus.asyncExit(code) 在您的 run() 方法中将允许您正常退出,但这不会被单元测试调用。
  • 您可以在启动时初始化一个在其构造函数中抛出异常的 bean(用 @Startup 注释),但这不是特别优雅并且不会让您控制状态代码。然而,它似乎 return -1,所以它至少满足非零退出代码的标准。 (遗憾的是 Quarkus.asyncExit(code) 似乎不适用于单元测试,即使它是在测试开始之前的 bean 初始化中执行的。)
  • 同上,但是你可以在bean构造函数中调用System.exit()。这使您可以控制退出代码,但这是最不干净的方法,它只是将 VM 拉走而没有任何优雅的清理机会。

编辑:刚刚从 zulipchat 线程看到了这个,它添加了一些必要的上下文:

I need to be able to bail out during startup if i see certain conditions (for example missing env variables or whatever) how am i supposed to do it ?

在这种情况下,我可能会声明一个 @Startup bean(或多个 bean)以基于这些环境变量进行初始化,并确保这些 bean 的构造函数在条件不正确时抛出有意义的异常(缺少 env 变量、损坏的 env 变量等)这有几个优点:

  • 您可以将适当的启动检查分成不同的 bean,强制分离责任;
  • 您有有意义的信息可以在日志中进行分析和操作;
  • 如果由于抛出该异常而出现错误,您可以使用非零退出代码有意义地停止,从而允许容器运行状况检查系统报告节点已严重死亡。