mlrun 1.9.0rc8__py3-none-any.whl → 1.9.0rc9__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of mlrun might be problematic. Click here for more details.

@@ -11,8 +11,7 @@
11
11
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
-
15
- import traceback
14
+ import time
16
15
  from collections.abc import Callable
17
16
  from enum import Enum
18
17
  from typing import Any, Final, Optional, Union
@@ -20,6 +19,9 @@ from typing import Any, Final, Optional, Union
20
19
  import taosws
21
20
  from taosws import TaosStmt
22
21
 
22
+ import mlrun
23
+ from mlrun.utils import logger
24
+
23
25
 
24
26
  class _StrEnum(str, Enum):
25
27
  pass
@@ -137,40 +139,99 @@ class Statement:
137
139
  return statement
138
140
 
139
141
 
140
- def _run(connection_string, prefix_statements, q, statements, query):
141
- try:
142
- conn = taosws.connect(connection_string)
143
-
144
- for statement in prefix_statements + statements:
145
- if isinstance(statement, Statement):
146
- prepared_statement = statement.prepare(conn.statement())
147
- prepared_statement.execute()
148
- else:
149
- conn.execute(statement)
150
-
151
- if not query:
152
- q.put(None)
153
- return
154
-
155
- res = conn.query(query)
156
-
157
- # taosws.TaosField is not serializable
158
- fields = [
159
- Field(field.name(), field.type(), field.bytes()) for field in res.fields
160
- ]
161
-
162
- q.put(QueryResult(list(res), fields))
163
- except Exception as e:
164
- tb = traceback.format_exc()
165
- q.put(ErrorResult(tb, e))
166
-
167
-
168
142
  class TDEngineConnection:
169
- def __init__(self, connection_string):
143
+ def __init__(self, connection_string, max_retries=3, retry_delay=0.5):
170
144
  self._connection_string = connection_string
171
145
  self.prefix_statements = []
146
+ self._max_retries = max_retries
147
+ self._retry_delay = retry_delay
172
148
 
173
- self._conn = taosws.connect(self._connection_string)
149
+ self._conn = self._create_connection()
150
+
151
+ def _create_connection(self):
152
+ """Create a new TDEngine connection."""
153
+ return taosws.connect(self._connection_string)
154
+
155
+ def _reconnect(self):
156
+ """Close current connection and create a new one."""
157
+ try:
158
+ if hasattr(self, "_conn") and self._conn:
159
+ self._conn.close()
160
+ except Exception as e:
161
+ logger.warning(f"Error closing connection during reconnect: {e}")
162
+
163
+ self._conn = self._create_connection()
164
+ logger.info("Successfully reconnected to TDEngine")
165
+
166
+ def _execute_with_retry(self, operation, operation_name, *args, **kwargs):
167
+ """
168
+ Execute an operation with retry logic for connection failures.
169
+
170
+ :param operation: The function to execute
171
+ :param operation_name: Name of the operation for logging
172
+ :param args: Arguments to pass to the operation
173
+ :param kwargs: Keyword arguments to pass to the operation
174
+ :return: Result of the operation
175
+ """
176
+ last_exception = None
177
+
178
+ for attempt in range(self._max_retries + 1): # +1 for initial attempt
179
+ try:
180
+ return operation(*args, **kwargs)
181
+
182
+ except taosws.Error as e:
183
+ last_exception = e
184
+
185
+ if attempt < self._max_retries:
186
+ logger.warning(
187
+ f"Connection error during {operation_name} "
188
+ f"(attempt {attempt + 1}/{self._max_retries + 1}): {e}. "
189
+ f"Retrying in {self._retry_delay} seconds..."
190
+ )
191
+
192
+ # Wait before retrying
193
+ time.sleep(self._retry_delay)
194
+
195
+ # Reconnect
196
+ try:
197
+ self._reconnect()
198
+ except Exception as reconnect_error:
199
+ logger.error(f"Failed to reconnect: {reconnect_error}")
200
+ if attempt == self._max_retries - 1:
201
+ # Last attempt, raise the reconnection error
202
+ raise TDEngineError(
203
+ f"Failed to reconnect after {operation_name} failure: {reconnect_error}"
204
+ ) from reconnect_error
205
+ continue
206
+ else:
207
+ # Max retries exceeded
208
+ logger.error(
209
+ f"Max retries ({self._max_retries}) exceeded for {operation_name}"
210
+ )
211
+ break
212
+
213
+ except Exception as e:
214
+ # Non-TDEngine error, don't retry
215
+ raise TDEngineError(
216
+ f"Unexpected error during {operation_name}: {e}"
217
+ ) from e
218
+
219
+ # If we get here, all retries failed
220
+ raise TDEngineError(
221
+ f"Failed to {operation_name} after {self._max_retries} retries: {last_exception}"
222
+ ) from last_exception
223
+
224
+ def _execute_statement(self, statement):
225
+ """Execute a single statement (string or Statement object)."""
226
+ if isinstance(statement, Statement):
227
+ prepared_statement = statement.prepare(self._conn.statement())
228
+ prepared_statement.execute()
229
+ else:
230
+ self._conn.execute(statement)
231
+
232
+ def _execute_query(self, query):
233
+ """Execute a query and return the result."""
234
+ return self._conn.query(query)
174
235
 
