tamar-model-client 0.1.21__py3-none-any.whl → 0.1.23__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.
@@ -31,7 +31,7 @@ from .core import (
31
31
  generate_request_id,
32
32
  set_request_id,
33
33
  get_protected_logger,
34
- MAX_MESSAGE_LENGTH
34
+ MAX_MESSAGE_LENGTH, get_request_id
35
35
  )
36
36
  from .core.base_client import BaseClient
37
37
  from .core.request_builder import RequestBuilder
@@ -201,10 +201,17 @@ class TamarModelClient(BaseClient, HttpFallbackMixin):
201
201
  """
202
202
  使用增强的错误处理器进行重试(同步版本)
203
203
  """
204
+ # 记录方法开始时间
205
+ method_start_time = time.time()
206
+
207
+ # 从kwargs中提取request_id(如果有的话),然后移除它
208
+ request_id = kwargs.pop('request_id', None) or get_request_id()
209
+
204
210
  # 构建请求上下文
205
211
  context = {
206
212
  'method': func.__name__ if hasattr(func, '__name__') else 'unknown',
207
213
  'client_version': 'sync',
214
+ 'request_id': request_id,
208
215
  }
209
216
 
210
217
  last_exception = None
@@ -222,9 +229,14 @@ class TamarModelClient(BaseClient, HttpFallbackMixin):
222
229
  should_retry = self._should_retry(e, attempt)
223
230
  if not should_retry or attempt >= self.max_retries:
224
231
  # 不可重试或已达到最大重试次数
232
+ current_duration = time.time() - method_start_time
233
+ context['duration'] = current_duration
225
234
  last_exception = self.error_handler.handle_error(e, context)
226
235
  break
227
236
 
237
+ # 计算当前的耗时
238
+ current_duration = time.time() - method_start_time
239
+
228
240
  # 记录重试日志
229
241
  log_data = {
230
242
  "log_type": "info",
@@ -234,7 +246,8 @@ class TamarModelClient(BaseClient, HttpFallbackMixin):
234
246
  "retry_count": attempt,
235
247
  "max_retries": self.max_retries,
236
248
  "method": context.get('method', 'unknown')
237
- }
249
+ },
250
+ "duration": current_duration
238
251
  }
239
252
  logger.warning(
240
253
  f"Attempt {attempt + 1}/{self.max_retries + 1} failed: {e.code()}",
@@ -246,6 +259,7 @@ class TamarModelClient(BaseClient, HttpFallbackMixin):
246
259
  delay = self._calculate_backoff(attempt, e.code())
247
260
  time.sleep(delay)
248
261
 
262
+ context['duration'] = current_duration
249
263
  last_exception = self.error_handler.handle_error(e, context)
250
264
 
251
265
  except Exception as e:
@@ -260,6 +274,73 @@ class TamarModelClient(BaseClient, HttpFallbackMixin):
260
274
  else:
261
275
  raise TamarModelException("Unknown error occurred")
262
276
 
277
+ def _should_retry(self, error: grpc.RpcError, attempt: int) -> bool:
278
+ """
279
+ 判断是否应该重试
280
+
281
+ Args:
282
+ error: gRPC错误
283
+ attempt: 当前重试次数
284
+
285
+ Returns:
286
+ bool: 是否应该重试
287
+ """
288
+ error_code = error.code()
289
+ from .exceptions import get_retry_policy, ErrorContext
290
+ policy = get_retry_policy(error_code)
291
+
292
+ # 先检查错误级别的 max_attempts 配置
293
+ # max_attempts 表示最大重试次数(不包括初始请求)
294
+ error_max_attempts = policy.get('max_attempts', self.max_retries)
295
+ if attempt >= error_max_attempts:
296
+ return False
297
+
298
+ # 再检查全局的 max_retries
299
+ if attempt >= self.max_retries:
300
+ return False
301
+
302
+ retryable = policy.get('retryable', False)
303
+
304
+ if retryable == False:
305
+ return False
306
+ elif retryable == True:
307
+ return True
308
+ elif retryable == 'conditional':
309
+ # 条件重试,特殊处理
310
+ if error_code == grpc.StatusCode.CANCELLED:
311
+ # 检查是否是网络中断导致的取消
312
+ context = {'method': 'unknown', 'client_version': 'sync'}
313
+ error_context = ErrorContext(error, context)
314
+ return error_context.is_network_cancelled()
315
+ else:
316
+ return self._check_error_details_for_retry(error)
317
+
318
+ return False
319
+
320
+ def _check_error_details_for_retry(self, error: grpc.RpcError) -> bool:
321
+ """
322
+ 检查错误详情决定是否重试
323
+
324
+ Args:
325
+ error: gRPC错误
326
+
327
+ Returns:
328
+ bool: 是否应该重试
329
+ """
330
+ error_message = error.details().lower() if error.details() else ""
331
+
332
+ # 可重试的错误模式
333
+ retryable_patterns = [
334
+ 'temporary', 'timeout', 'unavailable',
335
+ 'connection', 'network', 'try again'
336
+ ]
337
+
338
+ for pattern in retryable_patterns:
339
+ if pattern in error_message:
340
+ return True
341
+
342
+ return False
343
+
263
344
  def _calculate_backoff(self, attempt: int, error_code: grpc.StatusCode = None) -> float:
264
345
  """
265
346
  计算退避时间,支持不同的退避策略
@@ -316,10 +397,17 @@ class TamarModelClient(BaseClient, HttpFallbackMixin):
316
397
  Yields:
317
398
  流式响应的每个元素
318
399
  """
400
+ # 记录方法开始时间
401
+ method_start_time = time.time()
402
+
403
+ # 从kwargs中提取request_id(如果有的话),然后移除它
404
+ request_id = kwargs.pop('request_id', None) or get_request_id()
405
+
319
406
  last_exception = None
320
407
  context = {
321
408
  'method': 'stream',
322
409
  'client_version': 'sync',
410
+ 'request_id': request_id,
323
411
  }
324
412
 
325
413
  for attempt in range(self.max_retries + 1):
@@ -334,6 +422,9 @@ class TamarModelClient(BaseClient, HttpFallbackMixin):
334
422
  # 使用智能重试判断
335
423
  context['retry_count'] = attempt
336
424
 
425
+ # 计算当前的耗时
426
+ current_duration = time.time() - method_start_time
427
+
337
428
  # 判断是否应该重试
338
429
  should_retry = self._should_retry(e, attempt)
339
430
  if not should_retry or attempt >= self.max_retries:
@@ -347,12 +438,14 @@ class TamarModelClient(BaseClient, HttpFallbackMixin):
347
438
  "max_retries": self.max_retries,
348
439
  "method": "stream",
349
440
  "will_retry": False
350
- }
441
+ },
442
+ "duration": current_duration
351
443
  }
