|
6 | 6 |
|
7 | 7 | import tempfile |
8 | 8 | from collections import defaultdict |
| 9 | +from concurrent.futures import ThreadPoolExecutor |
9 | 10 | from functools import lru_cache |
10 | 11 | from logging import getLogger |
11 | 12 | from typing import Any |
@@ -100,18 +101,30 @@ def compute_packages_of_request_from_source_report( |
100 | 101 | request: osc.core.Request, |
101 | 102 | ) -> tuple[defaultdict[str, set[Package]], int]: |
102 | 103 | """Compute the package diff of a request based on source reports.""" |
| 104 | + # target projects (e.g. `SUSE:Products:SLE-Product-SLES:16.0:aarch64`) |
103 | 105 | repo_a: defaultdict[str, set[Package]] = defaultdict(set) |
| 106 | + # source projects (e.g. `SUSE:SLFO:Products:SLES:16.0:TEST`) |
104 | 107 | repo_b: defaultdict[str, set[Package]] = defaultdict(set) |
105 | 108 |
|
106 | | - for action in request.actions: |
107 | | - log.debug("Checking action '%s' -> '%s' of request %s", action.src_project, action.tgt_project, request.reqid) |
108 | | - # add packages for target project (e.g. `SUSE:Products:SLE-Product-SLES:16.0:aarch64`), that is repo "A" |
109 | | - load_packages_from_source_report( |
110 | | - action, OBSBinary(action.tgt_project, action.src_package, "images", "local"), repo_a |
111 | | - ) |
112 | | - # add packages for source project (e.g. `SUSE:SLFO:Products:SLES:16.0:TEST`), that is repo "B" |
113 | | - load_packages_from_source_report( |
114 | | - action, OBSBinary(action.src_project, action.src_package, "product", "local"), repo_b |
115 | | - ) |
| 109 | + def worker(action: Any, binary: OBSBinary) -> defaultdict[str, set[Package]]: # noqa: ANN401 |
| 110 | + packages: defaultdict[str, set[Package]] = defaultdict(set) |
| 111 | + load_packages_from_source_report(action, binary, packages) |
| 112 | + return packages |
| 113 | + |
| 114 | + tasks = [ |
| 115 | + *((a, OBSBinary(a.tgt_project, a.src_package, "images", "local")) for a in request.actions), |
| 116 | + *((a, OBSBinary(a.src_project, a.src_package, "product", "local")) for a in request.actions), |
| 117 | + ] |
| 118 | + |
| 119 | + with ThreadPoolExecutor() as executor: |
| 120 | + # Use executor.map to ensure exceptions are raised if they occur in threads |
| 121 | + results = list(executor.map(lambda p: worker(*p), tasks)) |
| 122 | + |
| 123 | + # results contains first all "target" projects, then all "source" projects |
| 124 | + num_actions = len(request.actions) |
| 125 | + for i, res in enumerate(results): |
| 126 | + target_repo = repo_a if i < num_actions else repo_b |
| 127 | + for arch, pks in res.items(): |
| 128 | + target_repo[arch].update(pks) |
116 | 129 |
|
117 | 130 | return RepoDiff.compute_diff_for_packages("product repo", repo_a, "TEST repo", repo_b) |
0 commit comments