mirror of
https://github.com/lnbits/lnbits.git
synced 2025-09-19 03:57:29 +02:00
fix: extension stop background work (#2281)
* feat: add helper methods * fix: do not try to stop background work on first install * fix: first stop via function call then try REST API * fix: `make check` * fix: prepare for `{ext_id}_stop`
This commit is contained in:
@@ -53,8 +53,45 @@ async def stop_extension_background_work(
|
|||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Stop background work for extension (like asyncio.Tasks, WebSockets, etc).
|
Stop background work for extension (like asyncio.Tasks, WebSockets, etc).
|
||||||
Extensions SHOULD expose a DELETE enpoint at the root level of their API.
|
Extensions SHOULD expose a `api_stop()` function and/or a DELETE enpoint
|
||||||
|
at the root level of their API.
|
||||||
"""
|
"""
|
||||||
|
stopped = await _stop_extension_background_work(ext_id)
|
||||||
|
|
||||||
|
if not stopped:
|
||||||
|
# fallback to REST API call
|
||||||
|
await _stop_extension_background_work_via_api(ext_id, user, access_token)
|
||||||
|
|
||||||
|
|
||||||
|
async def _stop_extension_background_work(ext_id) -> bool:
|
||||||
|
upgrade_hash = settings.extension_upgrade_hash(ext_id) or ""
|
||||||
|
ext = Extension(ext_id, True, False, upgrade_hash=upgrade_hash)
|
||||||
|
|
||||||
|
try:
|
||||||
|
logger.info(f"Stopping background work for extension '{ext.module_name}'.")
|
||||||
|
old_module = importlib.import_module(ext.module_name)
|
||||||
|
|
||||||
|
# Extensions must expose an `{ext_id}_stop()` function at the module level
|
||||||
|
# The `api_stop()` function is for backwards compatibility (will be deprecated)
|
||||||
|
stop_fns = [f"{ext_id}_stop", "api_stop"]
|
||||||
|
stop_fn_name = next((fn for fn in stop_fns if hasattr(old_module, fn)), None)
|
||||||
|
assert stop_fn_name, "No stop function found for '{ext.module_name}'"
|
||||||
|
|
||||||
|
await getattr(old_module, stop_fn_name)()
|
||||||
|
|
||||||
|
logger.info(f"Stopped background work for extension '{ext.module_name}'.")
|
||||||
|
except Exception as ex:
|
||||||
|
logger.warning(f"Failed to stop background work for '{ext.module_name}'.")
|
||||||
|
logger.warning(ex)
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
async def _stop_extension_background_work_via_api(ext_id, user, access_token):
|
||||||
|
logger.info(
|
||||||
|
f"Stopping background work for extension '{ext_id}' using the REST API."
|
||||||
|
)
|
||||||
async with httpx.AsyncClient() as client:
|
async with httpx.AsyncClient() as client:
|
||||||
try:
|
try:
|
||||||
url = f"http://{settings.host}:{settings.port}/{ext_id}/api/v1?usr={user}"
|
url = f"http://{settings.host}:{settings.port}/{ext_id}/api/v1?usr={user}"
|
||||||
@@ -63,7 +100,11 @@ async def stop_extension_background_work(
|
|||||||
)
|
)
|
||||||
resp = await client.delete(url=url, headers=headers)
|
resp = await client.delete(url=url, headers=headers)
|
||||||
resp.raise_for_status()
|
resp.raise_for_status()
|
||||||
|
logger.info(f"Stopped background work for extension '{ext_id}'.")
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
|
logger.warning(
|
||||||
|
f"Failed to stop background work for '{ext_id}' using the REST API."
|
||||||
|
)
|
||||||
logger.warning(ex)
|
logger.warning(ex)
|
||||||
|
|
||||||
|
|
||||||
|
@@ -824,8 +824,9 @@ async def api_install_extension(
|
|||||||
|
|
||||||
await add_installed_extension(ext_info)
|
await add_installed_extension(ext_info)
|
||||||
|
|
||||||
# call stop while the old routes are still active
|
if extension.is_upgrade_extension:
|
||||||
await stop_extension_background_work(data.ext_id, user.id, access_token)
|
# call stop while the old routes are still active
|
||||||
|
await stop_extension_background_work(data.ext_id, user.id, access_token)
|
||||||
|
|
||||||
if data.ext_id not in settings.lnbits_deactivated_extensions:
|
if data.ext_id not in settings.lnbits_deactivated_extensions:
|
||||||
settings.lnbits_deactivated_extensions += [data.ext_id]
|
settings.lnbits_deactivated_extensions += [data.ext_id]
|
||||||
|
@@ -68,6 +68,16 @@ class InstalledExtensionsSettings(LNbitsSettings):
|
|||||||
# list of redirects that extensions want to perform
|
# list of redirects that extensions want to perform
|
||||||
lnbits_extensions_redirects: List[Any] = Field(default=[])
|
lnbits_extensions_redirects: List[Any] = Field(default=[])
|
||||||
|
|
||||||
|
def extension_upgrade_path(self, ext_id: str) -> Optional[str]:
|
||||||
|
return next(
|
||||||
|
(e for e in self.lnbits_upgraded_extensions if e.endswith(f"/{ext_id}")),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
|
||||||
|
def extension_upgrade_hash(self, ext_id: str) -> Optional[str]:
|
||||||
|
path = settings.extension_upgrade_path(ext_id)
|
||||||
|
return path.split("/")[0] if path else None
|
||||||
|
|
||||||
|
|
||||||
class ThemesSettings(LNbitsSettings):
|
class ThemesSettings(LNbitsSettings):
|
||||||
lnbits_site_title: str = Field(default="LNbits")
|
lnbits_site_title: str = Field(default="LNbits")
|
||||||
|
Reference in New Issue
Block a user