1010import dateutil .parser
1111import pytest
1212import responses
13+ from responses import registries
1314
15+ from urllib3 .util .retry import Retry
1416from harmony .request import BBox , Collection , LinkType , Request , Dimension , CapabilitiesRequest , \
1517 AddLabelsRequest , DeleteLabelsRequest , JobsRequest
1618from harmony .client import Client , ProcessingFailedException , DEFAULT_JOB_LABEL
@@ -1482,12 +1484,6 @@ def test_handle_error_response_with_description_key():
14821484 status = 500 ,
14831485 json = error
14841486 )
1485- responses .add (
1486- responses .GET ,
1487- expected_status_url (job_id ),
1488- status = 500 ,
1489- json = error
1490- )
14911487 with pytest .raises (Exception ) as e :
14921488 Client (should_validate_auth = False ).submit (request )
14931489 assert str (e .value ) == f"('Internal Server Error', '{ error ['description' ]} ')"
@@ -1499,6 +1495,7 @@ def test_handle_error_response_with_description_key():
14991495 with pytest .raises (Exception ) as e :
15001496 Client (should_validate_auth = False ).progress (job_id )
15011497 assert str (e .value ) == f"('Internal Server Error', '{ error ['description' ]} ')"
1498+ assert len (responses .calls ) == 9
15021499
15031500@responses .activate
15041501def test_handle_error_response_no_description_key ():
@@ -1521,12 +1518,6 @@ def test_handle_error_response_no_description_key():
15211518 status = 500 ,
15221519 json = error
15231520 )
1524- responses .add (
1525- responses .GET ,
1526- expected_status_url (job_id ),
1527- status = 500 ,
1528- json = error
1529- )
15301521 with pytest .raises (Exception ) as e :
15311522 Client (should_validate_auth = False ).submit (request )
15321523 assert "500 Server Error: Internal Server Error for url" in str (e .value )
@@ -1538,6 +1529,8 @@ def test_handle_error_response_no_description_key():
15381529 with pytest .raises (Exception ) as e :
15391530 Client (should_validate_auth = False ).progress (job_id )
15401531 assert "500 Server Error: Internal Server Error for url" in str (e .value )
1532+ # Check retries
1533+ assert len (responses .calls ) == 9 # (1 + 4 + 4) # Post isn't retried.
15411534
15421535@responses .activate
15431536def test_handle_error_response_no_json ():
@@ -1559,12 +1552,6 @@ def test_handle_error_response_no_json():
15591552 status = 500 ,
15601553 body = 'error'
15611554 )
1562- responses .add (
1563- responses .GET ,
1564- expected_status_url (job_id ),
1565- status = 500 ,
1566- body = 'error'
1567- )
15681555 with pytest .raises (Exception ) as e :
15691556 Client (should_validate_auth = False ).submit (request )
15701557 assert "500 Server Error: Internal Server Error for url" in str (e .value )
@@ -1576,6 +1563,9 @@ def test_handle_error_response_no_json():
15761563 with pytest .raises (Exception ) as e :
15771564 Client (should_validate_auth = False ).progress (job_id )
15781565 assert "500 Server Error: Internal Server Error for url" in str (e .value )
1566+ # Check retries
1567+ assert len (responses .calls ) == 9 # (1 + 4 + 4)
1568+
15791569
15801570@responses .activate
15811571def test_handle_error_response_invalid_json ():
@@ -1597,12 +1587,6 @@ def test_handle_error_response_invalid_json():
15971587 status = 500 ,
15981588 json = 'error'
15991589 )
1600- responses .add (
1601- responses .GET ,
1602- expected_status_url (job_id ),
1603- status = 500 ,
1604- json = 'error'
1605- )
16061590 with pytest .raises (Exception ) as e :
16071591 Client (should_validate_auth = False ).submit (request )
16081592 assert "500 Server Error: Internal Server Error for url" in str (e .value )
@@ -1614,6 +1598,87 @@ def test_handle_error_response_invalid_json():
16141598 with pytest .raises (Exception ) as e :
16151599 Client (should_validate_auth = False ).progress (job_id )
16161600 assert "500 Server Error: Internal Server Error for url" in str (e .value )
1601+ # Check retries
1602+ assert len (responses .calls ) == 9 # (1 + 4 + 4)
1603+
1604+ @responses .activate
1605+ def test_handle_non_transient_error_no_retry ():
1606+ job_id = '89733-badc-1324'
1607+ collection = Collection (id = 'F229040468263-STRP' )
1608+ request = Request (
1609+ collection = collection ,
1610+ spatial = BBox (- 107 , 40 , - 105 , 42 )
1611+ )
1612+ responses .add (
1613+ responses .POST ,
1614+ expected_submit_url (collection .id ),
1615+ status = 200 ,
1616+ json = expected_job (collection .id , 'abcd-1234' )
1617+ )
1618+ responses .add (
1619+ responses .GET ,
1620+ expected_status_url (job_id ),
1621+ status = 431 ,
1622+ json = 'no-retry error'
1623+ )
1624+
1625+ Client (should_validate_auth = False ).submit (request )
1626+
1627+ with pytest .raises (Exception ) as e :
1628+ Client (should_validate_auth = False ).status (job_id )
1629+ assert "431 Client Error: Request Header Fields Too Large for url" in str (e .value )
1630+
1631+ # Check no retries
1632+ assert len (responses .calls ) == 2
1633+
1634+ @responses .activate (registry = registries .OrderedRegistry )
1635+ def test_handle_transient_error_responses ():
1636+ job_id = '3141592653-acbd-1234'
1637+ collection = Collection (id = 'C1342468263-ANYTHING' )
1638+ request = Request (
1639+ collection = collection ,
1640+ spatial = BBox (- 107 , 40 , - 105 , 42 )
1641+ )
1642+ responses .add (
1643+ responses .POST ,
1644+ expected_submit_url (collection .id ),
1645+ status = 200 ,
1646+ json = expected_job (collection .id , 'abcd-1234' ),
1647+ )
1648+ first_success = responses .add (
1649+ responses .GET ,
1650+ expected_status_url (job_id ),
1651+ status = 200 ,
1652+ json = expected_job (collection .id , job_id )
1653+ )
1654+ first_retry = responses .add (
1655+ responses .GET ,
1656+ expected_status_url (job_id ),
1657+ status = 502 ,
1658+ json = 'error'
1659+ )
1660+ second_retry = responses .add (
1661+ responses .GET ,
1662+ expected_status_url (job_id ),
1663+ status = 502 ,
1664+ json = 'error'
1665+ )
1666+ last_success = responses .add (
1667+ responses .GET ,
1668+ expected_status_url (job_id ),
1669+ status = 200 ,
1670+ json = expected_job (collection .id , job_id )
1671+ )
1672+
1673+ Client (should_validate_auth = False ).submit (request )
1674+ Client (should_validate_auth = False ).status (job_id )
1675+ Client (should_validate_auth = False ).status (job_id )
1676+
1677+ assert first_success .call_count == 1
1678+ assert first_retry .call_count == 1
1679+ assert second_retry .call_count == 1
1680+ assert last_success .call_count == 1
1681+
16171682
16181683def test_request_as_curl_get ():
16191684 collection = Collection (id = 'C1940468263-POCLOUD' )
@@ -1845,4 +1910,4 @@ def test_client_custom_environment_not_affected_by_env_var():
18451910 assert client .config .environment == Environment .UAT
18461911 assert client .config .harmony_hostname == 'harmony.uat.earthdata.nasa.gov'
18471912
1848- del os .environ ['ENVIRONMENT' ]
1913+ del os .environ ['ENVIRONMENT' ]
0 commit comments