Repository: influxdata/influxdb-client-python

Issue:
No request timeout causing points not being written to influxdb
<!--

Thank you for reporting a bug. 

* Please add a :+1: or comment on a similar existing bug report instead of opening a new one.
    * https://github.com/influxdata/influxdb-client-python/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+is%3Aclosed+sort%3Aupdated-desc+label%3Abug+
* Please check whether the bug can be reproduced with the latest release.
* The fastest way to fix a bug is to open a Pull Request.
    * https://github.com/influxdata/influxdb-client-python/pulls

-->
We have deployed some IOT sensors and we are seeing some sensors not reporting values for periods of 15 min or more. I believe this is caused because there is no request_timeout used in the rest.py. In the debug logs of the program the last line is the post request being made and getting no response. This causes the influxdb client to stop writing points to the influxdb. 

I thought the timeout parameter of the InfluxDBClient is setting the request timeout? If not, is it possible to set the request timeout? Because it is supported in the rest.py file (lines 159-165)

__Steps to reproduce:__
Minimal piece of code I run to reproduce.
```python3
from influxdb_client import InfluxDBClient, Point
from influxdb_client.client.write_api import SYNCHRONOUS

client = InfluxDBClient(url="http://127.0.0.1:8080", token="token", org="org", debug=True, timeout=1000)
write_api = client.write_api(write_options=SYNCHRONOUS)

p = Point("point").tag("tag","tag").field("Field", 1.0)
write_api.write(bucket="bucket", record=p)
```
1. run nc -l -k -p 8080 (to host a tcp server for the client to connect to)
2. run code shown above

__Expected behavior:__
I would expect it to raise an exception, restart the connection or resend the post request

__Actual behavior:__
Post request is made and continues waiting until the program is restarted.

__Specifications:__
 - Client Version: 0.16.0
 - InfluxDB Version: N/A
 - Platform: Linux


