2012-07-17 31 views
13

Trong ứng dụng Play Framework 2.0.1 (Scala), chúng tôi đang sử dụng thư viện máy khách dịch vụ web trả về java.util.concurrent.Future làm câu trả lời.Làm thế nào để bọc một java.util.concurrent.Future trong tương lai của Akka?

Thay vì ngăn chặn các ứng dụng Play trên get() cuộc gọi, chúng tôi muốn quấn j.u.c.Future trong một akka.dispatch.Future, để chúng ta có thể dễ dàng sử dụng chế biến AsyncResult khuôn khổ chơi của.

Có ai đã thực hiện việc này trước đây hoặc có thư viện hoặc mã mẫu không?


CẬP NHẬT: Điều gần nhất chúng tôi nhận thấy là thế này thảo luận nhóm google: https://groups.google.com/forum/#!topic/play-framework/c4DOOtGF50c

... nếu tất cả các bạn có là một jucFuture đơn giản là tốt nhất bạn có thể làm để tạo ra một giải pháp không chặn là lấy jucFuture và Promise, và cung cấp cho họ một số luồng chạy vòng lặp bỏ phiếu sẽ hoàn thành Lời hứa với kết quả của Tương lai khi nó được thực hiện.

Có ai có triển khai ví dụ này không?

Trả lời

7

@Viktor Klang: Chúng tôi hiểu rằng j.u.c.Future là một sự ghê tởm. Nhưng đó là những gì chúng tôi đang nhận được từ một phần của phần mềm, chúng tôi phải chấp nhận như được đưa ra trong thời gian này.

Cho đến nay, đây là những gì chúng tôi đã bị hack với nhau:

def wrapJavaFutureInAkkaFuture[T](javaFuture: java.util.concurrent.Future[T], maybeTimeout: Option[Duration] = None)(implicit system: ActorSystem): akka.dispatch.Future[T] = { 
    val promise = new akka.dispatch.DefaultPromise[T] 
    pollJavaFutureUntilDoneOrCancelled(javaFuture, promise, maybeTimeout.map(_.fromNow)) 
    promise 
} 

Nói cách khác, tạo ra một Akka riêng Promise (write-side của một Future) tương ứng với j.u.c.Future, đá ra khỏi callback pollJavaFutureUntilDoneOrCancelled để cập nhật Lời hứa bằng cách bỏ phiếu "hủy bỏ" và trả lại Lời hứa cho người gọi.

Vậy làm cách nào để chúng tôi "thăm dò ý kiến" cập nhật lời hứa Akka dựa trên trạng thái của j.u.c.Future?

def pollJavaFutureUntilDoneOrCancelled[T](javaFuture: java.util.concurrent.Future[T], promise: akka.dispatch.Promise[T], maybeDeadline: Option[Deadline] = None)(implicit system: ActorSystem) { 
    if (maybeDeadline.exists(_.isOverdue)) javaFuture.cancel(true); 

    if (javaFuture.isDone || javaFuture.isCancelled) { 
    promise.complete(allCatch either { javaFuture.get }) 
    } else { 
    Play.maybeApplication.foreach { implicit app => 
     system.scheduler.scheduleOnce(50 milliseconds) { 
     pollJavaFutureUntilDoneOrCancelled(javaFuture, promise, maybeDeadline) 
     } 
    } 
    } 
} 

Đây là nỗ lực được đề cập trong thảo luận nhóm trên google mà tôi đã tham chiếu trong câu hỏi. Nó sử dụng bộ lập lịch Akka để tự gọi lại sau mỗi 50 ms để kiểm tra xem j.u.c.Future có được thực hiện hay hủy bỏ hay không. Bất cứ khi nào điều đó xảy ra, nó cập nhật lời hứa Akka với trạng thái hoàn thành.

@Victor Klang, et al:

Đây có phải là phương pháp hay nhất này không? Bạn có biết cách tốt hơn để làm điều này không? Có phải chúng ta đang thiếu một nhược điểm ở đây mà chúng ta nên biết?

Cảm ơn bạn đã trợ giúp thêm.

+0

Một nhược điểm rõ ràng là, trong trường hợp xấu nhất này sẽ gây ra một sự chậm trễ cao của phản ứng. Ví dụ: nếu bạn có cài đặt mặc định và tương lai của bạn hoàn thành sau 1 giây sau khi kiểm tra, nó có thể gây ra sự chậm trễ khoảng 100ms. Tuy nhiên, điều này có thể được điều chỉnh bằng cách thiết lập 'scheduler.cài đặt thời gian đánh dấu trong cấu hình. – drexin

+0

@drexin đúng, nhưng thời gian đánh dấu và cân bằng tần suất thăm dò ý kiến ​​sẽ có mặt trong bất kỳ giải pháp dựa trên bỏ phiếu nào, đúng không? –

+1

Chắc chắn, nhưng khi bạn yêu cầu các nhược điểm, tôi chỉ muốn nói với bạn rằng nó không chỉ phụ thuộc vào tham số trễ của cuộc gọi 'scheduleOnce', mà còn phụ thuộc vào thiết lập trong cấu hình akka. Nếu bạn có thể sống với một sự chậm trễ này nên là một giải pháp có thể sử dụng. – drexin

0

Bạn nên sử dụng akka.dispatch.Futures.future() với java.util.concurrent.Callable:

val akkaFuture: akka.dispatch.Future[String] = akka.dispatch.Futures.future(
    new java.util.concurrent.Callable[String] { 
    def call: String = { 
     return "scala->" + javaFuture.get 
    } 
}, executionContext) 

Gist for complete example

+0

Điều này về cơ bản dẫn đến nhiều chủ đề hơn cần thiết, một trong số đó chặn và không tốt hơn chỉ đơn giản gọi javaFuture.get trên chuỗi chính. Giới thiệu tương lai akka là không có lợi ở đây ngoại trừ trong những tình huống khắc nghiệt mà tính tương thích thành phần là hoàn toàn cần thiết. – vishr

Các vấn đề liên quan