Skip to content

Commit

Permalink
Refactor rates API to use time cache
Browse files Browse the repository at this point in the history
  • Loading branch information
yashasvi-ranawat committed May 5, 2024
1 parent f01e14f commit a720347
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 52 deletions.
46 changes: 6 additions & 40 deletions bitcash/network/rates.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
from collections import OrderedDict
from decimal import ROUND_DOWN
from functools import wraps
from time import time

import requests
from bitcash.network.http import session
from bitcash.utils import Decimal
from bitcash.utils import Decimal, time_cache

DEFAULT_CACHE_TIME = 60

Expand Down Expand Up @@ -651,42 +649,9 @@ def currency_to_satoshi(amount, currency):
return int(satoshis * Decimal(amount))


class CachedRate:
__slots__ = ("satoshis", "last_update")

def __init__(self, satoshis, last_update):
self.satoshis = satoshis
self.last_update = last_update


def currency_to_satoshi_local_cache(f):
start_time = time()

cached_rates = dict(
[(currency, CachedRate(None, start_time)) for currency in EXCHANGE_RATES.keys()]
)

@wraps(f)
def wrapper(amount, currency):
now = time()

cached_rate = cached_rates[currency]

if (
not cached_rate.satoshis
or now - cached_rate.last_update > DEFAULT_CACHE_TIME
):
cached_rate.satoshis = EXCHANGE_RATES[currency]()
cached_rate.last_update = now

return int(cached_rate.satoshis * Decimal(amount))

return wrapper


@currency_to_satoshi_local_cache
def currency_to_satoshi_local_cached():
pass # pragma: no cover
@time_cache(max_age=DEFAULT_CACHE_TIME, cache_size=len(EXCHANGE_RATES))
def _currency_to_satoshi_cached(currency):
return EXCHANGE_RATES[currency]()


def currency_to_satoshi_cached(amount, currency):
Expand All @@ -700,7 +665,8 @@ def currency_to_satoshi_cached(amount, currency):
:type currency: ``str``
:rtype: ``int``
"""
return currency_to_satoshi_local_cached(amount, currency)
satoshis = _currency_to_satoshi_cached(currency)
return int(satoshis * Decimal(amount))


def satoshi_to_currency(num, currency):
Expand Down
34 changes: 22 additions & 12 deletions tests/network/test_rates.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
from time import sleep, time

from _pytest.monkeypatch import MonkeyPatch
import bitcash
from bitcash.network import rates as _rates
from bitcash.network.rates import (
RatesAPI,
bch_to_satoshi,
currency_to_satoshi,
currency_to_satoshi_cached,
EXCHANGE_RATES,
mbch_to_satoshi,
satoshi_to_currency,
satoshi_to_currency_cached,
Expand Down Expand Up @@ -73,38 +76,45 @@ def test_rates_close():
assert rates[-1] / rates[0] < 1.1 and rates[-1] / rates[0] > 0.9


def _dummy_usd_to_satoshi():
sleep(1)
return 1


DUMMY_EXCHANGE_RATES = {"usd": _dummy_usd_to_satoshi}


class TestRateCache:
def test_cache(self):
sleep(0.2)
def setup_method(self):
self.monkeypatch = MonkeyPatch()

def test_cache(self):
self.monkeypatch.setattr(_rates, "EXCHANGE_RATES", DUMMY_EXCHANGE_RATES)
start_time = time()
set_rate_cache_time(0)
currency_to_satoshi_cached(1, "usd")
initial_time = time() - start_time

start_time = time()
set_rate_cache_time(60)
currency_to_satoshi_cached(1, "usd")
currency_to_satoshi_cached(2, "usd")
cached_time = time() - start_time

assert initial_time > cached_time
self.monkeypatch.setattr(_rates, "EXCHANGE_RATES", EXCHANGE_RATES)

def test_expires(self):
sleep(0.2)

set_rate_cache_time(0)
self.monkeypatch.setattr(_rates, "EXCHANGE_RATES", DUMMY_EXCHANGE_RATES)
set_rate_cache_time(1.2)
currency_to_satoshi_cached(1, "usd")

start_time = time()
set_rate_cache_time(60)
currency_to_satoshi_cached(1, "usd")
currency_to_satoshi_cached(2, "usd")
cached_time = time() - start_time

sleep(0.2)

start_time = time()
set_rate_cache_time(0.1)
currency_to_satoshi_cached(1, "usd")
currency_to_satoshi_cached(3, "usd")
update_time = time() - start_time

assert update_time > cached_time
self.monkeypatch.setattr(_rates, "EXCHANGE_RATES", EXCHANGE_RATES)

0 comments on commit a720347

Please sign in to comment.