Add Kraken delay after first update to avoid limit (#55736)

* Add delay after first update to avoid limit

* Apply suggestions
This commit is contained in:
Kevin Stillhammer 2021-09-30 13:23:46 +02:00 committed by GitHub
parent ef4b6d7bdf
commit dd52ec78c7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 120 additions and 33 deletions

View File

@ -127,7 +127,7 @@ class KrakenData:
self._config_entry, options=options self._config_entry, options=options
) )
await self._async_refresh_tradable_asset_pairs() await self._async_refresh_tradable_asset_pairs()
# Wait 1 second to avoid triggering the CallRateLimiter # Wait 1 second to avoid triggering the KrakenAPI CallRateLimiter
await asyncio.sleep(CALL_RATE_LIMIT_SLEEP) await asyncio.sleep(CALL_RATE_LIMIT_SLEEP)
self.coordinator = DataUpdateCoordinator( self.coordinator = DataUpdateCoordinator(
self._hass, self._hass,
@ -139,6 +139,8 @@ class KrakenData:
), ),
) )
await self.coordinator.async_config_entry_first_refresh() await self.coordinator.async_config_entry_first_refresh()
# Wait 1 second to avoid triggering the KrakenAPI CallRateLimiter
await asyncio.sleep(CALL_RATE_LIMIT_SLEEP)
def _get_websocket_name_asset_pairs(self) -> str: def _get_websocket_name_asset_pairs(self) -> str:
return ",".join(wsname for wsname in self.tradable_asset_pairs.values()) return ",".join(wsname for wsname in self.tradable_asset_pairs.values())

View File