Discussion:
codecov[bot]: # [Codecov](https://codecov.io/gh/influxdata/influxdb-client-python/pull/222?src=pr&el=h1) Report
> Merging [#222](https://codecov.io/gh/influxdata/influxdb-client-python/pull/222?src=pr&el=desc) (5f9edd8) into [master](https://codecov.io/gh/influxdata/influxdb-client-python/commit/2870071c1e958d085e2c81f815895808ec680fe6?el=desc) (2870071) will **increase** coverage by `0.10%`.
> The diff coverage is `87.50%`.

[![Impacted file tree graph](https://codecov.io/gh/influxdata/influxdb-client-python/pull/222/graphs/tree.svg?width=650&height=150&src=pr&token=PcyupQSPFt)](https://codecov.io/gh/influxdata/influxdb-client-python/pull/222?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master     #222      +/-   ##
==========================================
+ Coverage   90.64%   90.75%   +0.10%     
==========================================
  Files          26       26              
  Lines        2010     2012       +2     
==========================================
+ Hits         1822     1826       +4     
+ Misses        188      186       -2     
```


| [Impacted Files](https://codecov.io/gh/influxdata/influxdb-client-python/pull/222?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [influxdb\_client/rest.py](https://codecov.io/gh/influxdata/influxdb-client-python/pull/222/diff?src=pr&el=tree#diff-aW5mbHV4ZGJfY2xpZW50L3Jlc3QucHk=) | `83.45% <80.00%> (+1.64%)` | :arrow_up: |
| [influxdb\_client/client/influxdb\_client.py](https://codecov.io/gh/influxdata/influxdb-client-python/pull/222/diff?src=pr&el=tree#diff-aW5mbHV4ZGJfY2xpZW50L2NsaWVudC9pbmZsdXhkYl9jbGllbnQucHk=) | `99.27% <100.00%> (ø)` | |
| [influxdb\_client/configuration.py](https://codecov.io/gh/influxdata/influxdb-client-python/pull/222/diff?src=pr&el=tree#diff-aW5mbHV4ZGJfY2xpZW50L2NvbmZpZ3VyYXRpb24ucHk=) | `84.44% <100.00%> (+0.17%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/influxdata/influxdb-client-python/pull/222?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/influxdata/influxdb-client-python/pull/222?src=pr&el=footer). Last update [2870071...5f9edd8](https://codecov.io/gh/influxdata/influxdb-client-python/pull/222?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f2eaa3b..2ee6a67 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,9 @@
 ### Features
 1. [#203](https://github.com/influxdata/influxdb-client-python/issues/219): Bind query parameters 
 
+### Bug Fixes
+1. [#222](https://github.com/influxdata/influxdb-client-python/pull/222): Pass configured timeout to HTTP client
+
 ## 1.16.0 [2021-04-01]
 
 ### Features
@@ -11,7 +14,7 @@
 
 ### Bug Fixes
 1. [#206](https://github.com/influxdata/influxdb-client-python/pull/207): Use default (system) certificates instead of Mozilla's root certificates (certifi.where())
-1. [#217](https://github.com/influxdata/influxdb-client-python/pull/217): Fixed clone_task function
+1. [#217](https://github.com/influxdata/influxdb-client-python/pull/217): Fix clone_task function
 
 ### API
 1. [#209](https://github.com/influxdata/influxdb-client-python/pull/209): Allow setting shard-group durations for buckets via API
diff --git a/influxdb_client/client/influxdb_client.py b/influxdb_client/client/influxdb_client.py
index cb027e9..8b793c0 100644
--- a/influxdb_client/client/influxdb_client.py
+++ b/influxdb_client/client/influxdb_client.py
@@ -20,7 +20,7 @@ from influxdb_client.client.write_api import WriteApi, WriteOptions, PointSettin
 class InfluxDBClient(object):
     """InfluxDBClient is client for InfluxDB v2."""
 
-    def __init__(self, url, token, debug=None, timeout=10000, enable_gzip=False, org: str = None,
+    def __init__(self, url, token, debug=None, timeout=10_000, enable_gzip=False, org: str = None,
                  default_tags: dict = None, **kwargs) -> None:
         """
         Initialize defaults.
@@ -28,7 +28,9 @@ class InfluxDBClient(object):
         :param url: InfluxDB server API url (ex. http://localhost:8086).
         :param token: auth token
         :param debug: enable verbose logging of http requests
-        :param timeout: default http client timeout
+        :param timeout: HTTP client timeout setting for a request specified in milliseconds.
+                        If one number provided, it will be total request timeout.
+                        It can also be a pair (tuple) of (connection, read) timeouts.
         :param enable_gzip: Enable Gzip compression for http requests. Currently only the "Write" and "Query" endpoints
                             supports the Gzip compression.
         :param org: organization name (used as a default in query and write API)
@@ -43,7 +45,6 @@ class InfluxDBClient(object):
         """
         self.url = url
         self.token = token
-        self.timeout = timeout
         self.org = org
 
         self.default_tags = default_tags
@@ -59,6 +60,7 @@ class InfluxDBClient(object):
         conf.ssl_ca_cert = kwargs.get('ssl_ca_cert', None)
         conf.proxy = kwargs.get('proxy', None)
         conf.connection_pool_maxsize = kwargs.get('connection_pool_maxsize', conf.connection_pool_maxsize)
+        conf.timeout = timeout
 
         auth_token = self.token
         auth_header_name = "Authorization"
diff --git a/influxdb_client/configuration.py b/influxdb_client/configuration.py
index 7161e59..68ffe0c 100644
--- a/influxdb_client/configuration.py
+++ b/influxdb_client/configuration.py
@@ -103,6 +103,9 @@ class Configuration(six.with_metaclass(TypeWithDefault, object)):
         # requests to the same host, which is often the case here.
         # cpu_count * 5 is used as default value to increase performance.
         self.connection_pool_maxsize = multiprocessing.cpu_count() * 5
+        # Timeout setting for a request. If one number provided, it will be total request timeout.
+        # It can also be a pair (tuple) of (connection, read) timeouts.
+        self.timeout = None
 
         # Proxy URL
         self.proxy = None
diff --git a/influxdb_client/rest.py b/influxdb_client/rest.py
index 5c718f5..0d79ae2 100644
--- a/influxdb_client/rest.py
+++ b/influxdb_client/rest.py
@@ -156,13 +156,14 @@ class RESTClientObject(object):
         headers = headers or {}
 
         timeout = None
-        if _request_timeout:
-            if isinstance(_request_timeout, (int, ) if six.PY3 else (int, long)):  # noqa: E501,F821
-                timeout = urllib3.Timeout(total=_request_timeout)
-            elif (isinstance(_request_timeout, tuple) and
-                  len(_request_timeout) == 2):
+        _configured_timeout = _request_timeout or self.configuration.timeout
+        if _configured_timeout:
+            if isinstance(_configured_timeout, (int, ) if six.PY3 else (int, long)):  # noqa: E501,F821
+                timeout = urllib3.Timeout(total=_configured_timeout / 1_000)
+            elif (isinstance(_configured_timeout, tuple) and
+                  len(_configured_timeout) == 2):
                 timeout = urllib3.Timeout(
-                    connect=_request_timeout[0], read=_request_timeout[1])
+                    connect=_configured_timeout[0] / 1_000, read=_configured_timeout[1] / 1_000)
 
         if 'Content-Type' not in headers:
             headers['Content-Type'] = 'application/json'


Test patch:
diff --git a/tests/test_InfluxDBClient.py b/tests/test_InfluxDBClient.py
index 6ad96e2..31814b3 100644
--- a/tests/test_InfluxDBClient.py
+++ b/tests/test_InfluxDBClient.py
@@ -65,7 +65,7 @@ class InfluxDBClientTest(unittest.TestCase):
         self.assertEqual("http://localhost:8086", self.client.url)
         self.assertEqual("my-org", self.client.org)
         self.assertEqual("my-token", self.client.token)
-        self.assertEqual(6000, self.client.timeout)
+        self.assertEqual(6000, self.client.api_client.configuration.timeout)
         self.assertEqual(3, len(self.client.default_tags))
         self.assertEqual("132-987-655", self.client.default_tags["id"])
         self.assertEqual("California Miner", self.client.default_tags["customer"])
diff --git a/tests/test_WriteApi.py b/tests/test_WriteApi.py
index 96c6d50..1bb6f9a 100644
--- a/tests/test_WriteApi.py
+++ b/tests/test_WriteApi.py
@@ -795,7 +795,7 @@ class DefaultTagsConfiguration(BaseTest):
 
         self.assertEqual("my-org", self.client.org)
         self.assertEqual("my-token", self.client.token)
-        self.assertEqual(6000, self.client.timeout)
+        self.assertEqual(6000, self.client.api_client.configuration.timeout)
 
     def test_default_tags_from_conf_file(self):
         self.client.close()