codosdk 1.0.41__tar.gz → 1.0.42__tar.gz

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.
Files changed (52) hide show
  1. {codosdk-1.0.41 → codosdk-1.0.42}/PKG-INFO +2 -2
  2. {codosdk-1.0.41 → codosdk-1.0.42}/codosdk.egg-info/PKG-INFO +2 -2
  3. {codosdk-1.0.41 → codosdk-1.0.42}/codosdk.egg-info/requires.txt +1 -1
  4. {codosdk-1.0.41 → codosdk-1.0.42}/setup.py +2 -2
  5. {codosdk-1.0.41 → codosdk-1.0.42}/websdk2/mqhelper.py +87 -15
  6. {codosdk-1.0.41 → codosdk-1.0.42}/LICENSE +0 -0
  7. {codosdk-1.0.41 → codosdk-1.0.42}/README.md +0 -0
  8. {codosdk-1.0.41 → codosdk-1.0.42}/codosdk.egg-info/SOURCES.txt +0 -0
  9. {codosdk-1.0.41 → codosdk-1.0.42}/codosdk.egg-info/dependency_links.txt +0 -0
  10. {codosdk-1.0.41 → codosdk-1.0.42}/codosdk.egg-info/top_level.txt +0 -0
  11. {codosdk-1.0.41 → codosdk-1.0.42}/opssdk/__init__.py +0 -0
  12. {codosdk-1.0.41 → codosdk-1.0.42}/opssdk/utils/__init__.py +0 -0
  13. {codosdk-1.0.41 → codosdk-1.0.42}/pyproject.toml +0 -0
  14. {codosdk-1.0.41 → codosdk-1.0.42}/setup.cfg +0 -0
  15. {codosdk-1.0.41 → codosdk-1.0.42}/websdk2/__init__.py +0 -0
  16. {codosdk-1.0.41 → codosdk-1.0.42}/websdk2/api_set.py +0 -0
  17. {codosdk-1.0.41 → codosdk-1.0.42}/websdk2/apis/__init__.py +0 -0
  18. {codosdk-1.0.41 → codosdk-1.0.42}/websdk2/apis/admin_apis.py +0 -0
  19. {codosdk-1.0.41 → codosdk-1.0.42}/websdk2/apis/agent_apis.py +0 -0
  20. {codosdk-1.0.41 → codosdk-1.0.42}/websdk2/apis/cmdb_apis.py +0 -0
  21. {codosdk-1.0.41 → codosdk-1.0.42}/websdk2/apis/kerrigan_apis.py +0 -0
  22. {codosdk-1.0.41 → codosdk-1.0.42}/websdk2/apis/mgv4_apis.py +0 -0
  23. {codosdk-1.0.41 → codosdk-1.0.42}/websdk2/apis/notice_apis.py +0 -0
  24. {codosdk-1.0.41 → codosdk-1.0.42}/websdk2/apis/task_apis.py +0 -0
  25. {codosdk-1.0.41 → codosdk-1.0.42}/websdk2/application.py +0 -0
  26. {codosdk-1.0.41 → codosdk-1.0.42}/websdk2/base_handler.py +0 -0
  27. {codosdk-1.0.41 → codosdk-1.0.42}/websdk2/cache.py +0 -0
  28. {codosdk-1.0.41 → codosdk-1.0.42}/websdk2/cache_context.py +0 -0
  29. {codosdk-1.0.41 → codosdk-1.0.42}/websdk2/client.py +0 -0
  30. {codosdk-1.0.41 → codosdk-1.0.42}/websdk2/cloud/__init__.py +0 -0
  31. {codosdk-1.0.41 → codosdk-1.0.42}/websdk2/cloud/qcloud_api.py +0 -0
  32. {codosdk-1.0.41 → codosdk-1.0.42}/websdk2/cloud/ucloud_api.py +0 -0
  33. {codosdk-1.0.41 → codosdk-1.0.42}/websdk2/cloud_utils.py +0 -0
  34. {codosdk-1.0.41 → codosdk-1.0.42}/websdk2/configs.py +0 -0
  35. {codosdk-1.0.41 → codosdk-1.0.42}/websdk2/consts.py +0 -0
  36. {codosdk-1.0.41 → codosdk-1.0.42}/websdk2/crud_utils.py +0 -0
  37. {codosdk-1.0.41 → codosdk-1.0.42}/websdk2/db_context.py +0 -0
  38. {codosdk-1.0.41 → codosdk-1.0.42}/websdk2/error.py +0 -0
  39. {codosdk-1.0.41 → codosdk-1.0.42}/websdk2/fetch_coroutine.py +0 -0
  40. {codosdk-1.0.41 → codosdk-1.0.42}/websdk2/jwt_token.py +0 -0
  41. {codosdk-1.0.41 → codosdk-1.0.42}/websdk2/ldap.py +0 -0
  42. {codosdk-1.0.41 → codosdk-1.0.42}/websdk2/logger.py +0 -0
  43. {codosdk-1.0.41 → codosdk-1.0.42}/websdk2/model_utils.py +0 -0
  44. {codosdk-1.0.41 → codosdk-1.0.42}/websdk2/program.py +0 -0
  45. {codosdk-1.0.41 → codosdk-1.0.42}/websdk2/salt_api.py +0 -0
  46. {codosdk-1.0.41 → codosdk-1.0.42}/websdk2/sqlalchemy_pagination.py +0 -0
  47. {codosdk-1.0.41 → codosdk-1.0.42}/websdk2/tools.py +0 -0
  48. {codosdk-1.0.41 → codosdk-1.0.42}/websdk2/utils/__init__.py +0 -0
  49. {codosdk-1.0.41 → codosdk-1.0.42}/websdk2/utils/cc_crypto.py +0 -0
  50. {codosdk-1.0.41 → codosdk-1.0.42}/websdk2/utils/date_format.py +0 -0
  51. {codosdk-1.0.41 → codosdk-1.0.42}/websdk2/utils/pydantic_utils.py +0 -0
  52. {codosdk-1.0.41 → codosdk-1.0.42}/websdk2/web_logs.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codosdk
