update_check.py 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. import asyncio
  2. import time
  3. import logging
  4. from typing import Optional
  5. import httpx
  6. from pydantic import BaseModel
  7. from gpustack import __version__
  8. from gpustack.utils import platform
  9. logger = logging.getLogger(__name__)
  10. cached_update = None
  11. cache_timestamp = None
  12. UPDATE_CACHE_TIMEOUT = 12 * 60 * 60
  13. UPDATE_CHECK_INTERVAL = 12 * 60 * 60
  14. UPDATE_CHECK_URL = "https://update-service.gpustack.ai"
  15. def is_dev_version() -> bool:
  16. return "0.0.0" in __version__
  17. class UpdateResponse(BaseModel):
  18. latest_version: str
  19. async def get_update(update_check_url: Optional[str] = None) -> UpdateResponse:
  20. if is_dev_version():
  21. return UpdateResponse(latest_version=__version__)
  22. global cached_update, cache_timestamp
  23. if (
  24. cached_update is None
  25. or cache_timestamp is None
  26. or time.time() - cache_timestamp > UPDATE_CACHE_TIMEOUT
  27. ):
  28. cached_update = await do_get_update(update_check_url)
  29. cache_timestamp = time.time()
  30. return cached_update
  31. async def do_get_update(
  32. update_check_url: Optional[str] = None,
  33. timeout: int = 3,
  34. ) -> UpdateResponse:
  35. if update_check_url is None:
  36. update_check_url = UPDATE_CHECK_URL
  37. try:
  38. os_name = platform.system()
  39. arch = platform.arch()
  40. headers = {"User-Agent": f"gpustack/{__version__} ({os_name}; {arch})"}
  41. params = {"os": os_name, "arch": arch, "version": __version__}
  42. async with httpx.AsyncClient(timeout=timeout) as client:
  43. response = await client.get(
  44. update_check_url, headers=headers, params=params
  45. )
  46. response.raise_for_status()
  47. response_data = response.json()
  48. return UpdateResponse(**response_data)
  49. except Exception as e:
  50. logger.debug(f"Failed to check for updates: {e}")
  51. return UpdateResponse(latest_version=__version__)
  52. class UpdateChecker:
  53. """
  54. UpdateChecker checks for updates periodically.
  55. """
  56. def __init__(
  57. self, update_check_url: Optional[str] = None, interval=UPDATE_CHECK_INTERVAL
  58. ):
  59. self._interval = interval
  60. self._update_check_url = update_check_url
  61. async def start(self):
  62. while True:
  63. try:
  64. await get_update(self._update_check_url)
  65. except Exception as e:
  66. logger.error(f"Failed to get update: {e}")
  67. await asyncio.sleep(self._interval)