diff --git a/README.md b/README.md index ac58a88..361d5b3 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,14 @@ configuration.yaml (string)(Required) The URL that points to your database. + db_retry_wait + (float)(Optional) + Time to wait between DB reconnects. + + db_retry_limit + (int)(Optional) + Max number of times to retry DB reconnect on startup. Defaults to 10. If set to `null` (without quotes) LTSS will try to reconnect to the DB indefinitely. Note that this setting applies only to LTSS startup; during normal operation LTSS will retry 10 times and then drop the write to prevent filling up the internal queue. + chunk_time_interval (int)(Optional) The time interval to be used for chunking in TimescaleDB in microseconds. Defaults to 2592000000000 (30 days). Ignored for databases without TimescaleDB extension. diff --git a/custom_components/ltss/__init__.py b/custom_components/ltss/__init__.py index 56a5cc6..2bb7f25 100644 --- a/custom_components/ltss/__init__.py +++ b/custom_components/ltss/__init__.py @@ -48,14 +48,20 @@ CONF_DB_URL = "db_url" CONF_CHUNK_TIME_INTERVAL = "chunk_time_interval" - -CONNECT_RETRY_WAIT = 3 +CONF_DB_RETRY_WAIT = "db_retry_wait" +CONF_DB_RETRY_LIMIT = "db_retry_limit" CONFIG_SCHEMA = vol.Schema( { DOMAIN: INCLUDE_EXCLUDE_BASE_FILTER_SCHEMA.extend( { vol.Required(CONF_DB_URL): cv.string, + vol.Optional( + CONF_DB_RETRY_WAIT, default=3.0 + ): cv.positive_float, # time to wait between db reconnects, default 3.0s + vol.Optional(CONF_DB_RETRY_LIMIT, default=10): vol.Any( + None, cv.positive_int + ), # max. number of retries when connecting to the DB, no limit by default vol.Optional( CONF_CHUNK_TIME_INTERVAL, default=2592000000000 ): cv.positive_int, # 30 days @@ -71,12 +77,16 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: conf = config[DOMAIN] db_url = conf.get(CONF_DB_URL) + db_retry_wait = conf.get(CONF_DB_RETRY_WAIT) + db_retry_limit = conf.get(CONF_DB_RETRY_LIMIT) chunk_time_interval = conf.get(CONF_CHUNK_TIME_INTERVAL) entity_filter = convert_include_exclude_filter(conf) instance = LTSS_DB( hass=hass, uri=db_url, + db_retry_wait=db_retry_wait, + db_retry_limit=db_retry_limit, chunk_time_interval=chunk_time_interval, entity_filter=entity_filter, ) @@ -94,6 +104,8 @@ def __init__( hass: HomeAssistant, uri: str, chunk_time_interval: int, + db_retry_wait: int, + db_retry_limit: int, entity_filter: Callable[[str], bool], ) -> None: """Initialize the ltss.""" @@ -103,6 +115,8 @@ def __init__( self.queue: Any = queue.Queue() self.recording_start = dt_util.utcnow() self.db_url = uri + self.db_retry_wait = db_retry_wait + self.db_retry_limit = db_retry_limit self.chunk_time_interval = chunk_time_interval self.async_db_ready = asyncio.Future() self.engine: Any = None @@ -122,9 +136,11 @@ def run(self): tries = 1 connected = False - while not connected and tries <= 10: + while not connected and ( + self.db_retry_limit is None or tries <= self.db_retry_limit + ): if tries != 1: - time.sleep(CONNECT_RETRY_WAIT) + time.sleep(self.db_retry_wait) try: self._setup_connection() connected = True @@ -133,7 +149,7 @@ def run(self): _LOGGER.error( "Error during connection setup: %s (retrying " "in %s seconds)", err, - CONNECT_RETRY_WAIT, + self.db_retry_wait, ) tries += 1 @@ -201,7 +217,7 @@ def notify_hass_started(event): updated = False while not updated and tries <= 10: if tries != 1: - time.sleep(CONNECT_RETRY_WAIT) + time.sleep(self.db_retry_wait) try: with self.get_session() as session: with session.begin(): @@ -221,7 +237,7 @@ def notify_hass_started(event): "Error in database connectivity: %s. " "(retrying in %s seconds)", err, - CONNECT_RETRY_WAIT, + self.db_retry_wait, ) tries += 1 diff --git a/tests/pytest/test_databases.py b/tests/pytest/test_databases.py index b2a5770..4a32475 100644 --- a/tests/pytest/test_databases.py +++ b/tests/pytest/test_databases.py @@ -51,6 +51,8 @@ def ltss_init_wrapper(container): "postgresql://postgres@localhost:" + container.ports["5432/tcp"][0]["HostPort"], 123, + 3.0, + 10, lambda x: False, )