Playframework + Akka:如何避免执行关闭应用程序时执行的计划任务

Al-*_*far 3 java akka playframework playframework-2.5

我在播放应用程序服务器启动时启动的调度程序有问题,但是一旦应用程序关闭,它就会命中以下代码部分:

// firstDay something like 1 = monday 
private void startScheduler(final ImageService imageService,
                            final ActorSystem system) {
    startImagesCleanupScheduler(imageService, system);
    Logger.info("Schedulers started");
}
Run Code Online (Sandbox Code Playgroud)

我的问题是该Runnable块立即开始执行,而不仅仅是取消任务。

澄清代码:

以下方法启动Scheduler

private void startImagesCleanupScheduler(ImageService imageService, ActorSystem system) {
    system.scheduler().schedule(
            Duration.create(0, TimeUnit.MILLISECONDS), //Initial delay
            Duration.create(1, TimeUnit.DAYS),     //Frequency 1 days
            () -> {
                int rows = imageService.cleanupInactiveImages();
                Logger.info(String.format("%d inactive unused images cleaned from db", rows));

            },
            system.dispatcher()
    );
}
Run Code Online (Sandbox Code Playgroud)

我关机时的日志记录第一行:

[info] - application - 1 inactive unused images cleaned from db
[info] - application - Shutting down connection pool.
[info] - application - Creating Pool for datasource 'default'
...
[info] - application - Schedulers started
[info] - play.api.Play - Application started (Prod)
Run Code Online (Sandbox Code Playgroud)

你可以看到它执行了调度器,忽略了它原来的执行时间,然后关闭,然后启动,然后“调度器启动”。

什么问题,我如何取消调度程序或阻止播放在关机前运行它?这是 Akka 的错误吗?

我打电话给startScheduler里面OnStartup就像以下问题的答案:

弃用 onStart 的 java Playframework GlobalSettings

编辑: 以下是重现问题的最小代码:

首先创建OnStartup类:

@Singleton
public class OnStartup {

    @Inject
    public OnStartup(final ActorSystem system) {
        startScheduler(system);
    }

    private void startScheduler(final ActorSystem system) {
        startImagesCleanupScheduler(system);
        Logger.info("Schedulers started");
    }

    private void startImagesCleanupScheduler(ActorSystem system) {
        system.scheduler().schedule(
                Duration.create(0, TimeUnit.MILLISECONDS), //Initial delay
                Duration.create(1, TimeUnit.DAYS),     //Frequency 1 days
                () -> {
                    //int rows = imageService.cleanupInactiveImages();
                    rows = 1;
                    Logger.info(String.format("%d inactive unused images cleaned from db", rows ));
                },
                system.dispatcher()
        );
    }

}
Run Code Online (Sandbox Code Playgroud)

然后创建模块:

public class OnStartupModule extends AbstractModule {
    @Override
    public void configure() {
        bind(OnStartup.class).asEagerSingleton();
    }
}
Run Code Online (Sandbox Code Playgroud)

最后在 application.conf 中启用模块:

play.modules.enabled += "modules.OnStartupModule"
Run Code Online (Sandbox Code Playgroud)

Ale*_*vic 5

这对于评论来说有点太长了,但我没有测试这种方法,你可能需要调整它。文档说这些组件以它们创建的相反顺序被销毁。这意味着您可能会在ActorSystem关闭之前取消您的调度程序,因为这个类是在它之后注册的并且依赖于它。在您的OnStartup班级中创建一个像这样的关闭挂钩,您将在其中取消您的日程安排。这意味着在ActorSystem关闭时,将没有计划执行:

@Singleton
public class OnStartup {

    private final Cancellable cancellableSchedule;

    @Inject
    public OnStartup(final ActorSystem system, final ApplicationLifecycle l) {
        cancellableSchedule = startScheduler(system);
        initStopHook(l);
    }

    private Cancellable startScheduler(final ActorSystem system) {
        return startImagesCleanupScheduler(system);
        Logger.info("Schedulers started");
    }

    private Cancellable startImagesCleanupScheduler(ActorSystem system) {
        return system.scheduler().schedule(
            Duration.create(0, TimeUnit.MILLISECONDS), //Initial delay
            Duration.create(1, TimeUnit.DAYS),     //Frequency 1 days
            () -> {
                //int rows = imageService.cleanupInactiveImages();
                rows = 1;
                Logger.info(String.format("%d inactive unused images cleaned from db", rows ));
                },
            system.dispatcher()
        );
    }

    private void initStopHook(ApplicationLifecycle lifecycle) {
       lifecycle.addStopHook(() -> {
            cancellableSchedule.cancel();
        return CompletableFuture.completedFuture(null);
        });
     }

}
Run Code Online (Sandbox Code Playgroud)