mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
Better cache
This commit is contained in:
parent
7219c90957
commit
cba1213dd1
@ -29,6 +29,7 @@ use FireflyIII\Exceptions\FireflyException;
|
|||||||
use FireflyIII\Models\CurrencyExchangeRate;
|
use FireflyIII\Models\CurrencyExchangeRate;
|
||||||
use FireflyIII\Models\TransactionCurrency;
|
use FireflyIII\Models\TransactionCurrency;
|
||||||
use FireflyIII\Support\CacheProperties;
|
use FireflyIII\Support\CacheProperties;
|
||||||
|
use Illuminate\Support\Facades\Cache;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -49,9 +50,9 @@ class ExchangeRateConverter
|
|||||||
public function convert(TransactionCurrency $from, TransactionCurrency $to, Carbon $date, string $amount): string
|
public function convert(TransactionCurrency $from, TransactionCurrency $to, Carbon $date, string $amount): string
|
||||||
{
|
{
|
||||||
if (false === config('cer.enabled')) {
|
if (false === config('cer.enabled')) {
|
||||||
|
Log::debug('ExchangeRateConverter: disabled, return amount as is.');
|
||||||
return $amount;
|
return $amount;
|
||||||
}
|
}
|
||||||
Log::debug('convert()');
|
|
||||||
$rate = $this->getCurrencyRate($from, $to, $date);
|
$rate = $this->getCurrencyRate($from, $to, $date);
|
||||||
|
|
||||||
return bcmul($amount, $rate);
|
return bcmul($amount, $rate);
|
||||||
@ -63,9 +64,9 @@ class ExchangeRateConverter
|
|||||||
public function getCurrencyRate(TransactionCurrency $from, TransactionCurrency $to, Carbon $date): string
|
public function getCurrencyRate(TransactionCurrency $from, TransactionCurrency $to, Carbon $date): string
|
||||||
{
|
{
|
||||||
if (false === config('cer.enabled')) {
|
if (false === config('cer.enabled')) {
|
||||||
|
Log::debug('ExchangeRateConverter: disabled, return "1".');
|
||||||
return '1';
|
return '1';
|
||||||
}
|
}
|
||||||
Log::debug('getCurrencyRate()');
|
|
||||||
$rate = $this->getRate($from, $to, $date);
|
$rate = $this->getRate($from, $to, $date);
|
||||||
|
|
||||||
return '0' === $rate ? '1' : $rate;
|
return '0' === $rate ? '1' : $rate;
|
||||||
@ -76,25 +77,33 @@ class ExchangeRateConverter
|
|||||||
*/
|
*/
|
||||||
private function getRate(TransactionCurrency $from, TransactionCurrency $to, Carbon $date): string
|
private function getRate(TransactionCurrency $from, TransactionCurrency $to, Carbon $date): string
|
||||||
{
|
{
|
||||||
Log::debug('getRate()');
|
$key = $this->getCacheKey($from, $to, $date);
|
||||||
if ($this->isPrepared && $this->noPreparedRates) {
|
$res = Cache::get($key, null);
|
||||||
$fallback = $this->fallback[$from->id][$to->id] ?? '0';
|
|
||||||
Log::debug(sprintf('Return fallback rate from #%d to #%d on %s: %s', $from->id, $to->id, $date->format('Y-m-d'), $fallback));
|
|
||||||
|
|
||||||
return $fallback;
|
// find in cache
|
||||||
|
if (null !== $res) {
|
||||||
|
Log::debug(sprintf('ExchangeRateConverter: Return cached rate from #%d to #%d on %s.', $from->id, $to->id, $date->format('Y-m-d')));
|
||||||
|
return $res;
|
||||||
}
|
}
|
||||||
// first attempt:
|
|
||||||
|
// find in database
|
||||||
$rate = $this->getFromDB($from->id, $to->id, $date->format('Y-m-d'));
|
$rate = $this->getFromDB($from->id, $to->id, $date->format('Y-m-d'));
|
||||||
if (null !== $rate) {
|
if (null !== $rate) {
|
||||||
|
Cache::forever($key, $rate);
|
||||||
|
Log::debug(sprintf('ExchangeRateConverter: Return DB rate from #%d to #%d on %s.', $from->id, $to->id, $date->format('Y-m-d')));
|
||||||
return $rate;
|
return $rate;
|
||||||
}
|
}
|
||||||
// no result. perhaps the other way around?
|
|
||||||
|
// find reverse in database
|
||||||
$rate = $this->getFromDB($to->id, $from->id, $date->format('Y-m-d'));
|
$rate = $this->getFromDB($to->id, $from->id, $date->format('Y-m-d'));
|
||||||
if (null !== $rate) {
|
if (null !== $rate) {
|
||||||
return bcdiv('1', $rate);
|
$rate = bcdiv('1', $rate);
|
||||||
|
Cache::forever($key, $rate);
|
||||||
|
Log::debug(sprintf('ExchangeRateConverter: Return DB rate from #%d to #%d on %s.', $from->id, $to->id, $date->format('Y-m-d')));
|
||||||
|
return $rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if nothing in place, fall back on the rate for $from to EUR
|
// fallback scenario.
|
||||||
$first = $this->getEuroRate($from, $date);
|
$first = $this->getEuroRate($from, $date);
|
||||||
$second = $this->getEuroRate($to, $date);
|
$second = $this->getEuroRate($to, $date);
|
||||||
|
|
||||||
@ -102,17 +111,18 @@ class ExchangeRateConverter
|
|||||||
if (0 === bccomp('0', $first) || 0 === bccomp('0', $second)) {
|
if (0 === bccomp('0', $first) || 0 === bccomp('0', $second)) {
|
||||||
Log::warning(sprintf('$first is "%s" and $second is "%s"', $first, $second));
|
Log::warning(sprintf('$first is "%s" and $second is "%s"', $first, $second));
|
||||||
|
|
||||||
return '0';
|
return '1';
|
||||||
}
|
}
|
||||||
|
|
||||||
$second = bcdiv('1', $second);
|
$second = bcdiv('1', $second);
|
||||||
|
$rate = bcmul($first, $second);
|
||||||
return bcmul($first, $second);
|
Log::debug(sprintf('ExchangeRateConverter: Return DB rate from #%d to #%d on %s.', $from->id, $to->id, $date->format('Y-m-d')));
|
||||||
|
Cache::forever($key, $rate);
|
||||||
|
return $rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getFromDB(int $from, int $to, string $date): ?string
|
private function getFromDB(int $from, int $to, string $date): ?string
|
||||||
{
|
{
|
||||||
Log::debug('getFromDB()');
|
|
||||||
if ($from === $to) {
|
if ($from === $to) {
|
||||||
return '1';
|
return '1';
|
||||||
}
|
}
|
||||||
@ -121,7 +131,7 @@ class ExchangeRateConverter
|
|||||||
// perhaps the rate has been cached during this particular run
|
// perhaps the rate has been cached during this particular run
|
||||||
$preparedRate = $this->prepared[$date][$from][$to] ?? null;
|
$preparedRate = $this->prepared[$date][$from][$to] ?? null;
|
||||||
if (null !== $preparedRate && 0 !== bccomp('0', $preparedRate)) {
|
if (null !== $preparedRate && 0 !== bccomp('0', $preparedRate)) {
|
||||||
Log::debug(sprintf('Found prepared rate from #%d to #%d on %s.', $from, $to, $date));
|
Log::debug(sprintf('ExchangeRateConverter: Found prepared rate from #%d to #%d on %s.', $from, $to, $date));
|
||||||
|
|
||||||
return $preparedRate;
|
return $preparedRate;
|
||||||
}
|
}
|
||||||
@ -133,7 +143,7 @@ class ExchangeRateConverter
|
|||||||
if ('' === $rate) {
|
if ('' === $rate) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Log::debug(sprintf('Found cached rate from #%d to #%d on %s.', $from, $to, $date));
|
Log::debug(sprintf('ExchangeRateConverter: Found !cached! rate from #%d to #%d on %s.', $from, $to, $date));
|
||||||
|
|
||||||
return $rate;
|
return $rate;
|
||||||
}
|
}
|
||||||
@ -145,22 +155,21 @@ class ExchangeRateConverter
|
|||||||
->where('to_currency_id', $to)
|
->where('to_currency_id', $to)
|
||||||
->where('date', '<=', $date)
|
->where('date', '<=', $date)
|
||||||
->orderBy('date', 'DESC')
|
->orderBy('date', 'DESC')
|
||||||
->first()
|
->first();
|
||||||
;
|
|
||||||
++$this->queryCount;
|
++$this->queryCount;
|
||||||
$rate = (string) $result?->rate;
|
$rate = (string) $result?->rate;
|
||||||
|
|
||||||
if ('' === $rate) {
|
if ('' === $rate) {
|
||||||
app('log')->debug(sprintf('Found no rate for #%d->#%d (%s) in the DB.', $from, $to, $date));
|
app('log')->debug(sprintf('ExchangeRateConverter: Found no rate for #%d->#%d (%s) in the DB.', $from, $to, $date));
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (0 === bccomp('0', $rate)) {
|
if (0 === bccomp('0', $rate)) {
|
||||||
app('log')->debug(sprintf('Found rate for #%d->#%d (%s) in the DB, but it\'s zero.', $from, $to, $date));
|
app('log')->debug(sprintf('ExchangeRateConverter: Found rate for #%d->#%d (%s) in the DB, but it\'s zero.', $from, $to, $date));
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
app('log')->debug(sprintf('Found rate for #%d->#%d (%s) in the DB: %s.', $from, $to, $date, $rate));
|
app('log')->debug(sprintf('ExchangeRateConverter: Found rate for #%d->#%d (%s) in the DB: %s.', $from, $to, $date, $rate));
|
||||||
$cache->store($rate);
|
$cache->store($rate);
|
||||||
|
|
||||||
// if the rate has not been cached during this particular run, save it
|
// if the rate has not been cached during this particular run, save it
|
||||||
@ -184,7 +193,6 @@ class ExchangeRateConverter
|
|||||||
*/
|
*/
|
||||||
private function getEuroRate(TransactionCurrency $currency, Carbon $date): string
|
private function getEuroRate(TransactionCurrency $currency, Carbon $date): string
|
||||||
{
|
{
|
||||||
Log::debug('getEuroRate()');
|
|
||||||
$euroId = $this->getEuroId();
|
$euroId = $this->getEuroId();
|
||||||
if ($euroId === $currency->id) {
|
if ($euroId === $currency->id) {
|
||||||
return '1';
|
return '1';
|
||||||
@ -252,8 +260,7 @@ class ExchangeRateConverter
|
|||||||
->where('to_currency_id', $to->id)
|
->where('to_currency_id', $to->id)
|
||||||
->where('date', '<=', $end->format('Y-m-d'))
|
->where('date', '<=', $end->format('Y-m-d'))
|
||||||
->where('date', '>=', $start->format('Y-m-d'))
|
->where('date', '>=', $start->format('Y-m-d'))
|
||||||
->orderBy('date', 'DESC')->get()
|
->orderBy('date', 'DESC')->get();
|
||||||
;
|
|
||||||
++$this->queryCount;
|
++$this->queryCount;
|
||||||
if (0 === $set->count()) {
|
if (0 === $set->count()) {
|
||||||
Log::debug('No prepared rates found in this period, use the fallback');
|
Log::debug('No prepared rates found in this period, use the fallback');
|
||||||
@ -319,4 +326,9 @@ class ExchangeRateConverter
|
|||||||
}
|
}
|
||||||
Log::debug(sprintf('ExchangeRateConverter ran %d queries.', $this->queryCount));
|
Log::debug(sprintf('ExchangeRateConverter ran %d queries.', $this->queryCount));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getCacheKey(TransactionCurrency $from, TransactionCurrency $to, Carbon $date): string
|
||||||
|
{
|
||||||
|
return sprintf('cer-%d-%d-%s', $from->id, $to->id, $date->format('Y-m-d'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user