77import logging
88import multiprocessing
99
10- from influxdb_client_3 import InfluxDBClient3 , write_client_options
11- from influxdb_client_3 .write_client import WriteOptions
10+ from influxdb_client_3 import write_client_options
1211from influxdb_client_3 .exceptions import InfluxDBError
12+ from influxdb_client_3 .write_client import WriteOptions , WriteApi
13+ from influxdb_client_3 .write_client ._sync import rest_client
1314
1415logger = logging .getLogger ('influxdb_client.client.util.multiprocessing_helper' )
1516
@@ -35,9 +36,9 @@ class _PoisonPill:
3536 pass
3637
3738
38- class MultiprocessingWriter ( multiprocessing . Process ) :
39+ class MultiprocessingWriter :
3940 """
40- The Helper class to write data into InfluxDB in independent OS process.
41+ The Helper class to write data into InfluxDB in an independent OS process.
4142
4243 Example:
4344 .. code-block:: python
@@ -119,83 +120,80 @@ def main():
119120 __started__ = False
120121 __disposed__ = False
121122
122- def __init__ (self , ** kwargs ) -> None :
123+ def __init__ (self , start_method = 'spawn' , ** kwargs ) -> None :
123124 """
124125 Initialize defaults.
125126
126- For more information how to initialize the writer see the examples above.
127+ For more information on how to initialize the writer, see the examples above.
127128
128- :param kwargs: arguments are passed into ``__init__ `` function of ``InfluxDBClient`` and ``write_api``.
129+ :param kwargs: arguments are passed into the `` _ _init__ `` function of ``InfluxDBClient`` and ``write_api``.
129130 """
130- multiprocessing .Process .__init__ (self )
131+
132+ wco = write_client_options (write_options = kwargs .get ('write_options' , WriteOptions ()),
133+ success_callback = kwargs .get ('success_callback' , _success_callback ),
134+ error_callback = kwargs .get ('error_callback' , _error_callback ),
135+ retry_callback = kwargs .get ('retry_callback' , _retry_callback )
136+ )
137+
138+ if kwargs .get ('rest_client' ) is not None :
139+ rest = kwargs .get ('rest_client' )
140+ else :
141+ token = kwargs .get ('token' )
142+ default_header = {'Authorization' : f'Token { token } ' }
143+ rest = rest_client .RestClient (
144+ base_url = kwargs .get ('host' ),
145+ default_header = default_header ,
146+ )
147+
148+ write_api = WriteApi (
149+ bucket = kwargs .get ('database' ),
150+ org = kwargs .get ('org' ),
151+ default_header = kwargs .get ('default_header' ),
152+ rest_client = rest ,
153+ ** wco
154+ )
155+
156+ self .ctx = multiprocessing .get_context (start_method )
157+ self .process = self .ctx .Process (target = self .run , args = (write_api ,))
131158 self .kwargs = kwargs
132- self .client = None
133- self .write_api = None
134- self .queue_ = multiprocessing .Manager ().Queue ()
159+ self .queue_ = self .ctx .JoinableQueue ()
135160
136161 def write (self , ** kwargs ) -> None :
137162 """
138- Append time-series data into underlying queue.
163+ Append time-series data into the underlying queue.
139164
140- For more information how to pass arguments see the examples above.
165+ For more information on how to pass arguments, see the examples above.
141166
142- :param kwargs: arguments are passed into `` write`` function of ``WriteApi``
167+ :param kwargs: arguments are passed into the `` write `` function of ``WriteApi``
143168 :return: None
144169 """
145170 assert self .__disposed__ is False , 'Cannot write data: the writer is closed.'
146171 assert self .__started__ is True , 'Cannot write data: the writer is not started.'
147172 self .queue_ .put (kwargs )
148173
149- def run (self ) :
174+ def run (self , write_api : WriteApi ) -> None :
150175 """Initialize ``InfluxDBClient3`` and wait for data to write into InfluxDB."""
151- # Initialize Client and Write API
152- wco = write_client_options (write_options = self .kwargs .get ('write_options' , WriteOptions ()),
153- success_callback = self .kwargs .get ('success_callback' , _success_callback ),
154- error_callback = self .kwargs .get ('error_callback' , _error_callback ),
155- retry_callback = self .kwargs .get ('retry_callback' , _retry_callback )
156- )
157-
158- # Still need to create the InfluxDBClient3 because the init logics of InfluxDBClient3 will create the WriteApi.
159- # it will make WriteApi class created properly.
160- self .client = InfluxDBClient3 (write_client_options = wco , ** self .kwargs )
161176
162- # Close and set _query_api to None because query_api is not needed in this process.
163- # We only need write_api.
164- self .client ._query_api .close ()
165- self .client ._query_api = None
166-
167- self .write_api = self .client ._write_api
168177 # Infinite loop - until poison pill
169178 while True :
170179 next_record = self .queue_ .get ()
171180 if type (next_record ) is _PoisonPill :
172181 # Poison pill means break the loop
173- self .terminate ()
182+ logger .info ("flushing data..." )
183+ write_api .close ()
184+ logger .info ("closed" )
174185 self .queue_ .task_done ()
175186 break
176- self . write_api .write (** next_record )
187+ write_api .write (** next_record )
177188 self .queue_ .task_done ()
178189
179190 def start (self ) -> None :
180- """Start independent process for writing data into InfluxDB."""
181- super () .start ()
191+ """Start an independent process for writing data into InfluxDB."""
192+ self . process .start ()
182193 self .__started__ = True
183194
184- def terminate (self ) -> None :
185- """
186- Cleanup resources in independent process.
187-
188- This function **cannot be used** to terminate the ``MultiprocessingWriter``.
189- If you want to finish your writes please call: ``__del__``.
190- """
191- if self .write_api :
192- logger .info ("flushing data..." )
193- self .write_api .__del__ ()
194- self .write_api = None
195- if self .client :
196- self .client .close ()
197- self .client = None
198- logger .info ("closed" )
195+ def get_start_processing_method (self ):
196+ return self .ctx .get_start_method ()
199197
200198 def __enter__ (self ):
201199 """Enter the runtime context related to this object."""
@@ -207,11 +205,11 @@ def __exit__(self, exc_type, exc_value, traceback):
207205 self .__del__ ()
208206
209207 def __del__ (self ):
210- """Dispose the client and write_api."""
208+ """Dispose of the client and write_api."""
211209 if self .__started__ :
212210 self .queue_ .put (_PoisonPill ())
213211 self .queue_ .join ()
214- self .join ()
212+ self .process . join ()
215213 self .queue_ = None
216214 self .__started__ = False
217215 self .__disposed__ = True
0 commit comments