Skip to content

Commit

Permalink
Move all setup/startup tasks to new TaskManager (#2165)
Browse files Browse the repository at this point in the history
* Move tasks

* move more

* move more

* reclassify load task

* move all

* finish
  • Loading branch information
ludeeus committed Aug 25, 2021
1 parent f4104e1 commit 189f72e
Show file tree
Hide file tree
Showing 44 changed files with 689 additions and 711 deletions.
1 change: 0 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ jobs:

- name: "Set version number"
run: |
sed -i '/INTEGRATION_VERSION = /c\INTEGRATION_VERSION = "${{ steps.version.outputs.version }}"' ${{ github.workspace }}/custom_components/hacs/const.py
python3 ${{ github.workspace }}/manage/update_manifest.py --version ${{ steps.version.outputs.version }}
# Pack the HACS dir as a zip and upload to the release
Expand Down
80 changes: 70 additions & 10 deletions custom_components/hacs/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,39 @@
from __future__ import annotations

import logging
import math
import pathlib
from dataclasses import asdict, dataclass, field
from typing import TYPE_CHECKING, Any

from aiogithubapi import GitHub, GitHubAPI
from aiogithubapi import (
GitHub,
GitHubAPI,
GitHubAuthenticationException,
GitHubRatelimitException,
)
from aiogithubapi.objects.repository import AIOGitHubAPIRepository
from aiohttp.client import ClientSession
from awesomeversion import AwesomeVersion
from homeassistant.core import HomeAssistant

from .const import INTEGRATION_VERSION
from .enums import ConfigurationType, HacsDisabledReason, HacsStage, LovelaceMode
from homeassistant.loader import Integration
from queueman.manager import QueueManager

from .enums import (
ConfigurationType,
HacsCategory,
HacsDisabledReason,
HacsStage,
LovelaceMode,
)
from .exceptions import HacsException
from .utils.logger import getLogger

if TYPE_CHECKING:
from .hacsbase.data import HacsData
from .helpers.classes.repository import HacsRepository
from .operational.factory import HacsTaskFactory
from .tasks.manager import HacsTaskManager


@dataclass
Expand Down Expand Up @@ -87,7 +103,7 @@ class HacsCore:
class HacsCommon:
"""Common for HACS."""

categories: list[str] = field(default_factory=list)
categories: set[str] = field(default_factory=set)
default: list[str] = field(default_factory=list)
installed: list[str] = field(default_factory=list)
renamed_repositories: dict[str, str] = field(default_factory=dict)
Expand All @@ -113,7 +129,6 @@ class HacsSystem:
disabled: bool = False
disabled_reason: str | None = None
running: bool = False
version = AwesomeVersion(INTEGRATION_VERSION)
stage = HacsStage.SETUP
action: bool = False

Expand All @@ -124,29 +139,45 @@ class HacsBase:
_repositories = []
_repositories_by_full_name = {}
_repositories_by_id = {}

common = HacsCommon()
configuration = HacsConfiguration()
core = HacsCore()
data = None
data: HacsData | None = None
data_repo: AIOGitHubAPIRepository | None = None
factory: HacsTaskFactory | None = None
frontend = HacsFrontend()
github: GitHub | None = None
githubapi: GitHubAPI | None = None
hass: HomeAssistant | None = None
integration: Integration | None = None
log: logging.Logger = getLogger()
queue: QueueManager | None = None
recuring_tasks = []
repositories: list[HacsRepository] = []
repository: AIOGitHubAPIRepository | None = None
session: ClientSession | None = None
stage = HacsStage.SETUP
stage: HacsStage | None = None
status = HacsStatus()
system = HacsSystem()
version: AwesomeVersion | None = None
tasks: HacsTaskManager | None = None
version: str | None = None

@property
def integration_dir(self) -> pathlib.Path:
"""Return the HACS integration dir."""
return pathlib.Path(__file__).parent
return self.integration.file_path

async def async_set_stage(self, stage: HacsStage | None) -> None:
"""Set HACS stage."""
if stage and self.stage == stage:
return

self.stage = stage
if stage is not None:
self.log.info("Stage changed: %s", self.stage)
self.hass.bus.async_fire("hacs/stage", {"stage": self.stage})
await self.tasks.async_execute_runtume_tasks()

def disable_hacs(self, reason: HacsDisabledReason) -> None:
"""Disable HACS."""
Expand All @@ -160,3 +191,32 @@ def enable_hacs(self) -> None:
self.system.disabled = False
self.system.disabled_reason = None
self.log.info("HACS is enabled")

def enable_hacs_category(self, category: HacsCategory):
"""Enable HACS category."""
if category not in self.common.categories:
self.log.info("Enable category: %s", category)
self.common.categories.add(category)

def disable_hacs_category(self, category: HacsCategory):
"""Disable HACS category."""
if category in self.common.categories:
self.log.info("Disabling category: %s", category)
self.common.categories.pop(category)

async def async_can_update(self) -> int:
"""Helper to calculate the number of repositories we can fetch data for."""
try:
result = await self.githubapi.rate_limit()
if ((limit := result.data.resources.core.remaining or 0) - 1000) >= 15:
return math.floor((limit - 1000) / 15)
except GitHubAuthenticationException as exception:
self.log.error("GitHub authentication failed - %s", exception)
self.disable_hacs(HacsDisabledReason.INVALID_TOKEN)
except GitHubRatelimitException as exception:
self.log.error("GitHub API ratelimited - %s", exception)
self.disable_hacs(HacsDisabledReason.RATE_LIMIT)
except BaseException as exception: # pylint: disable=broad-except
self.log.exception(exception)

return 0
11 changes: 4 additions & 7 deletions custom_components/hacs/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,9 @@
from homeassistant.core import callback
from homeassistant.helpers import aiohttp_client
from homeassistant.helpers.event import async_call_later
from homeassistant.loader import async_get_integration

from custom_components.hacs.const import (
CLIENT_ID,
DOMAIN,
INTEGRATION_VERSION,
MINIMUM_HA_VERSION,
)
from custom_components.hacs.const import CLIENT_ID, DOMAIN, MINIMUM_HA_VERSION
from custom_components.hacs.enums import ConfigurationType
from custom_components.hacs.helpers.functions.configuration_schema import (
RELEASE_LIMIT,
Expand Down Expand Up @@ -72,11 +68,12 @@ async def _wait_for_activation(_=None):
)

if not self.activation:
integration = await async_get_integration(self.hass, DOMAIN)
if not self.device:
self.device = GitHubDeviceAPI(
client_id=CLIENT_ID,
session=aiohttp_client.async_get_clientsession(self.hass),
**{"client_name": f"HACS/{INTEGRATION_VERSION}"},
**{"client_name": f"HACS/{integration.version}"},
)
async_call_later(self.hass, 1, _wait_for_activation)
try:
Expand Down
22 changes: 3 additions & 19 deletions custom_components/hacs/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,17 @@

NAME_LONG = "HACS (Home Assistant Community Store)"
NAME_SHORT = "HACS"
INTEGRATION_VERSION = "main"
DOMAIN = "hacs"
CLIENT_ID = "395a8e669c5de9f7c6e8"
MINIMUM_HA_VERSION = "2021.2.0"
PROJECT_URL = "https://github.com/hacs/integration/"
CUSTOM_UPDATER_LOCATIONS = [
"{}/custom_components/custom_updater.py",
"{}/custom_components/custom_updater/__init__.py",
]


ISSUE_URL = f"{PROJECT_URL}issues"
DOMAIN_DATA = f"{NAME_SHORT.lower()}_data"

ELEMENT_TYPES = ["integration", "plugin"]

PACKAGE_NAME = "custom_components.hacs"

HACS_GITHUB_API_HEADERS = {
"User-Agent": f"HACS/{INTEGRATION_VERSION}",
"Accept": ACCEPT_HEADERS["preview"],
}

HACS_ACTION_GITHUB_API_HEADERS = {
"User-Agent": "HACS/action",
"Accept": ACCEPT_HEADERS["preview"],
Expand All @@ -44,16 +33,11 @@
# Messages
NO_ELEMENTS = "No elements to show, open the store to install some awesome stuff."

CUSTOM_UPDATER_WARNING = """
This cannot be used with custom_updater.
To use this you need to remove custom_updater form {}
"""

STARTUP = f"""
STARTUP = """
-------------------------------------------------------------------
HACS (Home Assistant Community Store)
Version: {INTEGRATION_VERSION}
Version: {version}
This is a custom integration
If you have any issues with this you need to open an issue here:
https://github.com/hacs/integration/issues
Expand Down
10 changes: 10 additions & 0 deletions custom_components/hacs/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,16 @@ class LovelaceMode(str, Enum):
YAML = "yaml"


class HacsTaskType(str, Enum):
"""HacsTaskType"""

RUNTIME = "runtime"
EVENT = "event"
SCHEDULE = "schedule"
MANUAL = "manual"
BASE = "base"


class HacsStage(str, Enum):
SETUP = "setup"
STARTUP = "startup"
Expand Down
3 changes: 1 addition & 2 deletions custom_components/hacs/hacsbase/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

from homeassistant.core import callback

from custom_components.hacs.const import INTEGRATION_VERSION
from custom_components.hacs.helpers.classes.manifest import HacsManifest
from custom_components.hacs.helpers.functions.register_repository import (
register_repository,
Expand Down Expand Up @@ -207,7 +206,7 @@ def async_restore_repository(self, entry, repository_data):
repository.status.first_install = False

if repository_data["full_name"] == "hacs/integration":
repository.data.installed_version = INTEGRATION_VERSION
repository.data.installed_version = self.hacs.version
repository.data.installed = True

return True
24 changes: 4 additions & 20 deletions custom_components/hacs/hacsbase/hacs.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,20 @@
from custom_components.hacs.helpers.functions.register_repository import (
register_repository,
)
from custom_components.hacs.helpers.functions.remaining_github_calls import (
get_fetch_updates_for,
)

from custom_components.hacs.helpers.functions.store import (
async_load_from_store,
async_save_to_store,
)
from custom_components.hacs.operational.setup_actions.categories import (
async_setup_extra_stores,
)
from custom_components.hacs.share import (
get_factory,
get_queue,
get_removed,
is_removed,
list_removed_repositories,
)

from ..base import HacsBase
from ..enums import HacsCategory, HacsStage
from ..share import get_factory, get_queue


class Hacs(HacsBase, HacsHelpers):
Expand Down Expand Up @@ -121,7 +115,6 @@ async def startup_tasks(self, _event=None):
"""Tasks that are started after startup."""
await self.async_set_stage(HacsStage.STARTUP)
self.status.background_task = True
await async_setup_extra_stores()
self.hass.bus.async_fire("hacs/status", {})

await self.handle_critical_repositories_startup()
Expand Down Expand Up @@ -241,15 +234,13 @@ async def prosess_queue(self, _notarealarg=None):
self.log.debug("Queue is already running")
return

can_update = await get_fetch_updates_for(self.githubapi)
can_update = await self.async_can_update()
self.log.debug(
"Can update %s repositories, items in queue %s",
can_update,
self.queue.pending_tasks,
)
if can_update == 0:
self.log.info("HACS is ratelimited, repository updates will resume later.")
else:
if can_update != 0:
self.status.background_task = True
self.hass.bus.async_fire("hacs/status", {})
try:
Expand Down Expand Up @@ -283,7 +274,6 @@ async def recurring_tasks_installed(self, _notarealarg=None):
async def recurring_tasks_all(self, _notarealarg=None):
"""Recurring tasks for all repositories."""
self.log.debug("Starting recurring background task for all repositories")
await async_setup_extra_stores()
self.status.background_task = True
self.hass.bus.async_fire("hacs/status", {})

Expand Down Expand Up @@ -351,9 +341,3 @@ async def async_get_category_repositories(self, category: HacsCategory):
continue
continue
self.queue.add(self.factory.safe_register(repo, category))

async def async_set_stage(self, stage: str) -> None:
"""Set the stage of HACS."""
self.stage = HacsStage(stage)
self.log.info("Stage changed: %s", self.stage)
self.hass.bus.async_fire("hacs/stage", {"stage": self.stage})
43 changes: 0 additions & 43 deletions custom_components/hacs/helpers/functions/constrains.py

This file was deleted.

Loading

0 comments on commit 189f72e

Please sign in to comment.