352
444
  logger.error(
353
445
  f"Stream failed: {e.code()} (no retry)",
354
446
  extra=log_data
355
447
  )
448
+ context['duration'] = current_duration
356
449
  last_exception = self.error_handler.handle_error(e, context)
357
450
  break
358
451
 
@@ -365,7 +458,8 @@ class TamarModelClient(BaseClient, HttpFallbackMixin):
365
458
  "retry_count": attempt,
366
459
  "max_retries": self.max_retries,
367
460
  "method": "stream"
368
- }
461
+ },
462
+ "duration": current_duration
369
463
  }
370
464
  logger.warning(
371
465
  f"Stream attempt {attempt + 1}/{self.max_retries + 1} failed: {e.code()} (will retry)",
@@ -609,10 +703,11 @@ class TamarModelClient(BaseClient, HttpFallbackMixin):
609
703
  # 对于流式响应,使用重试包装器
610
704
  return self._retry_request_stream(
611
705
  self._stream_with_logging,
612
- request, metadata, invoke_timeout, start_time, model_request
706
+ request, metadata, invoke_timeout, start_time, model_request,
707
+ request_id=request_id
613
708
  )
614
709
  else:
615
- result = self._retry_request(self._invoke_request, request, metadata, invoke_timeout)
710
+ result = self._retry_request(self._invoke_request, request, metadata, invoke_timeout, request_id=request_id)
616
711
 
617
712
  # 记录非流式响应的成功日志
618
713
  duration = time.time() - start_time
@@ -742,7 +837,8 @@ class TamarModelClient(BaseClient, HttpFallbackMixin):
742
837
  self.stub.BatchInvoke,
743
838
  batch_request,
744
839
  metadata=metadata,
745
- timeout=invoke_timeout
840
+ timeout=invoke_timeout,
841
+ request_id=request_id
746
842
  )
747
843
 
748
844
  # 构建响应对象
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tamar-model-client
3
- Version: 0.1.21
3
+ Version: 0.1.23
4
4
  Summary: A Python SDK for interacting with the Model Manager gRPC service
5
5
  Home-page: http://gitlab.tamaredge.top/project-tap/AgentOS/model-manager-client
6
6
  Author: Oscar Ou
@@ -1,12 +1,12 @@
1
1
  tamar_model_client/__init__.py,sha256=4DEIUGlLTeiaECjJQbGYik7C0JO6hHwwfbLYpYpMdzg,444
