Skip to content

Commit daae7bf

Browse files
committed
add task response
1 parent 2220aad commit daae7bf

5 files changed

Lines changed: 142 additions & 32 deletions

File tree

functions-python/tasks_executor/README.md

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -68,17 +68,6 @@ To update the geolocation files precision:
6868
}
6969
```
7070

71-
To populate license rules:
72-
73-
```json
74-
{
75-
"task": "populate_license_rules",
76-
"payload": {
77-
"dry_run": true
78-
}
79-
}
80-
```
81-
8271
To populate licenses:
8372

8473
```json

functions-python/tasks_executor/src/tasks/licenses/populate_license_rules.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,10 @@ def populate_license_rules(dry_run, db_session):
6060
logging.info(
6161
"Loaded %d rules from %d categories.", len(rules_data), len(rules_json)
6262
)
63-
63+
result = ""
6464
if dry_run:
65-
logging.info("Dry run: would insert/update %d rules.", len(rules_data))
65+
result = "Dry run: would insert/update %d rules.", len(rules_data)
66+
logging.info(result)
6667
else:
6768
for rule_data in rules_data:
6869
rule_object = Rule(
@@ -73,9 +74,11 @@ def populate_license_rules(dry_run, db_session):
7374
)
7475
db_session.merge(rule_object)
7576

76-
logging.info(
77-
"Successfully upserted %d rules into the database.", len(rules_data)
77+
result = "Successfully upserted %d rules into the database.", len(
78+
rules_data
7879
)
80+
logging.info(result)
81+
return result
7982

8083
except requests.exceptions.RequestException as e:
8184
logging.error("Failed to download rules JSON file: %s", e)

functions-python/tasks_executor/src/tasks/licenses/populate_license_tags.py

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,10 @@ def populate_license_tags(dry_run, db_session):
7474
len(tags_data),
7575
)
7676

