Ich habe so etwas wie das Folgende für das Zwischenspeichern von JSON-Antworten in Redis für eine Scala-Anwendung mit http4s, Argonaut und Slick, und möchte bestätigen, dass es funktioniert, wie ich es erwarte. Die Idee ist, wenn ein Redis key
nicht gefunden wurde, dann rufen Sie die gegebenen fallback
Methode die Daten von der ursprünglichen Quelle (MySQL) und für zukünftige Anfragen cachen zu bekommen, sonst überspringen MySQL:ruft eine Zukunft Methodenparameter „by-name“ notwendig?
/** Get from MySQL */
def getThingsFromDatabase(matchingId: Int): Future[Seq[Thing]] = {
println("getThingsFromDatabase")
val query = things.filter(_.fieldId === matchingId)
db.run(query.result)
}
/** Get from Redis, else MySQL via `fallback` */
def getThingsFromRedisOrDatabase(key: String,
fallback: Future[Seq[Thing]]):
Future[argonaut.Json] = {
val stored = redis.get(key)
stored match {
// Data exists, return from redis
case Some(s) => {
Parse.parse(s) match { // convert string to Json
case Right(r) => Future { r } // Json => Future[argonaut.Json]
case Left(l) => println(l) // error
}
}
// Data does not exist, get from database and store
case None() => {
val data = fallback.map(_.toList.asJson)
data map { redis.set(key, _) }
data // Future[argonaut.Json]
}
}
}
// GET /things/12
Ok(getThingsFromRedisOrDatabase("things:12", getThingsFromDatabase(12)))
Dies funktioniert jedoch der obige Code druckt „getThingsFromDatabase“ immer unabhängig davon, ob oder nicht es gibt Daten in Redis weil getThingsFromDatabase(12)
, wenn sie als Parameter aufgerufen ausführt. Die ursprüngliche Datenbank scheint nicht wie beabsichtigt mit Daten in Redis (ohne Fehler beim Herunterfahren) betroffen zu sein. Ich denke, das liegt daran, dass die fallback
Zukunft ist in diesem Szenario nicht verwendet wird, so dass es auch dann nicht abschließt, obwohl die Methode ausgeführt wurde.
Wenn fallback: Future[Seq[Thing]]
geändert Call-by-Namen (dh fallback: => Future[Seq[Thing]]
), „getThingsFromDatabase“ nur beim ersten Mal gedruckt, wenn der Cache leer ist, wie erwartet, da fallback
heißt nur in dem None()
Zustand und nicht ausgeführt als ein Parameter.
Während letzteres die beabsichtigte Funktionalität ist, würde es einen Unterschied zwischen der ursprünglichen und der Call-by-Name-Version geben, wenn es keine println
in der getThingsFromDatabase
Methode gibt? Beide scheinen die Notwendigkeit nicht gehen zu MySQL zu treffen, wenn Redis die gewünschten Daten hat, weder tatsächlich die Zukunft abgeschlossen, obwohl das erstere das Verfahren ausführt.