Skip to content

Commit 26f440f

Browse files
authored
Add request retry mechanism (unit-finance#143)
* added backoff to requests * remove prints * retries default is 1 now * retries default is 0 now * changed init method, added retries param * remove print * split to functions according to code and added idempotency_key_is_not_present check * remove MAX_DURATION * pr comment * - idempotency_key_is_present - added post_create function for create requests with idempotency_key - backoff_idempotency_key_handler * update README.md * update README.md
1 parent fe47253 commit 26f440f

34 files changed

+177
-89
lines changed

README.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,28 @@ Fetching a customer
5656
```python
5757
import os
5858
from unit import Unit
59-
from unit.models.customer import *
6059

6160
token = os.environ.get("token")
6261
api_url = os.environ.get("api_url")
6362

6463
unit = Unit(api_url, token)
6564
customer = unit.customers.list().data[0]
6665
print(customer.id)
66+
```
67+
68+
## Retrying API Requests
69+
API requests can fail for many reasons, from network components failures, API rate limits, timeouts or service incidents.
70+
<br> Create requests without idempotency key won't trigger the retry mechanism, so we recommend to pass an idempotency key where applicable.
71+
72+
You can read about retries here: https://docs.unit.co/#retries. <br>
73+
74+
the default amount of retries is 0. <br>Unit initialization with retries:
75+
```python
76+
import os
77+
from unit import Unit
78+
79+
token = os.environ.get("token")
80+
api_url = os.environ.get("api_url")
81+
82+
unit = Unit(api_url, token, retries=3)
6783
```

e2e_tests/account_end_of_day_test.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,3 @@ def test_list_account_end_of_day():
1212
for a in response.data:
1313
assert a.type == "accountEndOfDay"
1414

15-
test_list_account_end_of_day()

e2e_tests/application_test.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import os
2-
import unittest
2+
import uuid
33
from datetime import timedelta
44
from unit import Unit
55
from unit.models.application import *
@@ -9,6 +9,7 @@
99

1010
ApplicationTypes = ["individualApplication", "businessApplication", "trustApplication"]
1111

12+
1213
def create_individual_application():
1314
device_fingerprint = DeviceFingerprint.from_json_api({
1415
"provider": "iovation",
@@ -21,6 +22,7 @@ def create_individual_application():
2122
Phone("1", "2025550108"),
2223
ssn="000000003",
2324
device_fingerprints=[device_fingerprint],
25+
idempotency_key=str(uuid.uuid1()),
2426
jwt_subject="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9fQ"
2527
)
2628

@@ -73,3 +75,4 @@ def test_update_business_application():
7375
updated = client.applications.update(PatchApplicationRequest(app.data.id, "businessApplication",
7476
tags={"patch": "test-patch"}))
7577
assert updated.data.type == "businessApplication"
78+

e2e_tests/event_test.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,3 @@ def test_fire_event():
2222
response = client.events.fire(event_id)
2323
assert response.data == []
2424

25-

e2e_tests/payment_test.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ def create_book_payment():
2222

2323
def test_list_and_get_payments():
2424
payments_ids = []
25+
2526
response = client.payments.list()
2627

2728
for t in response.data:

requirements-dev.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
requests==2.26.0
22
pytest
3+
backoff

requirements.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
requests~=2.28.0
2+
backoff~=2.1.2c
3+
pytest

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
keywords=['unit', 'finance', 'banking',
1313
'banking-as-a-service', 'API', 'SDK'],
1414
install_requires=[
15-
'requests'
15+
'requests', 'backoff'
1616
],
1717
classifiers=[
1818
'Development Status :: 4 - Beta',

unit/__init__.py

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -27,28 +27,28 @@
2727

2828

2929
class Unit(object):
30-
def __init__(self, api_url, token):
31-
self.applications = ApplicationResource(api_url, token)
32-
self.customers = CustomerResource(api_url, token)
33-
self.accounts = AccountResource(api_url, token)
34-
self.cards = CardResource(api_url, token)
35-
self.transactions = TransactionResource(api_url, token)
36-
self.payments = PaymentResource(api_url, token)
37-
self.statements = StatementResource(api_url, token)
38-
self.customerTokens = CustomerTokenResource(api_url, token)
39-
self.counterparty = CounterpartyResource(api_url, token)
40-
self.returnAch = ReturnAchResource(api_url, token)
41-
self.applicationForms = ApplicationFormResource(api_url, token)
42-
self.fees = FeeResource(api_url, token)
43-
self.events = EventResource(api_url, token)
44-
self.webhooks = WebhookResource(api_url, token)
45-
self.institutions = InstitutionResource(api_url, token)
46-
self.atmLocations = AtmLocationResource(api_url, token)
47-
self.billPays = BillPayResource(api_url, token)
48-
self.api_tokens = APITokenResource(api_url, token)
49-
self.authorizations = AuthorizationResource(api_url, token)
50-
self.authorization_requests = AuthorizationRequestResource(api_url, token)
51-
self.account_end_of_day = AccountEndOfDayResource(api_url, token)
52-
self.checkDeposits = CheckDepositResource(api_url, token)
53-
self.disputes = DisputeResource(api_url, token)
54-
self.rewards = RewardResource(api_url, token)
30+
def __init__(self, api_url, token, retries=0):
31+
self.applications = ApplicationResource(api_url, token, retries)
32+
self.customers = CustomerResource(api_url, token, retries)
33+
self.accounts = AccountResource(api_url, token, retries)
34+
self.cards = CardResource(api_url, token, retries)
35+
self.transactions = TransactionResource(api_url, token, retries)
36+
self.payments = PaymentResource(api_url, token, retries)
37+
self.statements = StatementResource(api_url, token, retries)
38+
self.customerTokens = CustomerTokenResource(api_url, token, retries)
39+
self.counterparty = CounterpartyResource(api_url, token, retries)
40+
self.returnAch = ReturnAchResource(api_url, token, retries)
41+
self.applicationForms = ApplicationFormResource(api_url, token, retries)
42+
self.fees = FeeResource(api_url, token, retries)
43+
self.events = EventResource(api_url, token, retries)
44+
self.webhooks = WebhookResource(api_url, token, retries)
45+
self.institutions = InstitutionResource(api_url, token, retries)
46+
self.atmLocations = AtmLocationResource(api_url, token, retries)
47+
self.billPays = BillPayResource(api_url, token, retries)
48+
self.api_tokens = APITokenResource(api_url, token, retries)
49+
self.authorizations = AuthorizationResource(api_url, token, retries)
50+
self.authorization_requests = AuthorizationRequestResource(api_url, token, retries)
51+
self.account_end_of_day = AccountEndOfDayResource(api_url, token, retries)
52+
self.checkDeposits = CheckDepositResource(api_url, token, retries)
53+
self.disputes = DisputeResource(api_url, token, retries)
54+
self.rewards = RewardResource(api_url, token, retries)

unit/api/account_end_of_day_resource.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55

66
class AccountEndOfDayResource(BaseResource):
7-
def __init__(self, api_url, token):
8-
super().__init__(api_url, token)
7+
def __init__(self, api_url, token, retries):
8+
super().__init__(api_url, token, retries)
99
self.resource = "account-end-of-day"
1010

1111
def list(self, params: ListAccountEndOfDayParams = None) -> Union[UnitResponse[List[AccountEndOfDayDTO]], UnitError]:

0 commit comments

Comments
 (0)