1

プロパティに基づいてジョブを動的にスケジュールするアプリケーションがあります。ServiceReadyEvent をリッスンしてから、ジョブをスケジュールします。以下は、ファクトリを介してコンテキストに追加される小さな例です。

class JobsLoader(
    @param:Named(TaskExecutors.SCHEDULED) val taskScheduler: TaskScheduler,
    val myJobName: String
) : ApplicationEventListener<ServiceReadyEvent> {

    override fun onApplicationEvent(event: ServiceReadyEvent?) {
        taskScheduler.schedule("* * * * *", ()  -> println("running job $jobName"))
    }
}

このコードをテストするために、kotest を使用して Micronaut テストを行いました。

@MicronautTest
class Job1Spec(
        @param:Named(TaskExecutors.SCHEDULED) val taskScheduler: TaskScheduler
) {

    init {

        "start job loader" {
            val jobsLoader = JobsLoader("job1", taskScheduler)
            jobsLoader.onApplicationEvent(ServiceReadyEvent(ServiceInstance.of("test", URL("http://localhost:8080"))))
        }

        "verify the job runs" {
            //code here to verify the job ran and performed the correct calls
        }

    }   
}

他の仕事の二次試験もあります

@MicronautTest
class Job2Spec(
        @param:Named(TaskExecutors.SCHEDULED) val taskScheduler: TaskScheduler
) {

    init {

        "start job loader" {
            val jobsLoader = JobsLoader("job2", taskScheduler)
            jobsLoader.onApplicationEvent(ServiceReadyEvent(ServiceInstance.of("test", URL("http://localhost:8080"))))
        }

        "verify the job runs" {
            //code here to verify the job ran and performed the correct calls
        }

    }   
}

私の問題は、2 番目のテスト中に、2 番目のテストの実行中に最初のジョブがまだスケジュールされていることを確認することです。

[INFO] 2020-09-10 12:57:00,005 pool-2-thread-1 running job job1
[INFO] 2020-09-10 12:57:00,009 pool-4-thread-1 running job job2 

ジョブの実行を除いて、テストの最初の実行に関する他のすべてが停止しました。ジョブの実行中に HttpClient が閉じられたために例外がスローされるため、まだ実行されていることがわかりました。

私はもう試した

  • テスト間のテスト コンテキストの再構築rebuildContext = true
  • クラスでスケジュールされた先物を追跡JobsLoaderし、関数でそれらをキャンセルしafterSpecます。先物のリストは、私がそれらをキャンセルするまでには常に空です。
  • TaskScheduler および ExecutorService Bean を手動で更新する

テストはすべて問題なくパスしますが、例外が散らばっています。特に、ますます多くのジョブをテストするようになり、テストしているジョブ以外はすべて失敗し続けています。これが kotest、micronaut テスト、スケジューラ、いくつかの組み合わせ、またはまったく別の問題であるかどうかはわかりません (vertx ログも表示されますが、それは問題ではないと思います)。次のテストを実行する前に、これらのジョブ/スレッドを強制終了する方法を見つけ出す必要があります。

どんな助けやアイデアも大歓迎です!

4

1 に答える 1

1

そのため、すべてを入力した後、私の問題が何であるかがすぐにわかりました. テストでジョブを手動で作成していますが、これは micronaut コンテキストの一部ではないため、ジョブをキャンセルしようとすると、将来のリストが常に空になります。

ジョブをロードしてコンテキストに追加するようにテストを変更しました。

var jobsLoader: JobsLoader? = null

    override fun beforeSpec(spec: Spec) {
        jobsLoader = JobsLoader(taskScheduler, getJobsConfiguration(), jobResolver, eventPublisher)
        jobsLoader?.onApplicationEvent(ServiceReadyEvent(ServiceInstance.of("test", URL("http://localhost:8080"))))
        super.beforeSpec(spec)
    }

    override fun afterSpec(spec: Spec) {
        jobsLoader?.stopJobs()
        super.afterSpec(spec)
    }

次に、ジョブローダーにジョブをキャンセルする機能を提供しました。

class JobsLoader(
    @param:Named(TaskExecutors.SCHEDULED) val taskScheduler: TaskScheduler,
    val myJobName: String
) : ApplicationEventListener<ServiceReadyEvent> {

    private val scheduledJobs = mutableListOf<ScheduledFuture<*>>()

    override fun onApplicationEvent(event: ServiceReadyEvent?) {
        val scheduledFuture = taskScheduler.schedule("* * * * *", ()  -> println("running job $jobName"))
        scheduledJobs.add(scheduledFuture)
    }

    fun stopJobs() {
        scheduledJobs.forEach { it.cancel(false) }
    }
}
于 2020-09-10T18:50:24.863 に答える