2
- tamar_model_client/async_client.py,sha256=cU3cUrwP75zacyFa3KibcYfacJBsxRNLIu1vtQZrrcU,32836
2
+ tamar_model_client/async_client.py,sha256=H6IhGI415DGXoeNAd4A0anw1oL4Ss3LYdcEVeG_Co68,34416
3
3
  tamar_model_client/auth.py,sha256=gbwW5Aakeb49PMbmYvrYlVx1mfyn1LEDJ4qQVs-9DA4,438
4
4
  tamar_model_client/circuit_breaker.py,sha256=0XHJXBYA4O8vwsDGwqNrae9zxNJphY5Rfucc9ytVFGA,5419
5
- tamar_model_client/error_handler.py,sha256=kVfHL7DWvO3sIobjVuJbqjV4mtI4oqbS4Beax7Dmm9w,11788
6
- tamar_model_client/exceptions.py,sha256=FImLCBpYQ8DpsNbH-ZttxyClEZCL6ICmQGESIlbI--s,12038
5
+ tamar_model_client/error_handler.py,sha256=oI_jUTjnq4OXu8fwJoGXNmQpddEgOFF9ZUhbytq7H6c,12384
6
+ tamar_model_client/exceptions.py,sha256=D6G8igA-YO4AroeCa-9CDDPt4hSqBFX5C_4w-NCIL1w,13063
7
7
  tamar_model_client/json_formatter.py,sha256=IyBv_pEEzjF-KaMF-7rxRpNc_fxRYK2A-pu_2n4Liow,1990
8
8
  tamar_model_client/logging_icons.py,sha256=MRTZ1Xvkep9ce_jdltj54_XZUXvIpQ95soRNmLdJ4qw,1837
9
- tamar_model_client/sync_client.py,sha256=AhNFlhk9aC7JhNrI2BEZJDLjXZwVT9pMy3u9jgjO1QU,32603
9
+ tamar_model_client/sync_client.py,sha256=RDM-ptIL0cNIie-2qpkTEFh60XTks8p2Wdz0Q5YHA1Q,36241
10
10
  tamar_model_client/utils.py,sha256=Kn6pFz9GEC96H4eejEax66AkzvsrXI3WCSDtgDjnVTI,5238
11
11
  tamar_model_client/core/__init__.py,sha256=bJRJllrp4Xc0g_qu1pW9G-lsXNB7c1r0NBIfb2Ypxe0,832
12
12
  tamar_model_client/core/base_client.py,sha256=sYvJZsDu_66akddAMowSnihFtgOoVKaQJxxnVruF9Ms,8995
@@ -27,9 +27,10 @@ tamar_model_client/schemas/inputs.py,sha256=dz1m8NbUIxA99JXZc8WlyzbKpDuz1lEzx3Vg
27
27
  tamar_model_client/schemas/outputs.py,sha256=M_fcqUtXPJnfiLabHlyA8BorlC5pYkf5KLjXO1ysKIQ,1031
28
28
  tests/__init__.py,sha256=kbmImddLDwdqlkkmkyKtl4bQy_ipe-R8eskpaBylU9w,38
29
29
  tests/stream_hanging_analysis.py,sha256=W3W48IhQbNAR6-xvMpoWZvnWOnr56CTaH4-aORNBuD4,14807
30
- tests/test_google_azure_final.py,sha256=wAnfodYCs8VIqYlgT6nm1YnLnufqSuYfXBaVqCXkmfU,17019
30
+ tests/test_google_azure_final.py,sha256=9UI8G62prmnflBm4XuOxvBBshYvwCLQ1H2pqbish_DQ,26390
31
+ tests/test_logging_issue.py,sha256=JTMbotfHpAEPMBj73pOwxPn-Zn4QVQJX6scMz48FRDQ,2427
31
32
  tests/test_simple.py,sha256=Xf0U-J9_xn_LzUsmYu06suK0_7DrPeko8OHoHldsNxE,7169
32
- tamar_model_client-0.1.21.dist-info/METADATA,sha256=gj8tUbP3goUZKi3pVVWMxEpmmK6W72IV23Ym2ohlcBs,23453
33
- tamar_model_client-0.1.21.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
34
- tamar_model_client-0.1.21.dist-info/top_level.txt,sha256=f1I-S8iWN-cgv4gB8gxRg9jJOTJMumvm4oGKVPfGg6A,25
35
- tamar_model_client-0.1.21.dist-info/RECORD,,
33
+ tamar_model_client-0.1.23.dist-info/METADATA,sha256=aW4OAMkth31oY5n04wM1QTkfH7K1TFio9nrnQML5W6g,23453
34
+ tamar_model_client-0.1.23.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
35
+ tamar_model_client-0.1.23.dist-info/top_level.txt,sha256=f1I-S8iWN-cgv4gB8gxRg9jJOTJMumvm4oGKVPfGg6A,25
36
+ tamar_model_client-0.1.23.dist-info/RECORD,,