Let cache hash depend on x-index-revision http header from welcome call

This way RKorAPClient is informed about corpus and other index changes
and makes sure that no stale cache query results are used.

Change-Id: I508c17c4f9b0d5974de4d28f40f3d101d6d41c82
diff --git a/NEWS.md b/NEWS.md
index 226cc67..930b2ff 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -1,5 +1,8 @@
 # RKorAPClient 0.5.8.9001
 
+## Changes
+- A hash for the last index revision is queried on every new connection, making sure that no stale cache results are re-used.
+
 # RKorAPClient 0.5.8
 
 ## Changes
diff --git a/R/KorAPConnection.R b/R/KorAPConnection.R
index 9808f88..8d5a366 100644
--- a/R/KorAPConnection.R
+++ b/R/KorAPConnection.R
@@ -12,7 +12,7 @@
 #' @import utils
 #' @import methods
 #' @export
-KorAPConnection <- setClass("KorAPConnection", slots=c(KorAPUrl="character", apiVersion="character", apiUrl="character", accessToken="characterOrNULL", userAgent="character", timeout="numeric", verbose="logical", cache="logical"))
+KorAPConnection <- setClass("KorAPConnection", slots=c(KorAPUrl="character", apiVersion="character", indexRevision="characterOrNULL", apiUrl="character", accessToken="characterOrNULL", userAgent="character", timeout="numeric", verbose="logical", cache="logical"))
 
 #' @param .Object KorAPConnection object
 #' @param KorAPUrl the URL of the KorAP server instance you want to access.
@@ -78,7 +78,9 @@
             .Object@timeout = timeout
             .Object@verbose = verbose
             .Object@cache = cache
-            message(apiCall(.Object, .Object@apiUrl, json = FALSE, cache = FALSE))
+            welcome <- apiCall(.Object, .Object@apiUrl, json = FALSE, cache = FALSE, getHeaders = TRUE)
+            message(welcome[[2]])
+            .Object@indexRevision <- welcome[[1]][["x-index-revision"]]
             .Object
           })
 
@@ -153,12 +155,13 @@
 #' @param kco KorAPConnection object
 #' @param url request url
 #' @param json logical that determines if json result is expected
+#' @param getHeaders logical that determines if headers and content should be returned (as a list)
 #' @importFrom jsonlite fromJSON
 #' @export
-setMethod("apiCall", "KorAPConnection",  function(kco, url, json = TRUE, cache = kco@cache) {
+setMethod("apiCall", "KorAPConnection",  function(kco, url, json = TRUE, getHeaders = FALSE, cache = kco@cache) {
   result <- ""
   if (cache) {
-    result <- R.cache::loadCache(dir=KorAPCacheSubDir(), key=list(url, kco@accessToken))
+    result <- R.cache::loadCache(dir=KorAPCacheSubDir(), key=list(url, kco@accessToken, kco@indexRevision))
     if (!is.null(result)) {
       if (!is.null(result$meta))
         result$meta$cached <- "local"
@@ -196,9 +199,13 @@
     result <- content(resp, "text", encoding = "UTF-8")
   }
   if (cache) {
-    R.cache::saveCache(result, key = list(url, kco@accessToken), dir = KorAPCacheSubDir(), compress = TRUE)
+    R.cache::saveCache(result, key = list(url, kco@accessToken, kco@indexRevision), dir = KorAPCacheSubDir(), compress = TRUE)
   }
-  result
+  if (getHeaders) {
+    list(httr::headers(resp), result)
+  } else {
+    result
+  }
 })
 
 setGeneric("clearCache", function(kco)  standardGeneric("clearCache") )
diff --git a/man/KorAPConnection-class.Rd b/man/KorAPConnection-class.Rd
index 6b3f4fd..73e0a6e 100644
--- a/man/KorAPConnection-class.Rd
+++ b/man/KorAPConnection-class.Rd
@@ -32,7 +32,7 @@
 
 \S4method{clearAccessToken}{KorAPConnection}(kco)
 
-\S4method{apiCall}{KorAPConnection}(kco, url, json = TRUE, cache = kco@cache)
+\S4method{apiCall}{KorAPConnection}(kco, url, json = TRUE, getHeaders = FALSE, cache = kco@cache)
 
 \S4method{clearCache}{KorAPConnection}(kco)
 
@@ -80,6 +80,8 @@
 
 \item{json}{logical that determines if json result is expected}
 
+\item{getHeaders}{logical that determines if headers and content should be returned (as a list)}
+
 \item{object}{KorAPConnection object}
 }
 \value{
diff --git a/tests/testthat/test-corpusQuery.R b/tests/testthat/test-corpusQuery.R
index ab97765..5f84fab 100644
--- a/tests/testthat/test-corpusQuery.R
+++ b/tests/testthat/test-corpusQuery.R
@@ -1,3 +1,18 @@
+test_that("frequencyQuery can be cached", {
+  kco <- new("KorAPConnection", cache = TRUE, verbose = TRUE)
+  frequencyQuery(kco, "Ameisenplage", "pubDate since 2014")
+  expect_output(frequencyQuery(kco, "Ameisenplage", "pubDate since 2014"), "cached")
+})
+
+test_that("Cache depends on indexRevision (handling also NULL values)", {
+  kco <- new("KorAPConnection", cache = TRUE, verbose = TRUE)
+  kco@indexRevision <- NULL
+  frequencyQuery(kco, "Ameisenplage", "pubDate since 2014")
+  kco@indexRevision <- as.character(Sys.time())
+  expect_output(frequencyQuery(kco, "Ameisenplage", "pubDate since 2014"), "took [0-9.]+ s")
+  expect_output(frequencyQuery(kco, "Ameisenplage", "pubDate since 2014"), "cached")
+})
+
 test_that("corpusQuery returns results", {
   q <- new("KorAPConnection") %>%
     corpusQuery("Ameisenplage")