Mark total results for cache in case of timeout - fixes #84
Change-Id: I7bad5a3c5df7332f5375c4027cffe67128a3b118
diff --git a/Changes b/Changes
index 1e739b2..a30f6bb 100755
--- a/Changes
+++ b/Changes
@@ -9,6 +9,7 @@
"Leibniz Institute for the German Language".
- Fixed "next"-character in paginations.
- Added new IDS logo.
+ - Fix timeout cache (#84).
0.31 2018-11-30
- Update to Mojolicious >= 8.06.
diff --git a/lib/Kalamar/Controller/Search.pm b/lib/Kalamar/Controller/Search.pm
index ea6edb8..04f9b0d 100644
--- a/lib/Kalamar/Controller/Search.pm
+++ b/lib/Kalamar/Controller/Search.pm
@@ -5,8 +5,6 @@
use Mojo::Util qw/quote/;
use POSIX 'ceil';
-has no_cache => 0;
-
has items_per_page => 25;
# TODO:
@@ -109,7 +107,7 @@
# Check if total results information is cached
my $total_results = -1;
- if (!$cutoff && !$c->no_cache) {
+ if (!$cutoff && !$c->stash('no_cache')) {
# Create cache string
my $user = $c->user_handle;
@@ -124,6 +122,11 @@
# Set stash if cache exists
if (defined $total_results) {
+
+ if ($total_results =~ s/^!//) {
+ $c->stash(time_exceeded => 1);
+ };
+
$c->stash(total_results => $total_results);
$c->app->log->debug('Get total result from cache: ' . $total_results);
@@ -153,7 +156,8 @@
unless (defined $total_results) {
# There are results to remember
- if (!$cutoff && $json->{meta}->{totalResults} >= 0) {
+ if (!$cutoff &&
+ $json->{meta}->{totalResults} >= 0) {
# Remove cutoff requirement again
# $url->query([cutoff => 'true']);
@@ -164,7 +168,9 @@
$c->app->log->debug('Set for total results: ' . $total_cache_str);
# Set cache
- $c->chi->set($total_cache_str => $total_results);
+ $c->chi->set(
+ $total_cache_str => ($json->{meta}->{timeExceeded} ? '!' : '') . $total_results
+ );
}
# Undefined total results
diff --git a/lib/Kalamar/Plugin/KalamarErrors.pm b/lib/Kalamar/Plugin/KalamarErrors.pm
index 2c897fc..9a8d9d8 100644
--- a/lib/Kalamar/Plugin/KalamarErrors.pm
+++ b/lib/Kalamar/Plugin/KalamarErrors.pm
@@ -46,7 +46,7 @@
$mojo->helper(
notify_on_warnings => sub {
my ($c, $json) = @_;
- return _notify($c, $json, 'warnings', 'warning');
+ return _notify($c, $json, 'warnings', 'warn');
}
);
@@ -79,7 +79,7 @@
if (!$json && !$err) {
$c->notify(error => 'JSON response is invalid');
- return; # Mojo::Promise->new->reject;
+ return;
};
# There is json
@@ -91,7 +91,7 @@
if ($c->notify_on_errors($json)) {
# Return on errors - ignore warnings
- return;# Mojo::Promise->new->reject;
+ return;
};
# Notify on warnings
@@ -101,7 +101,7 @@
if ($json->{status}) {
$c->notify(error => 'Middleware error ' . $json->{'status'});
- return;# Mojo::Promise->new->reject;
+ return;
};
}
@@ -110,7 +110,7 @@
# Send rejection promise
$c->notify(error => $err->{code} . ': ' . $err->{message});
- return; #Mojo::Promise->new->reject;
+ return;
};
return $json;
diff --git a/lib/Kalamar/Plugin/KalamarHelpers.pm b/lib/Kalamar/Plugin/KalamarHelpers.pm
index 3edced7..a85f2ae 100644
--- a/lib/Kalamar/Plugin/KalamarHelpers.pm
+++ b/lib/Kalamar/Plugin/KalamarHelpers.pm
@@ -311,7 +311,7 @@
$c->stash(api_request => $url->to_string);
# No cache request
- if ($c->no_cache) {
+ if ($c->stash('no_cache')) {
return $c->korap_request($method => $url)->then(
sub {
diff --git a/lib/Kalamar/Plugin/KalamarUser.pm b/lib/Kalamar/Plugin/KalamarUser.pm
index d0340e8..83c5fe2 100644
--- a/lib/Kalamar/Plugin/KalamarUser.pm
+++ b/lib/Kalamar/Plugin/KalamarUser.pm
@@ -29,7 +29,7 @@
# Set API!
$plugin->api($param->{api}) or return;
$plugin->ua(Mojo::UserAgent->new(
- connect_timeout => 15,
+ connect_timeout => 90,
inactivity_timeout => 120,
max_redirects => 3
));
diff --git a/t/fixtures/response_query_timeout_o0_c25.json b/t/fixtures/response_query_timeout_o0_c25.json
new file mode 100644
index 0000000..691acb5
--- /dev/null
+++ b/t/fixtures/response_query_timeout_o0_c25.json
@@ -0,0 +1,83 @@
+{
+ "status" : 200,
+ "json" : {
+ "@context" : "http://korap.ids-mannheim.de/ns/KoralQuery/v0.3/context.jsonld",
+ "meta" : {
+ "count" : 25,
+ "startIndex" : 0,
+ "authorized" : null,
+ "context" : {
+ "left" : ["token",40],
+ "right" : ["token",40]
+ },
+ "fields" : ["pubDate","subTitle","author","pubPlace","title","textSigle","UID","ID","layerInfos","corpusSigle","docSigle","corpusID","textClass"],
+ "version" : "0.55.7",
+ "benchmark" : "0.120577834 s",
+ "serialQuery" : "tokens:s:Baum",
+ "itemsPerPage" : 25,
+ "timeExceeded": true,
+ "timeout": 10000,
+ "totalResults": 4274841
+ },
+ "warnings": [
+ [
+ 682,
+ "Response time exceeded"
+ ]
+ ],
+ "query" : {
+ "@type" : "koral:token",
+ "wrap" : {
+ "@type" : "koral:term",
+ "layer" : "orth",
+ "key" : "Baum",
+ "match" : "match:eq",
+ "foundry" : "opennlp",
+ "rewrites" : [
+ {
+ "@type" : "koral:rewrite",
+ "src" : "Kustvakt",
+ "operation" : "operation:injection",
+ "scope" : "foundry"
+ }
+ ]
+ }
+ },
+ "matches" : [
+ {
+ "field" : "tokens",
+ "pubPlace" : "München",
+ "textSigle" : "GOE/AGI/00000",
+ "docSigle" : "GOE/AGI",
+ "corpusSigle" : "GOE",
+ "title" : "Italienische Reise",
+ "subTitle" : "Auch ich in Arkadien!",
+ "author" : "Goethe, Johann Wolfgang von",
+ "layerInfos" : "base/s=spans corenlp/c=spans corenlp/p=tokens corenlp/s=spans dereko/s=spans malt/d=rels mdp/d=rels opennlp/p=tokens opennlp/s=spans tt/l=tokens tt/p=tokens tt/s=spans",
+ "startMore" : true,
+ "endMore" : true,
+ "snippet" : "<span class=\"context-left\"><span class=\"more\"></span>sie etwas bedeuten zu wollen und machte mit der Oberlippe eine fatale Miene. ich sprach sehr viel mit ihr durch, sie war überall zu Hause und merkte gut auf die Gegenstände. so fragte sie mich einmal, was das für ein </span><span class=\"match\"><mark>Baum</mark></span><span class=\"context-right\"> sei. es war ein schöner großer Ahorn, der erste, der mir auf der ganzen Reise zu Gesichte kam. den hatte sie doch gleich bemerkt und freute sich, da mehrere nach und nach erschienen, daß sie auch diesen Baum unterscheiden könne<span class=\"more\"></span></span>",
+ "matchID" : "match-GOE/AGI/00000-p2030-2031",
+ "UID" : 0,
+ "pubDate" : "1982"
+ },
+ {
+ "field" : "tokens",
+ "pubPlace" : "München",
+ "textSigle" : "GOE/AGI/00001",
+ "docSigle" : "GOE/AGI",
+ "corpusSigle" : "GOE",
+ "title" : "Italienische Reise",
+ "subTitle" : "Auch ich in Arkadien!",
+ "author" : "Goethe, Johann Wolfgang von",
+ "layerInfos" : "base/s=spans corenlp/c=spans corenlp/p=tokens corenlp/s=spans dereko/s=spans malt/d=rels mdp/d=rels opennlp/p=tokens opennlp/s=spans tt/l=tokens tt/p=tokens tt/s=spans",
+ "startMore" : true,
+ "endMore" : true,
+ "snippet" : "<span class=\"context-left\"><span class=\"more\"></span>für ein Baum sei. es war ein schöner großer Ahorn, der erste, der mir auf der ganzen Reise zu Gesichte kam. den hatte sie doch gleich bemerkt und freute sich, da mehrere nach und nach erschienen, daß sie auch diesen </span><span class=\"match\"><mark>Baum</mark></span><span class=\"context-right\"> unterscheiden könne. sie gehe, sagte sie, nach Bozen auf die Messe, wo ich doch wahrscheinlich auch hinzöge. wenn sie mich dort anträfe, müsse ich ihr einen Jahrmarkt kaufen, welches ich ihr denn auch versprach. dort wollte sie auch ihre neue<span class=\"more\"></span></span>",
+ "matchID" : "match-GOE/AGI/00000-p2068-2069",
+ "UID" : 0,
+ "pubDate" : "1982"
+ }
+ ]
+ }
+}
diff --git a/t/fixtures/response_query_timeout_o0_c25_cotrue.json b/t/fixtures/response_query_timeout_o0_c25_cotrue.json
new file mode 100644
index 0000000..661622c
--- /dev/null
+++ b/t/fixtures/response_query_timeout_o0_c25_cotrue.json
@@ -0,0 +1,74 @@
+{
+ "status" : 200,
+ "json" : {
+ "@context" : "http://korap.ids-mannheim.de/ns/KoralQuery/v0.3/context.jsonld",
+ "meta" : {
+ "count" : 25,
+ "startIndex" : 0,
+ "authorized" : null,
+ "context" : {
+ "left" : ["token",40],
+ "right" : ["token",40]
+ },
+ "fields" : ["pubDate","subTitle","author","pubPlace","title","textSigle","UID","ID","layerInfos","corpusSigle","docSigle","corpusID","textClass"],
+ "version" : "0.55.7",
+ "benchmark" : "0.120577834 s",
+ "serialQuery" : "tokens:s:Baum",
+ "itemsPerPage" : 25
+ },
+ "query" : {
+ "@type" : "koral:token",
+ "wrap" : {
+ "@type" : "koral:term",
+ "layer" : "orth",
+ "key" : "Baum",
+ "match" : "match:eq",
+ "foundry" : "opennlp",
+ "rewrites" : [
+ {
+ "@type" : "koral:rewrite",
+ "src" : "Kustvakt",
+ "operation" : "operation:injection",
+ "scope" : "foundry"
+ }
+ ]
+ }
+ },
+ "matches" : [
+ {
+ "field" : "tokens",
+ "pubPlace" : "München",
+ "textSigle" : "GOE/AGI/00000",
+ "docSigle" : "GOE/AGI",
+ "corpusSigle" : "GOE",
+ "title" : "Italienische Reise",
+ "subTitle" : "Auch ich in Arkadien!",
+ "author" : "Goethe, Johann Wolfgang von",
+ "layerInfos" : "base/s=spans corenlp/c=spans corenlp/p=tokens corenlp/s=spans dereko/s=spans malt/d=rels mdp/d=rels opennlp/p=tokens opennlp/s=spans tt/l=tokens tt/p=tokens tt/s=spans",
+ "startMore" : true,
+ "endMore" : true,
+ "snippet" : "<span class=\"context-left\"><span class=\"more\"></span>sie etwas bedeuten zu wollen und machte mit der Oberlippe eine fatale Miene. ich sprach sehr viel mit ihr durch, sie war überall zu Hause und merkte gut auf die Gegenstände. so fragte sie mich einmal, was das für ein </span><span class=\"match\"><mark>Baum</mark></span><span class=\"context-right\"> sei. es war ein schöner großer Ahorn, der erste, der mir auf der ganzen Reise zu Gesichte kam. den hatte sie doch gleich bemerkt und freute sich, da mehrere nach und nach erschienen, daß sie auch diesen Baum unterscheiden könne<span class=\"more\"></span></span>",
+ "matchID" : "match-GOE/AGI/00000-p2030-2031",
+ "UID" : 0,
+ "pubDate" : "1982"
+ },
+ {
+ "field" : "tokens",
+ "pubPlace" : "München",
+ "textSigle" : "GOE/AGI/00001",
+ "docSigle" : "GOE/AGI",
+ "corpusSigle" : "GOE",
+ "title" : "Italienische Reise",
+ "subTitle" : "Auch ich in Arkadien!",
+ "author" : "Goethe, Johann Wolfgang von",
+ "layerInfos" : "base/s=spans corenlp/c=spans corenlp/p=tokens corenlp/s=spans dereko/s=spans malt/d=rels mdp/d=rels opennlp/p=tokens opennlp/s=spans tt/l=tokens tt/p=tokens tt/s=spans",
+ "startMore" : true,
+ "endMore" : true,
+ "snippet" : "<span class=\"context-left\"><span class=\"more\"></span>für ein Baum sei. es war ein schöner großer Ahorn, der erste, der mir auf der ganzen Reise zu Gesichte kam. den hatte sie doch gleich bemerkt und freute sich, da mehrere nach und nach erschienen, daß sie auch diesen </span><span class=\"match\"><mark>Baum</mark></span><span class=\"context-right\"> unterscheiden könne. sie gehe, sagte sie, nach Bozen auf die Messe, wo ich doch wahrscheinlich auch hinzöge. wenn sie mich dort anträfe, müsse ich ihr einen Jahrmarkt kaufen, welches ich ihr denn auch versprach. dort wollte sie auch ihre neue<span class=\"more\"></span></span>",
+ "matchID" : "match-GOE/AGI/00000-p2068-2069",
+ "UID" : 0,
+ "pubDate" : "1982"
+ }
+ ]
+ }
+}
diff --git a/t/match_info.t b/t/match_info.t
index 5d23887..59f12ed 100644
--- a/t/match_info.t
+++ b/t/match_info.t
@@ -78,7 +78,7 @@
$t->get_ok('/corpus/brokenwarn/X/X/p0-1')
->status_is(200)
- ->json_is('/notifications/0/0', 'warning')
+ ->json_is('/notifications/0/0', 'warn')
->json_is('/notifications/0/1', '1: Warning 1')
->json_is('/notifications/1/0', 'error')
->json_is('/notifications/1/1', 'Message structure failed')
diff --git a/t/query.t b/t/query.t
index b1ae3bb..2ce7a90 100644
--- a/t/query.t
+++ b/t/query.t
@@ -209,6 +209,20 @@
->text_like('noscript div.notify-error', qr!Parameter ".+?" invalid!)
;
+# Query with timeout
+$t->get_ok('/?q=timeout')
+ ->status_is(200)
+ ->text_like('noscript div.notify-warn', qr!Response time exceeded!)
+ ->text_is('#total-results', '> 4,274,841');
+;
+
+# Do not cache
+$t->get_ok('/?q=timeout')
+ ->status_is(200)
+ # ->text_like('noscript div.notify-warning', qr!Response time exceeded!)
+ ->text_is('#total-results', '> 4,274,841');
+ ;
+
done_testing;
__END__
diff --git a/t/server/mock.pl b/t/server/mock.pl
index 79eeb90..31cfaca 100644
--- a/t/server/mock.pl
+++ b/t/server/mock.pl
@@ -48,7 +48,17 @@
};
my $response = $file->slurp;
- return decode_json($response);
+ my $decode = decode_json($response);
+ unless ($decode) {
+ return {
+ status => 500,
+ json => {
+ errors => [[0, 'Unable to parse JSON']]
+ }
+ }
+ };
+
+ return $decode;
};