3
- Version: 1.0.41
3
+ Version: 1.0.42
4
4
  Summary: CODO项目的Python SDK
5
5
  Home-page: https://github.com/ss1917/codo_sdk/
6
6
  Author: shenshuo
@@ -23,7 +23,7 @@ Requires-Dist: fire==0.5.0
23
23
  Requires-Dist: shortuuid==1.0.11
24
24
  Requires-Dist: pymysql==0.9.3
25
25
  Requires-Dist: sqlalchemy==1.3.23
26
- Requires-Dist: pika==1.3.1
26
+ Requires-Dist: pika==1.3.2
27
27
  Requires-Dist: PyJWT==2.0.1
28
28
  Requires-Dist: requests==2.28.2
29
29
  Requires-Dist: redis==4.5.1
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codosdk
3
- Version: 1.0.41
3
+ Version: 1.0.42
4
4
  Summary: CODO项目的Python SDK
5
5
  Home-page: https://github.com/ss1917/codo_sdk/
6
6
  Author: shenshuo
@@ -23,7 +23,7 @@ Requires-Dist: fire==0.5.0
23
23
  Requires-Dist: shortuuid==1.0.11
24
24
  Requires-Dist: pymysql==0.9.3
25
25
  Requires-Dist: sqlalchemy==1.3.23
26
- Requires-Dist: pika==1.3.1
26
+ Requires-Dist: pika==1.3.2
27
27
  Requires-Dist: PyJWT==2.0.1
28
28
  Requires-Dist: requests==2.28.2
29
29
  Requires-Dist: redis==4.5.1
@@ -2,7 +2,7 @@ fire==0.5.0
2
2
  shortuuid==1.0.11
3
3
  pymysql==0.9.3
4
4
  sqlalchemy==1.3.23
5
- pika==1.3.1
5
+ pika==1.3.2
6
6
  PyJWT==2.0.1