175
236
  def run(
176
237
  self,
@@ -181,33 +242,40 @@ class TDEngineConnection:
181
242
  if not isinstance(statements, list):
182
243
  statements = [statements]
183
244
 
184
- for statement in self.prefix_statements + statements:
245
+ # Execute all statements with retry logic
246
+ all_statements = self.prefix_statements + statements
247
+ for i, statement in enumerate(all_statements):
248
+ operation_name = f"execute statement {i + 1}/{len(all_statements)}"
185
249
  if isinstance(statement, Statement):
186
- try:
187
- prepared_statement = statement.prepare(self._conn.statement())
188
- prepared_statement.execute()
189
- except taosws.Error as e:
190
- raise TDEngineError(
191
- f"Failed to run prepared statement `{self._conn.statement()}`: {e}"
192
- ) from e
250
+ operation_name += " (prepared)"
193
251
  else:
194
- try:
195
- self._conn.execute(statement)
196
- except taosws.Error as e:
197
- raise TDEngineError(
198
- f"Failed to run statement `{statement}`: {e}"
199
- ) from e
252
+ operation_name += f" `{statement}`"
253
+
254
+ self._execute_with_retry(self._execute_statement, operation_name, statement)
200
255
 
201
256
  if not query:
202
257
  return None
203
258
 
204
- try:
205
- res = self._conn.query(query)
206
- except taosws.Error as e:
207
- raise TDEngineError(f"Failed to run query `{query}`: {e}") from e
259
+ # Execute query with retry logic
260
+ res = self._execute_with_retry(
261
+ self._execute_query, f"execute query `{query}`", query
262
+ )
208
263
 
264
+ # Process results
209
265
  fields = [
210
266
  Field(field.name(), field.type(), field.bytes()) for field in res.fields
211
267
  ]
212
268
 
213
269
  return QueryResult(list(res), fields)
270
+
271
+ def close(self):
272
+ """Close the connection."""
273
+ try:
274
+ if self._conn:
275
+ self._conn.close()
276
+ logger.debug("TDEngine connection closed")
277
+ self._conn = None
278
+ except Exception as e:
279
+ logger.warning(
280
+ f"Error closing TDEngine connection: {mlrun.errors.err_to_str(e)}"
281
+ )
@@ -12,8 +12,8 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ import threading
15
16
  from datetime import datetime, timedelta
16
- from threading import Lock
17
17
  from typing import Callable, Final, Literal, Optional, Union
18
18
 
19
19
  import pandas as pd
@@ -32,8 +32,8 @@ from mlrun.model_monitoring.db.tsdb.tdengine.tdengine_connection import (
32
32
  from mlrun.model_monitoring.helpers import get_invocations_fqn
33
33
  from mlrun.utils import logger
34
34
 
35
- _connection = None
36
- _connection_lock = Lock()
35
+ # Thread-local storage for connections
36
+ _thread_local = threading.local()
37
37
 
38
38
 
39
39
  class TDEngineTimestampPrecision(mlrun.common.types.StrEnum):
@@ -76,16 +76,15 @@ class TDEngineConnector(TSDBConnector):
76
76
 
77
77
  @property
78
78
  def connection(self) -> TDEngineConnection:
79
- global _connection
80
-
81
- if _connection:
82
- return _connection
83
-
84
- with _connection_lock:
85
- if not _connection:
86
- _connection = self._create_connection()
87
-
88
- return _connection
79
+ if not hasattr(_thread_local, "connection"):
80
+ _thread_local.connection = self._create_connection()
81
+ logger.debug(
82
+ "Created new TDEngine connection for thread",
83
+ project=self.project,
84
+ thread_name=threading.current_thread().name,
85
+ thread_id=threading.get_ident(),
86
+ )
87
+ return _thread_local.connection
89
88
 
90
89
  def _create_connection(self) -> TDEngineConnection:
91
90
  """Establish a connection to the TSDB server."""
mlrun/projects/project.py CHANGED
@@ -1408,7 +1408,10 @@ class MlrunProject(ModelObj):
1408
1408
  https://apscheduler.readthedocs.io/en/3.x/modules/triggers/cron.html#module-apscheduler.triggers.cron
1409
1409
  Note that "local" engine does not support this argument
1410
1410
  :param ttl: Pipeline ttl in secs (after that the pods will be removed)
1411
- :param image: Image for workflow runner job, only for scheduled and remote workflows
1411
+ :param image: Image for workflow runner job, only for scheduled and remote workflows.
1412
+ The image must have mlrun[kfp] installed which requires python 3.9.
1413
+ Therefore, the project default image will not be used for the workflow,
1414
+ and the image must be specified explicitly.
1412
1415
  :param args: Argument values (key=value, ..)
1413
1416
  """
1414
1417
 
@@ -1,4 +1,4 @@
1
1
  {
2
- "git_commit": "4754fd79dbb4d1b30f70ca03493ee7787da6089b",
3
- "version": "1.9.0-rc8"
2
+ "git_commit": "d71319e6a92279074fcbe69811a8d7dbd7a2b642",
3
+ "version": "1.9.0-rc9"
4
4
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mlrun
3
- Version: 1.9.0rc8
3
+ Version: 1.9.0rc9
4
4
  Summary: Tracking and config of machine learning runs
5
5
  Home-page: https://github.com/mlrun/mlrun
6
6
  Author: Yaron Haviv
@@ -15,6 +15,7 @@ Classifier: Operating System :: Microsoft :: Windows
15
15
  Classifier: Operating System :: MacOS
16
16
  Classifier: Programming Language :: Python :: 3
17
17
  Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.11
18
19
  Classifier: Programming Language :: Python
19
20
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
20
21
  Classifier: Topic :: Software Development :: Libraries
@@ -242,8 +242,8 @@ mlrun/model_monitoring/db/tsdb/helpers.py,sha256=0oUXc4aUkYtP2SGP6jTb3uPPKImIUsV
242
242
  mlrun/model_monitoring/db/tsdb/tdengine/__init__.py,sha256=vgBdsKaXUURKqIf3M0y4sRatmSVA4CQiJs7J5dcVBkQ,620
243
243
  mlrun/model_monitoring/db/tsdb/tdengine/schemas.py,sha256=EslhaR65jfeNdD5Ibk-3Hb4e5r5qYPfHb9rTChX3sG0,12689
244
244
  mlrun/model_monitoring/db/tsdb/tdengine/stream_graph_steps.py,sha256=Uadj0UvAmln2MxDWod-kAzau1uNlqZh981rPhbUH_5M,2857
245
- mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connection.py,sha256=8xo2O_yQrJGNDoYYB3Bwtdwwvzs3U9dT3BtPot0zENQ,6449
246
- mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py,sha256=h0ZrNgOwTlBRd_DaYDc6eeVM9f_8CLJMUPEAIrZpbyU,37803
245
+ mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connection.py,sha256=dtkaHaWKWERPXylEWMECeetwrz3rWl0P43AADcTjlls,9330
246
+ mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py,sha256=f-3bycfwGvu7gX_Jh3vRT-s2k_yZRXLeIkBrt11xTdc,37998
247
247
  mlrun/model_monitoring/db/tsdb/v3io/__init__.py,sha256=aL3bfmQsUQ-sbvKGdNihFj8gLCK3mSys0qDcXtYOwgc,616
248
248
  mlrun/model_monitoring/db/tsdb/v3io/stream_graph_steps.py,sha256=_-zo9relCDtjGgievxAcAP9gVN9nDWs8BzGtFwTjb9M,6284
249
249
  mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py,sha256=aDdyHWJLOG-3EgPTJgbEzOOQf5NetpFQk_HdQbs5_zI,47160
@@ -271,7 +271,7 @@ mlrun/platforms/iguazio.py,sha256=6VBTq8eQ3mzT96tzjYhAtcMQ2VjF4x8LpIPW5DAcX2Q,13
271
271
  mlrun/projects/__init__.py,sha256=0Krf0WIKfnZa71WthYOg0SoaTodGg3sV_hK3f_OlTPI,1220
272
272
  mlrun/projects/operations.py,sha256=9ntpM8WnnyRk1iCY0NDKW-3aR4j2QZPSJM0SdMnsQKs,20032
273
273
  mlrun/projects/pipelines.py,sha256=wud7ezeEmhIJvfYE_wzQbA4ygEfGXHtbOtoOpan6poY,48556
274
- mlrun/projects/project.py,sha256=O3oeg5ZZLvsvftN_T6syB1xQJ7e1eFg37mrlIaL4VCY,237075
274
+ mlrun/projects/project.py,sha256=VY9Wd1GfMH8CUUdOPN9UDsmcvsddlB_HYd2abodvSXY,237350
275
275
  mlrun/runtimes/__init__.py,sha256=J9Sy2HiyMlztNv6VUurMzF5H2XzttNil8nRsWDsqLyg,8923
276
276
  mlrun/runtimes/base.py,sha256=K-38p2HYSpaPcenJgEzQqLlLVFxfwLu2Bwe9oXGWCTM,37853
277
277
  mlrun/runtimes/daskjob.py,sha256=JwuGvOiPsxEDHHMMUS4Oie4hLlYYIZwihAl6DjroTY0,19521
@@ -341,11 +341,11 @@ mlrun/utils/notifications/notification/mail.py,sha256=ZyJ3eqd8simxffQmXzqd3bgbAq
341
341
  mlrun/utils/notifications/notification/slack.py,sha256=kfhogR5keR7Zjh0VCjJNK3NR5_yXT7Cv-x9GdOUW4Z8,7294
342
342
  mlrun/utils/notifications/notification/webhook.py,sha256=zxh8CAlbPnTazsk6r05X5TKwqUZVOH5KBU2fJbzQlG4,5330
343
343
  mlrun/utils/version/__init__.py,sha256=7kkrB7hEZ3cLXoWj1kPoDwo4MaswsI2JVOBpbKgPAgc,614
344
- mlrun/utils/version/version.json,sha256=-dffrM4IxXc-h_dn68qDgfH05FcPVSknGFKhWh-Ltsw,88
344
+ mlrun/utils/version/version.json,sha256=9OoUMhTH3Ii0QEe_aO06dt56NtO2_K4FElMMumdqFx0,88
345
345
  mlrun/utils/version/version.py,sha256=eEW0tqIAkU9Xifxv8Z9_qsYnNhn3YH7NRAfM-pPLt1g,1878
346
- mlrun-1.9.0rc8.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
347
- mlrun-1.9.0rc8.dist-info/METADATA,sha256=itS4CUiW4wWgXKfGDT7AUaSKoT32z2Ao09gzQI7_HDw,25708
348
- mlrun-1.9.0rc8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
349
- mlrun-1.9.0rc8.dist-info/entry_points.txt,sha256=1Owd16eAclD5pfRCoJpYC2ZJSyGNTtUr0nCELMioMmU,46
350
- mlrun-1.9.0rc8.dist-info/top_level.txt,sha256=NObLzw3maSF9wVrgSeYBv-fgnHkAJ1kEkh12DLdd5KM,6
351
- mlrun-1.9.0rc8.dist-info/RECORD,,
346
+ mlrun-1.9.0rc9.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
347
+ mlrun-1.9.0rc9.dist-info/METADATA,sha256=Zg7y-d5F7YBeE5O0lnyaiDwrVlCNPU9j2A4hlnXoRSk,25759
348
+ mlrun-1.9.0rc9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
349
+ mlrun-1.9.0rc9.dist-info/entry_points.txt,sha256=1Owd16eAclD5pfRCoJpYC2ZJSyGNTtUr0nCELMioMmU,46
350
+ mlrun-1.9.0rc9.dist-info/top_level.txt,sha256=NObLzw3maSF9wVrgSeYBv-fgnHkAJ1kEkh12DLdd5KM,6
351
+ mlrun-1.9.0rc9.dist-info/RECORD,,