액터모델에는 타이머를 탑재해 반복 스케쥴 이벤트를 실행할수 있습니다. 

함수를 즉각 실행 시키는것이 아닌, 자기자신에게 메시지를 추가해 액터가 가진 동일한 메일함을 이용하기때문에 동시 중복실행이 일어나지 않는 특징을 가지고 있습니다.


코드생성 프롬프트

10초에 한번씩 HelloCount를 0으로 초기화하는 이벤트를 생성하고 싶습니다. 타이머 컨셉을 적용해 모델을 개선


변경되는 코드 범위

object ResetHelloCount : HelloStateActorCommand()

/** HelloStateActor 클래스 */
class HelloStateActor private constructor(
    private val context: ActorContext<HelloStateActorCommand>,
    private val timers: TimerScheduler<HelloStateActorCommand>,
    private var state: State
) : AbstractBehavior<HelloStateActorCommand>(context) {

    companion object {
        fun create(initialState: State): Behavior<HelloStateActorCommand> {
            return Behaviors.withTimers { timers ->
                Behaviors.setup { context -> HelloStateActor(context, timers, initialState) }
            }
        }
    }

    init {
        timers.startTimerAtFixedRate(ResetHelloCount, Duration.ofSeconds(10))
    }

    private fun onResetHelloCount(command: ResetHelloCount): Behavior<HelloStateActorCommand> {
        helloCount = 0
        return this
    }


TimerScheduler<HelloStateActorCommand>는 Akka Typed에서 제공하는 타이머 기능을 사용하기 위한 인터페이스입니다. 이 인터페이스를 사용하면 주기적으로 또는 일정 시간 후에 특정 메시지를 액터에게 전송할 수 있습니다. 이를 통해 시간 기반 이벤트를 처리할 수 있습니다.  

주요 메서드:  

  • startTimerAtFixedRate: 주기적으로 메시지를 전송합니다.
  • startSingleTimer: 한 번만 메시지를 전송합니다.
  • cancel: 특정 타이머를 취소합니다.


추가되는 테스트 코드

    @Test
    fun testResetHelloCount() {
        val probe = testKit.createTestProbe<Any>()
        val helloStateActor = testKit.spawn(HelloStateActor.create(State.HAPPY))

        // Send Hello messages
        helloStateActor.tell(Hello("Hello", probe.ref()))
        helloStateActor.tell(Hello("Hello", probe.ref()))

        probe.expectMessage(HelloResponse("Kotlin"))
        probe.expectMessage(HelloResponse("Kotlin"))

        // Verify the hello count
        helloStateActor.tell(GetHelloCount(probe.ref()))
        probe.expectMessage(HelloCountResponse(2))

        // Wait for the timer to reset the count
        Thread.sleep(Duration.ofSeconds(11).toMillis())

        // Verify the hello count is reset
        helloStateActor.tell(GetHelloCount(probe.ref()))
        probe.expectMessage(HelloCountResponse(0))
    }
  • 10초 뒤에 HelloCount 가 초기화되는지 검증합니다.


개선되는 컨셉

10초 뒤에 작동하는 기능을 검증하기위해 10초를 기달리는 것이아닌~ 액터 테스트 시스템에 발생하는 시간을 가상으로 진행시킬수 있습니다.

이 테스트 기능을 도입함에 따라~ 시간이 흘러 발생하는 다양한 시나리오 테스트 수행이 가능해지며 유닛테스트 검증 시간을 단축화할수 있습니다.


TestKit에 ManualTime 주입

import akka.actor.testkit.typed.javadsl.ActorTestKit
import akka.actor.testkit.typed.javadsl.ManualTime
import com.typesafe.config.ConfigFactory
import org.junit.jupiter.api.AfterAll
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.Test
import java.time.Duration

class HelloStateActorTest {

    companion object {
        private lateinit var testKit: ActorTestKit
        private lateinit var manualTime: ManualTime

        @BeforeAll
        @JvmStatic
        fun setup() {
            val config = ManualTime.config().withFallback(ConfigFactory.defaultApplication())
            testKit = ActorTestKit.create(config)
            manualTime = ManualTime.get(testKit.system())
        }

....


timePasses를 통해 시간을 흘러가게하기

        // Advance the time by 5 seconds
        manualTime.timePasses(Duration.ofSeconds(5))
        helloStateActor.tell(GetHelloCount(probe.ref()))

        probe.expectMessage(HelloCountResponse(2))

        // Advance the time by 6 seconds
        manualTime.timePasses(Duration.ofSeconds(6))
        // Verify the hello count is reset
        helloStateActor.tell(GetHelloCount(probe.ref()))

        probe.expectMessage(HelloCountResponse(0))

  • TimerScheduler 와 호환되어~ 시간이 흘러가면 해당 이벤트가 임의 발생합니다.
  • 10초에 Reset을 하기때문에  6초~ 5초 를 각각 흘러가게해 수신카운트를 검증할수 있습니다.


테스트결과

액터내에 메시지함에서 시간이 흘러간것을 검증 할때 유용하게 이용할수 있습니다.

20:14:22.717 [HelloStateActorTest-akka.actor.default-dispatcher-5] INFO  actor.hellostate.HelloStateActor - onHello-Kotlin
20:14:22.717 [HelloStateActorTest-akka.actor.default-dispatcher-5] INFO  actor.hellostate.HelloStateActor - onHello-Kotlin
20:14:22.719 [HelloStateActorTest-akka.actor.default-dispatcher-2] INFO  actor.hellostate.HelloStateActor - onGetHelloCount-helloCount: 2
20:14:22.832 [HelloStateActorTest-akka.actor.default-dispatcher-7] INFO  actor.hellostate.HelloStateActor - onGetHelloCount-helloCount: 2
20:14:22.934 [HelloStateActorTest-akka.actor.default-dispatcher-7] INFO  actor.hellostate.HelloStateActor - Resetting hello count
20:14:22.936 [HelloStateActorTest-akka.actor.default-dispatcher-7] INFO  actor.hellostate.HelloStateActor - onGetHelloCount-helloCount: 0
20:14:22.958 [HelloStateActorTest-akka.actor.default-dispatcher-7] INFO  akka.actor.CoordinatedShutdown - Running CoordinatedShutdown with reason [ActorSystemTerminateReason]
> Task :test
BUILD SUCCESSFUL in 3s

git : https://github.com/psmon/java-labs/blob/master/KotlinBootLabs/src/main/kotlin/actor/hellostate/HelloStateActor.kt


next : 불규칙적으로 발생하는 이벤트를 배치처리가 아닌 준실시간(Near RealTime) 으로 고성능으로 Bulk처리하는방법




  • No labels