Add dependency-based cache to game support algorithm

This commit is contained in:
rubenwardy 2024-03-29 16:02:32 +00:00
parent b33a7f79b1
commit a8d2cc0383
2 changed files with 11 additions and 5 deletions

@ -14,7 +14,7 @@
# You should have received a copy of the GNU Affero General Public License # You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
from typing import List, Dict, Optional from typing import List, Dict, Optional, Tuple
import sqlalchemy import sqlalchemy
@ -93,10 +93,12 @@ class GSPackage:
class GameSupport: class GameSupport:
packages: Dict[str, GSPackage] packages: Dict[str, GSPackage]
modified_packages: set[GSPackage] modified_packages: set[GSPackage]
dependency_cache: Dict[str, Tuple[Optional[bool], Optional[set[str]]]]
def __init__(self): def __init__(self):
self.packages = {} self.packages = {}
self.modified_packages = set() self.modified_packages = set()
self.dependency_cache = {}
@property @property
def all_confirmed(self): def all_confirmed(self):
@ -135,6 +137,10 @@ class GameSupport:
dep_supports_all = False dep_supports_all = False
for_dep = set() for_dep = set()
if depend in self.dependency_cache:
dep_supports_all, for_dep = self.dependency_cache[depend]
return dep_supports_all, for_dep
for provider in self.get_all_that_provide(depend): for provider in self.get_all_that_provide(depend):
found_in = self._get_supported_games(provider, visited) found_in = self._get_supported_games(provider, visited)
if found_in is None: if found_in is None:
@ -146,6 +152,7 @@ class GameSupport:
else: else:
for_dep.update(found_in) for_dep.update(found_in)
self.dependency_cache[depend] = (dep_supports_all, for_dep)
return dep_supports_all, for_dep return dep_supports_all, for_dep
def _get_supported_games_for_deps(self, package: GSPackage, visited: list[str]) -> Optional[set[str]]: def _get_supported_games_for_deps(self, package: GSPackage, visited: list[str]) -> Optional[set[str]]:
@ -214,6 +221,7 @@ class GameSupport:
return package.supported_games return package.supported_games
def on_update(self, package: GSPackage, old_provides: Optional[set[str]] = None): def on_update(self, package: GSPackage, old_provides: Optional[set[str]] = None):
self.dependency_cache = {}
to_update = {package} to_update = {package}
checked = set() checked = set()
@ -235,10 +243,12 @@ class GameSupport:
checked.add(depending_package) checked.add(depending_package)
def on_remove(self, package: GSPackage): def on_remove(self, package: GSPackage):
self.dependency_cache = {}
del self.packages[package.id_] del self.packages[package.id_]
self.on_update(package) self.on_update(package)
def on_first_run(self): def on_first_run(self):
self.dependency_cache = {}
for package in self.packages.values(): for package in self.packages.values():
if not package.is_confirmed: if not package.is_confirmed:
self.on_update(package) self.on_update(package)

@ -204,11 +204,9 @@ def test_cycle():
support.on_update(modA) support.on_update(modA)
assert support.all_errors == { assert support.all_errors == {
"author/mod_a: Dependency cycle detected: author/mod_b -> author/mod_a -> author/mod_b",
"author/mod_b: Dependency cycle detected: author/mod_a -> author/mod_b -> author/mod_a", "author/mod_b: Dependency cycle detected: author/mod_a -> author/mod_b -> author/mod_a",
"author/mod_a: Dependency cycle detected: author/mod_a -> author/mod_b -> author/mod_a", "author/mod_a: Dependency cycle detected: author/mod_a -> author/mod_b -> author/mod_a",
"author/mod_b: Unable to fulfill dependency mod_a", "author/mod_b: Unable to fulfill dependency mod_a",
"author/mod_b: Dependency cycle detected: author/mod_b -> author/mod_a -> author/mod_b",
"author/mod_a: Unable to fulfill dependency mod_b" "author/mod_a: Unable to fulfill dependency mod_b"
} }
@ -377,9 +375,7 @@ def test_update_cycle():
assert support.all_errors == { assert support.all_errors == {
"author/mod_c: Dependency cycle detected: author/mod_a -> author/mod_c -> author/mod_a", "author/mod_c: Dependency cycle detected: author/mod_a -> author/mod_c -> author/mod_a",
"author/mod_a: Dependency cycle detected: author/mod_a -> author/mod_c -> author/mod_a", "author/mod_a: Dependency cycle detected: author/mod_a -> author/mod_c -> author/mod_a",
"author/mod_a: Dependency cycle detected: author/mod_c -> author/mod_a -> author/mod_c",
"author/mod_a: Unable to fulfill dependency mod_c", "author/mod_a: Unable to fulfill dependency mod_c",
"author/mod_c: Dependency cycle detected: author/mod_c -> author/mod_a -> author/mod_c",
"author/mod_c: Unable to fulfill dependency mod_a" "author/mod_c: Unable to fulfill dependency mod_a"
} }