7
7
  requests==2.28.2
8
8
  redis==4.5.1
@@ -9,7 +9,7 @@ desc : CODO SDK
9
9
  import sys
10
10
  from setuptools import setup, find_packages
11
11
 
12
- VERSION = '1.0.41'
12
+ VERSION = '1.0.42'
13
13
 
14
14
  if sys.version_info < (2, 7) or (3, 0) <= sys.version_info < (3, 6):
15
15
  print('This program requires at least Python 2.7 or 3.6 to run.')
@@ -24,7 +24,7 @@ def get_data_files():
24
24
 
25
25
 
26
26
  def get_install_requires():
27
- requires = ['fire==0.5.0', 'shortuuid==1.0.11', 'pymysql==0.9.3', 'sqlalchemy==1.3.23', 'pika==1.3.1',
27
+ requires = ['fire==0.5.0', 'shortuuid==1.0.11', 'pymysql==0.9.3', 'sqlalchemy==1.3.23', 'pika==1.3.2',
28
28
  'PyJWT==2.0.1', 'requests==2.28.2', 'redis==4.5.1', 'tornado>=6.0', 'loguru>=0.6.0',
29
29
  'cryptography==42.0.4', 'ldap3==2.9', 'pydantic>=1.10.5']
30
30
  return requires
@@ -120,6 +120,7 @@ logger.setLevel(logging.WARNING)
120
120
  # else:
121
121
  # self.__channel.basic_publish(exchange=self.__exchange, routing_key=self.__routing_key, body=body)
122
122
  # logging.info('Publish message %s sucessfuled.' % body)
123
+
123
124
  class RabbitMQConnectionPool:
124
125
  """RabbitMQ连接池管理器 - 实现一个应用一个连接的最佳实践"""
125
126
 
@@ -148,22 +149,37 @@ class RabbitMQConnectionPool:
148
149
  mq_config = configs[const.MQ_CONFIG_ITEM][mq_key]
149
150
  cls._validate_config(mq_config)
150
151
 
151
- # 创建连接
152
+ # 创建连接参数,优化超时和重试设置
152
153
  credentials = pika.PlainCredentials(
153
154
  mq_config[const.MQ_USER],
154
155
  mq_config[const.MQ_PWD]
155
156
  )
156
- connection = pika.BlockingConnection(
157
- pika.ConnectionParameters(
158
- host=mq_config[const.MQ_ADDR],
159
- port=int(mq_config[const.MQ_PORT]),
160
- virtual_host=mq_config[const.MQ_VHOST],
161
- credentials=credentials,
162
- heartbeat=600,
163
- blocked_connection_timeout=300
164
- )
157
+
158
+ connection_params = pika.ConnectionParameters(
159
+ host=mq_config[const.MQ_ADDR],
160
+ port=int(mq_config[const.MQ_PORT]),
161
+ virtual_host=mq_config[const.MQ_VHOST],
162
+ credentials=credentials,
163
+ heartbeat=300, # 减少心跳间隔
164
+ blocked_connection_timeout=60, # 减少阻塞超时
165
+ socket_timeout=30, # 添加socket超时
166
+ connection_attempts=3, # 连接重试次数
167
+ retry_delay=1, # 重试延迟
168
+ stack_timeout=30, # 栈超时
169
+ # 添加TCP连接参数 某些系统上可能不被支持 删除
170
+ # tcp_options={
171
+ # 'TCP_KEEPIDLE': 60,
172
+ # 'TCP_KEEPINTVL': 30,
173
+ # 'TCP_KEEPCNT': 3
174
+ # }
165
175
  )
166
176
 
177
+ connection = pika.BlockingConnection(connection_params)
178
+
179
+ # 验证连接状态
180
+ if not connection.is_open:
181
+ raise Exception("Connection failed to open properly")
182
+
167
183
  cls._connections[mq_key] = connection
168
184
  logging.info(f"Created new RabbitMQ connection for key: {mq_key}")
169
185
 
@@ -254,10 +270,49 @@ class MessageQueueBase:
254
270
  f"you must provide a queue_name to avoid anonymous queues."
255
271
  )
256
272
 
273
+ # def _get_channel(self) -> Any:
274
+ # """获取新的通道"""
275
+ # connection = RabbitMQConnectionPool.get_connection(self._mq_key)
276
+ # return connection.channel()
277
+
257
278
  def _get_channel(self) -> Any:
258
279
  """获取新的通道"""
259
- connection = RabbitMQConnectionPool.get_connection(self._mq_key)
260
- return connection.channel()
280
+ max_attempts = 3
281
+ for attempt in range(max_attempts):
282
+ try:
283
+ connection = RabbitMQConnectionPool.get_connection(self._mq_key)
284
+ if not connection or not connection.is_open:
285
+ raise Exception("Connection is not available or not open")
286
+
287
+ # 添加连接状态检查
288
+ try:
289
+ # 尝试发送心跳检查连接状态
290
+ connection.process_data_events(time_limit=0)
291
+ except:
292
+ raise Exception("Connection heartbeat failed")
293
+
294
+ channel = connection.channel()
295
+ if not channel or not channel.is_open:
296
+ raise Exception("Channel is not available or not open")
297
+ return channel
298
+
299
+ except Exception as e:
300
+ self.logger.warning(f"Failed to get healthy channel (attempt {attempt + 1}): {e}")
301
+ if attempt < max_attempts - 1:
302
+ # 清理并重建连接
303
+ with RabbitMQConnectionPool._connection_lock:
304
+ try:
305
+ RabbitMQConnectionPool._cleanup_connection(self._mq_key)
306
+ RabbitMQConnectionPool._connections[self._mq_key] = None
307
+ except Exception as cleanup_e:
308
+ self.logger.warning(f"Error during connection cleanup: {cleanup_e}")
309
+
310
+ # 短暂等待后重试
311
+ import time
312
+ time.sleep(0.1 * (attempt + 1))
313
+ else:
314
+ # 最后一次尝试失败,抛出异常
315
+ raise Exception(f"Failed to get channel after {max_attempts} attempts: {e}")
261
316
 
262
317
  def _with_retry(self, operation: Callable, *args, **kwargs) -> Any:
263
318
  """带重试机制执行操作"""
@@ -273,8 +328,25 @@ class MessageQueueBase:
273
328
  break
274
329
  else:
275
330
  self.logger.warning(f"Attempt {attempt + 1} failed: {e}. Retrying...")
276
- # 触发连接重建
277
- RabbitMQConnectionPool._connections[self._mq_key] = None
331
+
332
+ # 只在特定错误类型时清理连接
333
+ error_str = str(e).lower()
334
+ if any(keyword in error_str for keyword in [
335
+ 'connection', 'channel', 'socket', 'transport',
336
+ 'callback', 'deque', 'abort', 'closed'
337
+ ]):
338
+ # 安全地清理连接
339
+ with RabbitMQConnectionPool._connection_lock:
340
+ try:
341
+ if self._mq_key in RabbitMQConnectionPool._connections:
342
+ RabbitMQConnectionPool._cleanup_connection(self._mq_key)
343
+ RabbitMQConnectionPool._connections[self._mq_key] = None
344
+ except Exception as cleanup_e:
345
+ self.logger.debug(f"Error during connection cleanup: {cleanup_e}")
346
+
347
+ # 递增延迟重试
348
+ import time
349
+ time.sleep(0.1 * (2 ** attempt))
278
350
 
279
351
  raise last_exception
280
352
 
@@ -498,5 +570,5 @@ if __name__ == "__main__":
498
570
 
499
571
  # 示例3:向后兼容的使用方式
500
572
  print("=== 向后兼容使用 ===")
501
- with MessageQueueBase('test_exchange', 'direct', routing_key='test.key') as old_mq:
573
+ with MessageQueueBase('test_exchange', 'direct', routing_key='test.key', queue_name='task_test_queue') as old_mq:
502
574
  old_mq.publish_message("Hello from old interface!")
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes