Skip to content

Commit

Permalink
Fix ActionKit collect_upload_errors() Bug (move-coop#979)
Browse files Browse the repository at this point in the history
* Check is_completed rather than status not new

* Gather all errors for each upload

* Add tests, replace while with for loop

* Refactor errors.extend for readability
  • Loading branch information
technicalex authored Jan 26, 2024
1 parent 54c5d74 commit 9fe215f
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 8 deletions.
28 changes: 22 additions & 6 deletions parsons/action_kit/action_kit.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import logging
import requests
import time
import math

from parsons.etl.table import Table
from parsons.utilities import check_env
Expand Down Expand Up @@ -1307,15 +1308,30 @@ def collect_upload_errors(self, result_array):
for res in result_array:
upload_id = res.get("id")
if upload_id:
# Pend until upload is complete
while True:
upload = self._base_get(endpoint="upload", entity_id=upload_id)
if not upload or upload.get("status") != "new":
if upload.get("is_completed"):
break
else:
time.sleep(1)
error_data = self._base_get(
endpoint="uploaderror", params={"upload": upload_id}
)
logger.debug(f"error collect result: {error_data}")
errors.extend(error_data.get("objects") or [])

# ActionKit limits length of error list returned
# Iterate until all errors are gathered
error_count = upload.get("has_errors")
limit = 20

error_pages = math.ceil(error_count / limit)
for page in range(0, error_pages):
error_data = self._base_get(
endpoint="uploaderror",
params={
"upload": upload_id,
"_limit": limit,
"_offset": page * limit,
},
)
logger.debug(f"error collect result: {error_data}")
errors.extend(error_data.get("objects", []))

return errors
27 changes: 25 additions & 2 deletions test/test_action_kit.py
Original file line number Diff line number Diff line change
Expand Up @@ -714,8 +714,31 @@ def test_table_split(self):
)

def test_collect_errors(self):
resp_mock = mock.MagicMock()
type(resp_mock.get()).json = lambda x: {"is_completed": True, "has_errors": 25}
self.actionkit.conn = resp_mock

self.actionkit.collect_upload_errors([{"id": "12345"}])
self.actionkit.conn.get.assert_called_with(

self.actionkit.conn.get.assert_any_call(
"https://domain.actionkit.com/rest/v1/upload/12345/", params=None
)

# With 25 errors, we will view two pages
self.actionkit.conn.get.assert_any_call(
"https://domain.actionkit.com/rest/v1/uploaderror/",
params={"upload": "12345"},
params={"upload": "12345", "_limit": 20, "_offset": 0},
)
self.actionkit.conn.get.assert_any_call(
"https://domain.actionkit.com/rest/v1/uploaderror/",
params={"upload": "12345", "_limit": 20, "_offset": 20},
)

# Assert that we don't attempt to view a third page
assert (
mock.call(
"https://domain.actionkit.com/rest/v1/uploaderror/",
params={"upload": "12345", "_limit": 20, "_offset": 40},
)
not in self.actionkit.conn.get.call_args_list
), "Called with invalid arguments."

0 comments on commit 9fe215f

Please sign in to comment.