2016-01-05 36 views
3

在playframework中緩存未來結果的正確方法是什麼?例如: -Cache.getOrElse on Futures in Playframework

val userGravatar: Future[JsValue] = RemoteGravatarService.get(user.id, user.email) 

object RemoveGravatarService { 
    def get(userId: String, email: String): Future[JsValue] = { 
    Cache.getOrElse("gravatar-for-$userId", 1.hour) { 
     WS.url("gravatar.com/email=$email").get().asJson 
    } 
    } 
} 

我們不想問(這個虛構的)「的Gravatar」每一次,因爲它不會改變頻繁。但我們經常需要本地的som userGravatar信息。

這裏我們緩存未來本身,但實際上我們只想緩存未來的結果。有沒有一種方便/正確的方法來實現這一點?

+0

任何類型的,但讓我們說'JsValue'(因爲它是可序列化)。更新了類型註釋的示例。這裏重要的是,如果緩存中的值已準備就緒,我希望緩存響應'Future.successful(previousJsonResult)'。 – kornfridge

+0

你可以使用噴霧緩存 –

回答

6

Play的API中沒有處理Future的方法。你可以打包Play的緩存API來處理orElse的情況,它會返回Future。一般:

object FutureCache { 

    def getOrElse[A](key: String, expiration: Int)(orElse: => Future[A]) 
     (implicit app: Application, ct: ClassTag[A], ec: ExecutionContext): Future[A] = { 
     Cache.getAs[A](key).map(Future.successful).getOrElse { 
      val value = orElse 
      value onSuccess { case result => Cache.set(key, result, expiration) } 
      value 
     } 
    } 

} 

用法:

FutureCache.getOrElse[JsValue]("gravatar-for-$userId", 3600) { 
    WS.url("gravatar.com/email=$email").get().map(_.json) 
} 

你也可以爲使用DurationgetOrElse創造過載。

0

你可以使用一個無極[JsValue],這樣的事情:

val userGravatar: Future[JsValue] = RemoteGravatarService.get(user.id, user.email) 

object RemoveGravatarService { 
    def get(userId: String, email: String): Future[JsValue] = { 
    Cache.getOrElse("gravatar-for-$userId", 1.hour) { 
     Promise[JsValue].completeWith(WS.url("gravatar.com/email=$email").get().map(_.json) 
    }.future 
    } 
}