summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBirte Kristina Friesel <derf@finalrewind.org>2024-09-28 13:42:49 +0200
committerBirte Kristina Friesel <derf@finalrewind.org>2024-09-28 13:42:49 +0200
commit248b692492c466a06aa0a7c9afb69137a7fc6200 (patch)
tree77988c1db7df52780d1a8ee3822d4e4d355d38eb
parent5c26e3b6a426343e2b3f852311fe0028ab7d75b8 (diff)
Cache efa replies by default
-rwxr-xr-xbin/efa-m19
-rw-r--r--lib/Travel/Status/DE/EFA.pm116
2 files changed, 121 insertions, 14 deletions
diff --git a/bin/efa-m b/bin/efa-m
index d788932..eb78069 100755
--- a/bin/efa-m
+++ b/bin/efa-m
@@ -16,6 +16,8 @@ use Travel::Status::DE::EFA;
my $service = 'VRR';
my $efa_url;
my $efa_encoding;
+my $use_cache = 1;
+my $cache;
my ( $date, $time, $input_type, $list_lines, $offset, $relative_times );
my ( $full_routes, $filter_via, $show_jid );
my ( $timeout, $developer_mode );
@@ -54,6 +56,7 @@ GetOptions(
'u|efa-url=s' => \$efa_url,
'v|via=s' => \$filter_via,
'V|track-via=s' => \$filter_via,
+ 'cache!' => \$use_cache,
'version' => \&show_version,
'devmode' => \$developer_mode,
@@ -67,6 +70,21 @@ if ( @ARGV < 1 or @ARGV > 2 ) {
show_help(1);
}
+if ($use_cache) {
+ my $cache_path = ( $ENV{XDG_CACHE_HOME} // "$ENV{HOME}/.cache" ) . '/efa-m';
+ eval {
+ require Cache::File;
+ $cache = Cache::File->new(
+ cache_root => $cache_path,
+ default_expires => '90 seconds',
+ lock_level => Cache::File::LOCK_LOCAL(),
+ );
+ };
+ if ($@) {
+ $cache = undef;
+ }
+}
+
# --line=foo,bar support
@edata_pre = split( qr{,}, join( q{,}, @edata_pre ) );
@grep_lines = split( qr{,}, join( q{,}, @grep_lines ) );
@@ -130,6 +148,7 @@ sub new_efa {
my $res = Travel::Status::DE::EFA->new(
service => $s,
efa_url => $u,
+ cache => $cache,
date => $date,
developer_mode => $developer_mode,
efa_encoding => $efa_encoding,
diff --git a/lib/Travel/Status/DE/EFA.pm b/lib/Travel/Status/DE/EFA.pm
index 6aa505b..75caf8e 100644
--- a/lib/Travel/Status/DE/EFA.pm
+++ b/lib/Travel/Status/DE/EFA.pm
@@ -32,17 +32,9 @@ sub new_p {
$self->{promise} = $opt{promise};
- $self->{ua}->post_p( $self->{efa_url} => form => $self->{post} )->then(
+ $self->post_with_cache_p->then(
sub {
- my ($tx) = @_;
- if ( my $err = $tx->error ) {
- $promise->reject(
-"POST $self->{efa_url} returned HTTP $err->{code} $err->{message}"
- );
- return;
- }
- my $content = $tx->res->body;
-
+ my ($content) = @_;
$self->{response} = $self->{json}->decode($content);
if ( $self->{developer_mode} ) {
@@ -149,6 +141,7 @@ sub new {
}
my $self = {
+ cache => $opt{cache},
response => $opt{from_json},
developer_mode => $opt{developer_mode},
efa_url => $opt{efa_url},
@@ -218,6 +211,13 @@ sub new {
$self->{ua}->env_proxy;
}
+ if ( $self->{cache} ) {
+ $self->{cache_key}
+ = $self->{efa_url} . '?'
+ . join( '&',
+ map { $_ . '=' . $self->{post}{$_} } sort keys %{ $self->{post} } );
+ }
+
if ( $opt{async} ) {
return $self;
}
@@ -230,14 +230,14 @@ sub new {
}
if ( not $self->{response} ) {
- my $response = $self->{ua}->post( $self->{efa_url}, $self->{post} );
+ my ( $response, $error ) = $self->post_with_cache;
- if ( $response->is_error ) {
- $self->{errstr} = $response->status_line;
+ if ($error) {
+ $self->{errstr} = $error;
return $self;
}
- $self->{response} = $self->{json}->decode( $response->content );
+ $self->{response} = $self->{json}->decode($response);
}
if ( $self->{developer_mode} ) {
@@ -249,6 +249,94 @@ sub new {
return $self;
}
+sub post_with_cache {
+ my ($self) = @_;
+ my $cache = $self->{cache};
+ my $url = $self->{efa_url};
+
+ if ( $self->{developer_mode} ) {
+ say 'POST ' . ( $self->{cache_key} // $url );
+ }
+
+ if ($cache) {
+ my $content = $cache->thaw( $self->{cache_key} );
+ if ($content) {
+ if ( $self->{developer_mode} ) {
+ say ' cache hit';
+ }
+ return ( ${$content}, undef );
+ }
+ }
+
+ if ( $self->{developer_mode} ) {
+ say ' cache miss';
+ }
+
+ my $reply = $self->{ua}->post( $url, $self->{post} );
+
+ if ( $reply->is_error ) {
+ return ( undef, $reply->status_line );
+ }
+ my $content = $reply->content;
+
+ if ($cache) {
+ $cache->freeze( $self->{cache_key}, \$content );
+ }
+
+ return ( $content, undef );
+}
+
+sub post_with_cache_p {
+ my ($self) = @_;
+ my $cache = $self->{cache};
+ my $url = $self->{efa_url};
+
+ if ( $self->{developer_mode} ) {
+ say 'POST ' . ( $self->{cache_key} // $url );
+ }
+
+ my $promise = $self->{promise}->new;
+
+ if ($cache) {
+ my $content = $cache->thaw( $self->{cache_key} );
+ if ($content) {
+ if ( $self->{developer_mode} ) {
+ say ' cache hit';
+ }
+ return $promise->resolve( ${$content} );
+ }
+ }
+
+ if ( $self->{developer_mode} ) {
+ say ' cache miss';
+ }
+
+ $self->{ua}->post_p( $url, form => $self->{post} )->then(
+ sub {
+ my ($tx) = @_;
+ if ( my $err = $tx->error ) {
+ $promise->reject(
+ "POST $url returned HTTP $err->{code} $err->{message}");
+ return;
+ }
+ my $content = $tx->res->body;
+ if ($cache) {
+ $cache->freeze( $self->{cache_key}, \$content );
+ }
+ $promise->resolve($content);
+ return;
+ }
+ )->catch(
+ sub {
+ my ($err) = @_;
+ $promise->reject($err);
+ return;
+ }
+ )->wait;
+
+ return $promise;
+}
+
sub errstr {
my ($self) = @_;