2

EDIT
チャッキング(例外のスロー)を開始すると、キャッシュする「悪い」データはありません。例外をキャッチすることで、Either[Why-Fail, Option[T]] にラップされていたとしても、自分の作業が増えるだけでした。例外は(理想的には)例外的であるため、ログに記録し、スローし、先に進みます...

ORIGINAL
キャッシングは良いが、失敗した操作のキャッシングは悪い

Cache.orElse("directory.active") {
  Ok( dao.findAll(active = true) as json )
}

DAO データベースのルックアップが失敗する可能性があり (この場合、データベース/クエリの失敗で空のリストが返されます)、結果として不正なデータがキャッシュされます。

これを回避するには?クエリを 1 回だけ実行し、その後のリクエストのためにキャッシュします。Scala では遅延初期化を行うことができますが、それは永続的なキャッシュを作成することになり、これも望ましくありません (メンバー ディレクトリの追加/編集時にキャッシュをクリアする必要があります)。

これがどのプラットフォームにも当てはまると仮定します。基本的には、操作を 1 回実行し、成功した結果をキャッシュする必要があります。

4

2 に答える 2

1

私はキャッシュの実装を手元に持っていないので、これをテストできませんでしたが、次のようなものはどうですか:

def getCache[A](key:String, result:()=>A)(invalidTest:A=>Boolean):Option[A] = {
  Cache.get(key).getOrElse {
    result match {
      case m:A if (!invalidTest(m)) => Cache.set(key,m);Some(m)
      case _ => None
    }
  }
}

getCache("directory.active", () => dao.findAll(active = true))(_.isEmpty)

あなたが言ったように、キャッシュに入れているタイプのデフォルトの有効性テストを使用して、これを追加するために Cache を簡単にポンピングできます。

代わりに Action の結果をキャッシュしたい場合 (そして、常に json を返している場合、およびas jsonタイプ Json を返す場合 -- 残念ながら、Play の担当者ではありません)、多分:

def getCache[A](key:String, result:()=>A)(invalidTest:A=>Boolean):SimpleResult[Json] = {
  Cache.get(key).getOrElse {
    result match {
      case m:A if (!invalidTest(m)) => Cache.set(key,Ok(m as json));Ok(m as json)
      case x:A => Ok(x as json)
      case _ => Ok(errorjson as json)
    }
  }
}

getCache("directory.active", () => dao.findAll(active = true))(_.isEmpty)
于 2012-07-13T22:07:43.200 に答える
0

@brandon のおかげで、私は Play のCache 実装のケーキと食べ過ぎの売春斡旋を思いつきました

def orElse[A,B](key: String, expire: Int = 0)
  (canFail: => B)(failOn: B => Boolean)(body: B => A)
  (implicit m: ClassManifest[A]): A = {

  PlayCache.getAs[A](key).getOrElse {
    canFail match {
      case x if(!failOn(x)) => // all good, cache away
        val tmp = body(x); set(key, tmp, expire); tmp
      case x => body(x) // never cache a failure
    }
  }
}

そして次のように使用します:

Cache.orElse("directory.active")(dao.findAll(active = true))(_.isEmpty) { 
  model=> Ok( directory.index(model) )
}

これにより、失敗する可能性のある操作を選択的にキャッシュすると同時に、canFail 操作が挿入される html ラッパーをキャッシュする機能を保持することができます。この特定のケースでは、findAll クエリは @400 メンバー レコードを返し、html レイヤー (150KB 生成) に jQuery DataTable を生成するため、操作全体をキャッシュすることが望ましいです。

于 2012-07-13T15:55:55.933 に答える