Skip to content

Commit ae18e23

Browse files
author
Dario Vallejo
committed
Pull request #12: EOA-3340 Update Python SDK to manage auto refresh of the connections
Merge in SDK/python_telesign from fix/EOA-3340/UpdatePythonSDKToManageAutoRefreshOfTheConnections1 to developer * commit '9c9b77c6c277b2eadf740c1f4f129942a9bf8046': solving english texts deleting readme EOA-3340 python sdk with auto refresh Pull request #11: EOA-3340 Update Python SDK to manage auto refresh of the connections Pull request #11: EOA-3340 Update Python SDK to manage auto refresh of the connections
2 parents 0acc3ad + 9c9b77c commit ae18e23

File tree

4 files changed

+61
-6
lines changed

4 files changed

+61
-6
lines changed

README.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,4 @@ If you use a Telesign SDK to make your request, authentication is handled behind
3737

3838
* Learn to send a request to Telesign with code with one of our [tutorials](https://developer.telesign.com/enterprise/docs/tutorials).
3939
* Browse our [Developer Portal](https://developer.telesign.com) for tutorials, how-to guides, reference content, and more.
40-
* Check out our [sample code](https://github.com/TeleSign/sample_code) on GitHub.
41-
42-
40+
* Check out our [sample code](https://github.com/TeleSign/sample_code) on GitHub.

RELEASE

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
2.3.1
2+
- Adds automatic HTTP session recycling (`pool_recycle`).
3+
- Improves keep-alive connection handling.
4+
15
2.3.0
26
- Added PATCH method to the RestClient class to facilitate Update Verification Process action
37

telesign/rest.py

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from email.utils import formatdate
77
from hashlib import sha256
88
from platform import python_version
9+
import time
910

1011
import requests
1112
import json
@@ -52,7 +53,8 @@ def __init__(self,
5253
sdk_version_dependency=None,
5354
proxies=None,
5455
timeout=10,
55-
auth_method=None):
56+
auth_method=None,
57+
pool_recycle=480):
5658
"""
5759
Telesign RestClient useful for making generic RESTful requests against our API.
5860
@@ -62,13 +64,22 @@ def __init__(self,
6264
:param proxies: (optional) Dictionary mapping protocol or protocol and hostname to the URL of the proxy.
6365
:param timeout: (optional) How long to wait for the server to send data before giving up, as a float,
6466
or as a (connect timeout, read timeout) tuple
67+
:param pool_recycle: (optional) Time in seconds to recycle the HTTP session to avoid stale connections (default 480).
68+
If a session is older than this value, it will be closed and a new session will be created automatically before each request.
69+
This helps prevent errors due to HTTP keep-alive connections being closed by the server after inactivity.
70+
71+
HTTP Keep-Alive behavior:
72+
TeleSign endpoints close idle HTTP keep-alive connections after 499 seconds. If you attempt to reuse a connection older than this, you may get a 'connection reset by peer' error.
73+
By default, pool_recycle=480 ensures sessions are refreshed before this limit.
6574
"""
6675
self.customer_id = customer_id
6776
self.api_key = api_key
6877

6978
self.api_host = rest_endpoint
7079

71-
self.session = requests.Session()
80+
self.pool_recycle = pool_recycle
81+
self._session_created_at = None
82+
self.session = self._create_session()
7283

7384
self.session.proxies = proxies if proxies else {}
7485

@@ -234,6 +245,28 @@ def patch(self, resource, body=None, json_fields=None, **query_params):
234245
"""
235246
return self._execute(self.session.patch, 'PATCH', resource, body, json_fields, **query_params)
236247

248+
def _create_session(self):
249+
session = requests.Session()
250+
self._session_created_at = time.time()
251+
return session
252+
253+
def _ensure_session(self):
254+
if self._session_created_at is None or (time.time() - self._session_created_at > self.pool_recycle):
255+
if self.session:
256+
self.session.close()
257+
self.session = self._create_session()
258+
259+
def _create_session(self):
260+
session = requests.Session()
261+
self._session_created_at = time.time()
262+
return session
263+
264+
def _ensure_session(self):
265+
if self._session_created_at is None or (time.time() - self._session_created_at > self.pool_recycle):
266+
if self.session:
267+
self.session.close()
268+
self.session = self._create_session()
269+
237270
def _execute(self, method_function, method_name, resource, body=None, json_fields=None, **query_params):
238271
"""
239272
Generic Telesign REST API request handler.
@@ -245,6 +278,7 @@ def _execute(self, method_function, method_name, resource, body=None, json_field
245278
:param query_params: query_params to perform the HTTP request with, as a dictionary.
246279
:return: The RestClient Response object.
247280
"""
281+
self._ensure_session()
248282
resource_uri = "{api_host}{resource}".format(api_host=self.api_host, resource=resource)
249283

250284
url_encoded_fields = self._encode_params(query_params)

tests/test_rest.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,4 +290,23 @@ def test_post_basic_auth(self, mock_generate_telesign_headers):
290290
self.assertEqual(post_args, expected_post_args,
291291
"client.session.post.call_args args do not match expected")
292292
self.assertEqual(post_kwargs, expected_post_kwargs,
293-
"client.session.post.call_args kwargs do not match expected")
293+
"client.session.post.call_args kwargs do not match expected")
294+
295+
def test_session_adapter_is_httpadapter(self):
296+
client = RestClient(self.customer_id, self.api_key)
297+
https_adapter = client.session.adapters["https://"]
298+
import requests
299+
self.assertIsInstance(https_adapter, requests.adapters.HTTPAdapter)
300+
301+
@patch("time.time")
302+
def test_session_refresh_on_pool_recycle(self, mock_time):
303+
# Simulate time to force session recycling
304+
mock_time.return_value = 1000
305+
client = RestClient(self.customer_id, self.api_key, pool_recycle=10)
306+
created_at_first = client._session_created_at
307+
# Advance time beyond the threshold
308+
mock_time.return_value = 1012
309+
# Force a request (any method calls _ensure_session)
310+
client._ensure_session()
311+
created_at_second = client._session_created_at
312+
self.assertNotEqual(created_at_first, created_at_second)

0 commit comments

Comments
 (0)