77+
result = ""
7778
if dry_run:
78-
logging.info(
79-
"Dry run: would insert/update %d groups and %d tags.",
80-
len(groups_data),
81-
len(tags_data),
82-
)
79+
result = f"Dry run: would insert/update {len(groups_data)} groups and {len(tags_data)} tags."
80+
logging.info(result)
8381
else:
8482
# Upsert groups first so FK from license_tag.group is satisfied
8583
for group in groups_data.values():
@@ -100,12 +98,10 @@ def populate_license_tags(dry_run, db_session):
10098
url=tag_data["url"],
10199
)
102100
db_session.merge(tag_object)
103-
104-
logging.info(
105-
"Successfully upserted %d groups and %d tags into the database.",
106-
len(groups_data),
107-
len(tags_data),
101+
result = (
102+
f"Successfully upserted {len(groups_data)} groups and {len(tags_data)} tags into the database.",
108103
)
104+
logging.info(result)
109105

110106
except requests.exceptions.RequestException as e:
111107
logging.error("Failed to download tags JSON file: %s", e)

functions-python/tasks_executor/src/tasks/licenses/populate_licenses.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,14 @@ def populate_licenses_handler(payload):
4646
payload (dict): Incoming payload data.
4747
"""
4848
dry_run = get_parameters(payload)
49-
populate_license_rules(dry_run)
50-
populate_license_tags(dry_run)
51-
return populate_licenses_task(dry_run)
49+
rules_result = populate_license_rules(dry_run)
50+
tags_result = populate_license_tags(dry_run)
51+
license_result = populate_licenses_task(dry_run)
52+
return {
53+
"rules": rules_result,
54+
"tags": tags_result,
55+
"licenses": license_result,
56+
}
5257

5358

5459
@with_db_session
@@ -166,10 +171,9 @@ def populate_licenses_task(dry_run, db_session):
166171
# including their rule and tag associations.
167172
if not is_new:
168173
db_session.merge(license_object)
169-
170-
logging.info(
171-
"Successfully upserted licenses into the database.",
172-
)
174+
result = "Successfully upserted licenses into the database."
175+
logging.info(result)
176+
return result
173177

174178
except requests.exceptions.RequestException as e:
175179
logging.error("Failed to download licenses JSON file: %s", e)

functions-python/tasks_executor/tests/tasks/populate_licenses_and_rules/test_populate_licenses.py

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from shared.database_gen.sqlacodegen_models import LicenseTag, Rule
77
from tasks.licenses.populate_licenses import (
88
LICENSES_API_URL,
9+
populate_licenses_handler,
910
populate_licenses_task,
1011
)
1112

@@ -182,5 +183,122 @@ def test_request_exception_handling(self, mock_get):
182183
mock_db_session.rollback.assert_not_called()
183184

184185

186+
class TestPopulateLicensesHandler(unittest.TestCase):
187+
"""Tests for the populate_licenses_handler orchestration function."""
188+
189+
@patch("tasks.licenses.populate_licenses.populate_licenses_task")
190+
@patch("tasks.licenses.populate_licenses.populate_license_tags")
191+
@patch("tasks.licenses.populate_licenses.populate_license_rules")
192+
def test_handler_calls_all_subtasks_and_returns_combined_result(
193+
self, mock_rules, mock_tags, mock_licenses
194+
):
195+
"""Handler should call all three sub-tasks and return a dict with their results."""
196+
mock_rules.return_value = "rules_result"
197+
mock_tags.return_value = "tags_result"
198+
mock_licenses.return_value = "licenses_result"
199+
200+
result = populate_licenses_handler({"dry_run": False})
201+
202+
mock_rules.assert_called_once_with(False)
203+
mock_tags.assert_called_once_with(False)
204+
mock_licenses.assert_called_once_with(False)
205+
self.assertEqual(
206+
result,
207+
{
208+
"rules": "rules_result",
209+
"tags": "tags_result",
210+
"licenses": "licenses_result",
211+
},
212+
)
213+
214+
@patch("tasks.licenses.populate_licenses.populate_licenses_task")
215+
@patch("tasks.licenses.populate_licenses.populate_license_tags")
216+
@patch("tasks.licenses.populate_licenses.populate_license_rules")
217+
def test_handler_dry_run_passes_flag_to_subtasks(
218+
self, mock_rules, mock_tags, mock_licenses
219+
):
220+
"""Handler should propagate dry_run=True to every sub-task."""
221+
mock_rules.return_value = "Dry run: would insert/update 0 rules."
222+
mock_tags.return_value = "Dry run: would insert/update 0 groups and 0 tags."
223+
mock_licenses.return_value = None
224+
225+
result = populate_licenses_handler({"dry_run": True})
226+
227+
mock_rules.assert_called_once_with(True)
228+
mock_tags.assert_called_once_with(True)
229+
mock_licenses.assert_called_once_with(True)
230+
self.assertEqual(result["rules"], "Dry run: would insert/update 0 rules.")
231+
self.assertEqual(
232+
result["tags"], "Dry run: would insert/update 0 groups and 0 tags."
233+
)
234+
self.assertIsNone(result["licenses"])
235+
236+
@patch("tasks.licenses.populate_licenses.populate_licenses_task")
237+
@patch("tasks.licenses.populate_licenses.populate_license_tags")
238+
@patch("tasks.licenses.populate_licenses.populate_license_rules")
239+
def test_handler_defaults_dry_run_to_false_when_missing(
240+
self, mock_rules, mock_tags, mock_licenses
241+
):
242+
"""Handler should default dry_run to False when the key is absent from the payload."""
243+
mock_rules.return_value = None
244+
mock_tags.return_value = None
245+
mock_licenses.return_value = None
246+
247+
populate_licenses_handler({})
248+
249+
mock_rules.assert_called_once_with(False)
250+
mock_tags.assert_called_once_with(False)
251+
mock_licenses.assert_called_once_with(False)
252+
253+
@patch("tasks.licenses.populate_licenses.populate_licenses_task")
254+
@patch("tasks.licenses.populate_licenses.populate_license_tags")
255+
@patch("tasks.licenses.populate_licenses.populate_license_rules")
256+
def test_handler_propagates_exception_from_rules(
257+
self, mock_rules, mock_tags, mock_licenses
258+
):
259+
"""If populate_license_rules raises, the handler should propagate the exception
260+
and the downstream sub-tasks should not be called."""
261+
mock_rules.side_effect = requests.exceptions.RequestException("Network error")
262+
263+
with self.assertRaises(requests.exceptions.RequestException):
264+
populate_licenses_handler({"dry_run": False})
265+
266+
mock_tags.assert_not_called()
267+
mock_licenses.assert_not_called()
268+
269+
@patch("tasks.licenses.populate_licenses.populate_licenses_task")
270+
@patch("tasks.licenses.populate_licenses.populate_license_tags")
271+
@patch("tasks.licenses.populate_licenses.populate_license_rules")
272+
def test_handler_propagates_exception_from_tags(
273+
self, mock_rules, mock_tags, mock_licenses
274+
):
275+
"""If populate_license_tags raises, the handler should propagate the exception
276+
and populate_licenses_task should not be called."""
277+
mock_rules.return_value = "rules_result"
278+
mock_tags.side_effect = requests.exceptions.RequestException("Network error")
279+
280+
with self.assertRaises(requests.exceptions.RequestException):
281+
populate_licenses_handler({"dry_run": False})
282+
283+
mock_licenses.assert_not_called()
284+
285+
@patch("tasks.licenses.populate_licenses.populate_licenses_task")
286+
@patch("tasks.licenses.populate_licenses.populate_license_tags")
287+
@patch("tasks.licenses.populate_licenses.populate_license_rules")
288+
def test_handler_result_keys_are_always_present(
289+
self, mock_rules, mock_tags, mock_licenses
290+
):
291+
"""The returned dict must always contain the three expected keys."""
292+
mock_rules.return_value = None
293+
mock_tags.return_value = None
294+
mock_licenses.return_value = None
295+
296+
result = populate_licenses_handler({"dry_run": False})
297+
298+
self.assertIn("rules", result)
299+
self.assertIn("tags", result)
300+
self.assertIn("licenses", result)
301+
302+
185303
if __name__ == "__main__":
186304
unittest.main()

0 commit comments

Comments
 (0)