0

실행하기에 너무 긴 PUT 요청이 있습니다. 나는 그것을 비동기로 만들고, continuations (await/promise 기능)을 사용하고 싶다. 내가 작업을 생성 (LongJobThatUpdatesThePassedEntity은) 즉, DB 트랜잭션 관리 어떻게 내 개체playframework 1.2.x :/async 및 JPA 트랜잭션 대기

public static void myLongPut(@required Long id, String someData) { 
     MyJpaModel myJpaModel = MyJpaModel.findById(id); 

     //straightforward modifications 
     updateMyJpaModel(someData); 
     myJpaModel.save(); 

     //long processing modifications to entity, involving WS calls 
     Promise<String> delayedResult = new LongJobThatUpdatesThePassedEntity(id).now(); 

     await(delayedResult); 

     render(myJpaModel.refresh()); 

    } 

수정?

작업 호출 전에 커밋이 있습니까?

작업에 자체 DB 트랜잭션이 있습니까?

LongJobThatUpdatesThePassedEntity 롤백에 문제가있는 경우 updateMyJpaModel에서 수행 된 수정이 유지됩니까?

마지막으로 render(myJpaModel.refresh())을 할 수 있습니까? 스트롱 포워드 수정과 긴 수정을 포함 할 예정입니까?

감사의

답변

1

내가 현재 사용하고 버전입니다 플레이 1.4.3에 대한 질문의 대부분을 응답 할 수 있습니다. Play 1.2부터 많은 변화가있을 것으로 기대하지는 않습니다.

DB 트랜잭션은 어떻게 관리됩니까?

Play! Play 관련 개념 인 "호출"을 사용하여 작업 및 컨트롤러 작업에 대한 트랜잭션을 처리합니다. 요컨대 모든 호출에 대해 각 플러그인은 호출 된 메소드가 실행되기 전후에 일부 설정 및 정리를 수행 할 수있는 기회를 얻습니다. 데이터베이스 액세스의 경우 JPAPlugin.withinFilter 메소드는 JPA 클래스의 도우미 메소드를 사용하여 트랜잭션을 시작하고 종료합니다.

작업 호출 전에 커밋이 있습니까?

await(Future<T>)으로 전화하면 현재 트랜잭션을 닫고 새 트랜잭션을 시작합니다. 특정 메커니즘은 PlayHandler$NettyInvocation으로 바뀌고 afterInvocation 콜백이 호출되는 "일시 중단"예외를 발생시킵니다. 이로 인해 JPAPlugin.afterInvocationJPA.closeTx()으로 전화를 걸어 트랜잭션을 커밋하거나 롤백합니다.

작업이 종료되고 await() 계속이 다시 시작될 때. 이것은 호출로도 처리되므로 JPAPlugin.withinFilter()을 사용하여 이전과 같은 방식으로 트랜잭션이 시작됩니다. 그러나 이전과 달리 컨트롤러 작업은 호출 대상이 아니며 ActionInvoker.invoke()invokeWithContinuation을 호출하여 저장된 연속 상태를 복원하고 await()에서 돌아가 실행을 다시 시작합니다.

JPA.withTransaction에는 연속 일시 중단/다시 시작에 걸쳐 동일한 엔티티 관리자를 유지하는 특수 논리가있는 것처럼 보입니다. 나는 이것이 없으면 refresh()를 호출 할 수 없을 것이라고 생각한다.

코드에서 트랜잭션 (transaction)을 닫고 트랜잭션 (transaction)를 시작하는 사이에 경쟁 조건이 있다고 생각합니다. 즉, 컨트롤러가 "before await"트랜잭션을 커밋하기 전에 작업의 트랜잭션이 시작될 수 있습니다. 이를 방지하려면 Job.now()에 전화하기 전에 JPA.closeTx()으로 명시 적으로 전화 할 수 있습니다.

코드 검사를 기준으로 볼 때 Play! 가 구현되면 작업이 종료되고 "after await()"트랜잭션이 열리기 전에 작업의 트랜잭션이 닫힙니다. 이 내용이 await() 계약의 의도 된 부분이라고 말하는 설명서가 있는지 여부를 알 수 없으므로이 경우 응용 프로그램에 필수적이라면 Job.doJobWithResult() 메서드가 반환되기 바로 전에 트랜잭션을 커밋하여 문서화되지 않은 동작을 사용하지 않아도됩니다.

작업에 자체 DB 트랜잭션이 있습니까?

예, 주석이 달린 트랜잭션이없는 경우는 예외입니다.

RollJback이라는 LongJobThatUpdatesThePassedEntity에 문제가있는 경우 updateMyJpaModel에서 수행 된 수정이 지속됩니까?

위의 설명에 따르면, 각각의 세 거래는 독립적입니다. 하나가 롤백되면, 나는 그것이 다른 사람들에게 어떻게 영향을 미치는지 보지 못한다.

+0

완료되었습니다. 마침내 .refresh()를 사용하지 않고 대신 Model.findById()를 호출합니다. –