@ -129,12 +129,14 @@ class KrakenSensor(CoordinatorEntity[Optional[KrakenResponse]], SensorEntity):
super()._handle_coordinator_update() super()._handle_coordinator_update()
def _update_internal_state(self) -> None: def _update_internal_state(self) -> None:
if not self.coordinator.data:
return
try: try:
self._attr_native_value = self.entity_description.value_fn( self._attr_native_value = self.entity_description.value_fn(
self.coordinator, self.tracked_asset_pair_wsname # type: ignore[arg-type] self.coordinator, self.tracked_asset_pair_wsname # type: ignore[arg-type]
) )
self._received_data_at_least_once = True # Received data at least one time. self._received_data_at_least_once = True
except TypeError: except KeyError:
if self._received_data_at_least_once: if self._received_data_at_least_once:
if self._available: if self._available:
_LOGGER.warning( _LOGGER.warning(

View File

@ -7,6 +7,12 @@ TRADEABLE_ASSET_PAIR_RESPONSE = pandas.DataFrame(
index=["ADAXBT", "ADAETH", "XBTEUR", "XXBTZGBP", "XXBTZUSD", "XXBTZJPY"], index=["ADAXBT", "ADAETH", "XBTEUR", "XXBTZGBP", "XXBTZUSD", "XXBTZJPY"],
) )
MISSING_PAIR_TRADEABLE_ASSET_PAIR_RESPONSE = pandas.DataFrame(
{"wsname": ["ADA/XBT", "ADA/ETH", "XBT/EUR", "XBT/GBP", "XBT/JPY"]},
columns=["wsname"],
index=["ADAXBT", "ADAETH", "XBTEUR", "XXBTZGBP", "XXBTZJPY"],
)
TICKER_INFORMATION_RESPONSE = pandas.DataFrame( TICKER_INFORMATION_RESPONSE = pandas.DataFrame(
{ {
"a": [ "a": [
@ -78,3 +84,67 @@ TICKER_INFORMATION_RESPONSE = pandas.DataFrame(
columns=["a", "b", "c", "h", "l", "o", "p", "t", "v"], columns=["a", "b", "c", "h", "l", "o", "p", "t", "v"],
index=["ADAXBT", "ADAETH", "XBTEUR", "XXBTZGBP", "XXBTZUSD", "XXBTZJPY"], index=["ADAXBT", "ADAETH", "XBTEUR", "XXBTZGBP", "XXBTZUSD", "XXBTZJPY"],
) )
MISSING_PAIR_TICKER_INFORMATION_RESPONSE = pandas.DataFrame(
{
"a": [
[0.000349400, 15949, 15949.000],
[0.000349400, 15949, 15949.000],
[0.000349400, 15949, 15949.000],
[0.000349400, 15949, 15949.000],
[0.000349400, 15949, 15949.000],
],
"b": [
[0.000348400, 20792, 20792.000],
[0.000348400, 20792, 20792.000],
[0.000348400, 20792, 20792.000],
[0.000348400, 20792, 20792.000],
[0.000348400, 20792, 20792.000],
],
"c": [
[0.000347800, 2809.36384377],
[0.000347800, 2809.36384377],
[0.000347800, 2809.36384377],
[0.000347800, 2809.36384377],
[0.000347800, 2809.36384377],
],
"h": [
[0.000351600, 0.000352100],
[0.000351600, 0.000352100],
[0.000351600, 0.000352100],
[0.000351600, 0.000352100],
[0.000351600, 0.000352100],
],
"l": [
[0.000344600, 0.000344600],
[0.000344600, 0.000344600],
[0.000344600, 0.000344600],
[0.000344600, 0.000344600],
[0.000344600, 0.000344600],
],
"o": [
0.000351300,
0.000351300,
0.000351300,
0.000351300,
0.000351300,
],
"p": [
[0.000348573, 0.000344881],
[0.000348573, 0.000344881],
[0.000348573, 0.000344881],
[0.000348573, 0.000344881],
[0.000348573, 0.000344881],
],
"t": [[82, 128], [82, 128], [82, 128], [82, 128], [82, 128]],
"v": [
[146300.24906838, 253478.04715403],
[146300.24906838, 253478.04715403],
[146300.24906838, 253478.04715403],
[146300.24906838, 253478.04715403],
[146300.24906838, 253478.04715403],
],
},
columns=["a", "b", "c", "h", "l", "o", "p", "t", "v"],
index=["ADAXBT", "ADAETH", "XBTEUR", "XXBTZGBP", "XXBTZJPY"],
)

View File

@ -13,7 +13,12 @@ from homeassistant.components.kraken.const import (
from homeassistant.const import CONF_SCAN_INTERVAL, EVENT_HOMEASSISTANT_START from homeassistant.const import CONF_SCAN_INTERVAL, EVENT_HOMEASSISTANT_START
import homeassistant.util.dt as dt_util import homeassistant.util.dt as dt_util
from .const import TICKER_INFORMATION_RESPONSE, TRADEABLE_ASSET_PAIR_RESPONSE from .const import (
MISSING_PAIR_TICKER_INFORMATION_RESPONSE,
MISSING_PAIR_TRADEABLE_ASSET_PAIR_RESPONSE,
TICKER_INFORMATION_RESPONSE,
TRADEABLE_ASSET_PAIR_RESPONSE,
)
from tests.common import MockConfigEntry, async_fire_time_changed from tests.common import MockConfigEntry, async_fire_time_changed
@ -230,38 +235,46 @@ async def test_missing_pair_marks_sensor_unavailable(hass):
with patch("homeassistant.util.dt.utcnow", return_value=utcnow), patch( with patch("homeassistant.util.dt.utcnow", return_value=utcnow), patch(
"pykrakenapi.KrakenAPI.get_tradable_asset_pairs", "pykrakenapi.KrakenAPI.get_tradable_asset_pairs",
return_value=TRADEABLE_ASSET_PAIR_RESPONSE, return_value=TRADEABLE_ASSET_PAIR_RESPONSE,
): ) as tradeable_asset_pairs_mock, patch(
with patch( "pykrakenapi.KrakenAPI.get_ticker_information",
"pykrakenapi.KrakenAPI.get_ticker_information", return_value=TICKER_INFORMATION_RESPONSE,
return_value=TICKER_INFORMATION_RESPONSE, ) as ticket_information_mock:
): entry = MockConfigEntry(
entry = MockConfigEntry( domain=DOMAIN,
domain=DOMAIN, options={
options={ CONF_SCAN_INTERVAL: DEFAULT_SCAN_INTERVAL,
CONF_SCAN_INTERVAL: DEFAULT_SCAN_INTERVAL, CONF_TRACKED_ASSET_PAIRS: [DEFAULT_TRACKED_ASSET_PAIR],
CONF_TRACKED_ASSET_PAIRS: [DEFAULT_TRACKED_ASSET_PAIR], },
}, )
) entry.add_to_hass(hass)
entry.add_to_hass(hass)
await hass.config_entries.async_setup(entry.entry_id) await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
hass.bus.async_fire(EVENT_HOMEASSISTANT_START) hass.bus.async_fire(EVENT_HOMEASSISTANT_START)
await hass.async_block_till_done() await hass.async_block_till_done()
sensor = hass.states.get("sensor.xbt_usd_ask") sensor = hass.states.get("sensor.xbt_usd_ask")
assert sensor.state == "0.0003494" assert sensor.state == "0.0003494"
with patch( tradeable_asset_pairs_mock.return_value = (
"pykrakenapi.KrakenAPI.get_ticker_information", MISSING_PAIR_TRADEABLE_ASSET_PAIR_RESPONSE
side_effect=KrakenAPIError("EQuery:Unknown asset pair"), )
): ticket_information_mock.side_effect = KrakenAPIError(
async_fire_time_changed( "EQuery:Unknown asset pair"
hass, utcnow + timedelta(seconds=DEFAULT_SCAN_INTERVAL * 2) )
) async_fire_time_changed(
await hass.async_block_till_done() hass, utcnow + timedelta(seconds=DEFAULT_SCAN_INTERVAL * 2)
)
await hass.async_block_till_done()
sensor = hass.states.get("sensor.xbt_usd_ask") ticket_information_mock.side_effect = None
assert sensor.state == "unavailable" ticket_information_mock.return_value = MISSING_PAIR_TICKER_INFORMATION_RESPONSE
async_fire_time_changed(
hass, utcnow + timedelta(seconds=DEFAULT_SCAN_INTERVAL * 2)
)
await hass.async_block_till_done()
sensor = hass.states.get("sensor.xbt_usd_ask")
assert sensor.state == "unavailable"