2017-11-06 7 views
1

클러스터에서 샤딩을 사용하여 akka의 PersistentActor를 사용하여 내 상태를 추적합니다.akka persist 함수가 매번 처리되지 않음

case UpdateRoom(id, room, userId) => ((ret: ActorRef) => { 
    (userRegion ? GetRoleForRoom(userId, id)).mapTo[String] map { role => 
    if (role == "owner") { 
     state = Some(room) 
     ret ! Success(room) 
     eventRegion ! RoomEventPackage(id, RoomUpdated(room)) 
     println("works") 
     persist(RoomUpdated(room))(e => println("this doesn't always fire") 
    } else { 
     ret ! Failure(InsufficientRights(role, "Update Room")) 
    } 
    } 

문제가 예상대로 함수의 나머지가 작동하는 동안 만 다른 모든 시간을 작동 영속화 즉 : 나는 내가 다음 코드를 통해 업데이트 할 수있는 '룸'이있다. ("작품"은 매번 인쇄되고, "항상 발사되는 것은 아닙니다"격차없이 두 번씩). 이벤트를 저장하기 위해 항상 업데이트 명령을 두 번 실행해야하지만 두 번 명령 저장을 위해 저장된 것처럼 보입니다.

akka persist의 중요한 부분이 누락 되었습니까?

답변

1

나는 외부에서 배우 (변경 가능) 상태에 액세스하는 Actor의 세계에서 심각한 실수를 저지르고 있다고 생각합니다. 귀하의 경우,이 ask/?에 의해 반환 된 Future의 콜백 내에서 두 번 발생합니다

  • 업데이트 상태 : state = Some(room)
  • persist

를 처리 할 수있는 유일한 안전한 방법을 호출 Actor에서 물어 본 후 액터의 상태를 수정하면 ask의 콜백에서 같은 액터에게 메시지를 보내고 그 끝에는 pipeTo을 사용할 수 있습니다. 설명하기 위해 코드의 단순화 된 버전을 사용

:

case UpdateRoom(id, room, userId) => 
    val answer = (userRegion ? GetRoleForRoom(userId, id)).mapTo[String] map(role => RoleForRoom(id, room, userId, role)) 
    answer piepTo self 
case RoleForRoom(id, room, userId, room) => 
    if (role == "owner") { 
    state = Some(room) 
    eventRegion ! RoomEventPackage(id, RoomUpdated(room)) 
    persist(RoomUpdated(room))(e => println("this is safe")) 
    } 

도 참조 : https://doc.akka.io/docs/akka/2.5.6/scala/general/jmm.html#actors-and-shared-mutable-state