🎨 SourceIterator can yield addtitional data
SourceIterator-s can yield a game and a tuple of additional data. This data will be passed to the Store, Pipeline and Managers.
This commit is contained in:
@@ -26,16 +26,18 @@ class AsyncManager(Manager):
|
||||
Already scheduled Tasks will no longer be cancellable."""
|
||||
self.cancellable = Gio.Cancellable()
|
||||
|
||||
def process_game(self, game: Game, callback: Callable[["Manager"], Any]) -> None:
|
||||
def process_game(
|
||||
self, game: Game, additional_data: tuple, callback: Callable[["Manager"], Any]
|
||||
) -> None:
|
||||
"""Create a task to process the game in a separate thread"""
|
||||
task = Task.new(None, self.cancellable, self._task_callback, (callback,))
|
||||
task.set_task_data((game,))
|
||||
task.set_task_data((game, additional_data))
|
||||
task.run_in_thread(self._task_thread_func)
|
||||
|
||||
def _task_thread_func(self, _task, _source_object, data, cancellable):
|
||||
"""Task thread entry point"""
|
||||
game, *_rest = data
|
||||
self.execute_resilient_manager_logic(game)
|
||||
game, additional_data, *_rest = data
|
||||
self.execute_resilient_manager_logic(game, additional_data)
|
||||
|
||||
def _task_callback(self, _source_object, _result, data):
|
||||
"""Method run after the task is done"""
|
||||
|
||||
@@ -10,7 +10,7 @@ class DisplayManager(Manager):
|
||||
|
||||
run_after = set((SteamAPIManager, SGDBManager))
|
||||
|
||||
def manager_logic(self, game: Game) -> None:
|
||||
def manager_logic(self, game: Game, _additional_data: tuple) -> None:
|
||||
# TODO decouple a game from its widget
|
||||
shared.win.games[game.game_id] = game
|
||||
game.update()
|
||||
|
||||
@@ -8,5 +8,5 @@ class FileManager(AsyncManager):
|
||||
|
||||
run_after = set((SteamAPIManager,))
|
||||
|
||||
def manager_logic(self, game: Game) -> None:
|
||||
def manager_logic(self, game: Game, _additional_data: tuple) -> None:
|
||||
game.save()
|
||||
|
||||
@@ -37,7 +37,7 @@ class Manager:
|
||||
self.errors_lock = Lock()
|
||||
|
||||
def report_error(self, error: Exception):
|
||||
"""Report an error that happened in Manager.run"""
|
||||
"""Report an error that happened in Manager.process_game"""
|
||||
with self.errors_lock:
|
||||
self.errors.append(error)
|
||||
|
||||
@@ -49,7 +49,7 @@ class Manager:
|
||||
return errors
|
||||
|
||||
@abstractmethod
|
||||
def manager_logic(self, game: Game) -> None:
|
||||
def manager_logic(self, game: Game, additional_data: tuple) -> None:
|
||||
"""
|
||||
Manager specific logic triggered by the run method
|
||||
* Implemented by final child classes
|
||||
@@ -58,10 +58,12 @@ class Manager:
|
||||
* May raise other exceptions that will be reported
|
||||
"""
|
||||
|
||||
def execute_resilient_manager_logic(self, game: Game, try_index: int = 0) -> None:
|
||||
def execute_resilient_manager_logic(
|
||||
self, game: Game, additional_data: tuple, try_index: int = 0
|
||||
) -> None:
|
||||
"""Execute the manager logic and handle its errors by reporting them or retrying"""
|
||||
try:
|
||||
self.manager_logic(game)
|
||||
self.manager_logic(game, additional_data)
|
||||
except Exception as error:
|
||||
if error in self.continue_on:
|
||||
# Handle skippable errors (skip silently)
|
||||
@@ -71,7 +73,9 @@ class Manager:
|
||||
# Handle retryable errors
|
||||
logging_format = "Retrying %s in %s for %s"
|
||||
sleep(self.retry_delay)
|
||||
self.execute_resilient_manager_logic(game, try_index + 1)
|
||||
self.execute_resilient_manager_logic(
|
||||
game, additional_data, try_index + 1
|
||||
)
|
||||
else:
|
||||
# Handle being out of retries
|
||||
logging_format = "Out of retries dues to %s in %s for %s"
|
||||
@@ -88,7 +92,9 @@ class Manager:
|
||||
f"{game.name} ({game.game_id})",
|
||||
)
|
||||
|
||||
def process_game(self, game: Game, callback: Callable[["Manager"], Any]) -> None:
|
||||
def process_game(
|
||||
self, game: Game, additional_data: tuple, callback: Callable[["Manager"], Any]
|
||||
) -> None:
|
||||
"""Pass the game through the manager"""
|
||||
self.execute_resilient_manager_logic(game)
|
||||
self.execute_resilient_manager_logic(game, additional_data)
|
||||
callback(self)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
from urllib3.exceptions import SSLError
|
||||
|
||||
from src.game import Game
|
||||
from src.store.managers.async_manager import AsyncManager
|
||||
from src.store.managers.steam_api_manager import SteamAPIManager
|
||||
@@ -8,9 +10,9 @@ class SGDBManager(AsyncManager):
|
||||
"""Manager in charge of downloading a game's cover from steamgriddb"""
|
||||
|
||||
run_after = set((SteamAPIManager,))
|
||||
retryable_on = set((HTTPError,))
|
||||
retryable_on = set((HTTPError, SSLError))
|
||||
|
||||
def manager_logic(self, game: Game) -> None:
|
||||
def manager_logic(self, game: Game, _additional_data: tuple) -> None:
|
||||
try:
|
||||
sgdb = SGDBHelper()
|
||||
sgdb.conditionaly_update_cover(game)
|
||||
|
||||
@@ -15,7 +15,7 @@ class SteamAPIManager(AsyncManager):
|
||||
|
||||
retryable_on = set((HTTPError, SSLError))
|
||||
|
||||
def manager_logic(self, game: Game) -> None:
|
||||
def manager_logic(self, game: Game, _additional_data: tuple) -> None:
|
||||
# Skip non-steam games
|
||||
if not game.source.startswith("steam_"):
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user