sycommon-python-lib 0.1.26__py3-none-any.whl → 0.1.38__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.
@@ -0,0 +1,317 @@
1
+ import io
2
+ import os
3
+ import time
4
+ import inspect
5
+ from typing import Any, Dict, Optional, Literal, Type, TypeVar
6
+ from urllib.parse import urljoin
7
+
8
+ import aiohttp
9
+ from pydantic import BaseModel
10
+ from sycommon.synacos.param import Body, Cookie, File, Form, Header, Param, Path, Query
11
+ from sycommon.logging.kafka_log import SYLogger
12
+ from sycommon.synacos.nacos_service import NacosService
13
+
14
+ # 定义 Pydantic 模型泛型(用于响应解析)
15
+ T = TypeVar('T', bound=BaseModel)
16
+
17
+ # ------------------------------
18
+ # Feign客户端装饰器(支持Pydantic)
19
+ # ------------------------------
20
+
21
+
22
+ def feign_client(
23
+ service_name: str,
24
+ path_prefix: str = "",
25
+ default_timeout: Optional[float] = None,
26
+ default_headers: Optional[Dict[str, str]] = None
27
+ ):
28
+ default_headers = default_headers or {}
29
+
30
+ def decorator(cls):
31
+ class FeignClient:
32
+ def __init__(self):
33
+ self.service_name = service_name
34
+ self.path_prefix = path_prefix
35
+ self.default_timeout = default_timeout
36
+ self.default_headers = default_headers.copy()
37
+ self.nacos_manager: Optional[NacosService] = None
38
+ self.session: Optional[aiohttp.ClientSession] = None
39
+
40
+ def __getattr__(self, name: str):
41
+ if not hasattr(cls, name):
42
+ raise AttributeError(f"类 {cls.__name__} 不存在方法 {name}")
43
+
44
+ func = getattr(cls, name)
45
+ sig = inspect.signature(func)
46
+ param_meta = self._parse_param_meta(sig)
47
+ # 获取响应模型(从返回类型注解中提取 Pydantic 模型)
48
+ resp_model = self._get_response_model(sig)
49
+
50
+ async def wrapper(*args, **kwargs) -> Any:
51
+ if not self.session:
52
+ self.session = aiohttp.ClientSession()
53
+ if not self.nacos_manager:
54
+ self.nacos_manager = NacosService(None)
55
+
56
+ try:
57
+ bound_args = self._bind_arguments(
58
+ func, sig, args, kwargs)
59
+ self._validate_required_params(param_meta, bound_args)
60
+
61
+ request_meta = getattr(func, "_feign_meta", {})
62
+ method = request_meta.get("method", "GET").upper()
63
+ path = request_meta.get("path", "")
64
+ is_upload = request_meta.get("is_upload", False)
65
+ method_headers = request_meta.get("headers", {})
66
+ timeout = request_meta.get(
67
+ "timeout", self.default_timeout)
68
+
69
+ headers = self._build_headers(
70
+ param_meta, bound_args, method_headers)
71
+ full_path = f"{self.path_prefix}{path}"
72
+ full_path = self._replace_path_params(
73
+ full_path, param_meta, bound_args)
74
+
75
+ base_url = await self._get_service_base_url(headers)
76
+ url = urljoin(base_url, full_path)
77
+ SYLogger.info(f"请求: {method} {url}")
78
+
79
+ query_params = self._get_query_params(
80
+ param_meta, bound_args)
81
+ cookies = self._get_cookies(param_meta, bound_args)
82
+ # 处理请求数据(支持 Pydantic 模型转字典)
83
+ request_data = await self._get_request_data(
84
+ method, param_meta, bound_args, is_upload, method_headers
85
+ )
86
+
87
+ async with self.session.request(
88
+ method=method,
89
+ url=url,
90
+ headers=headers,
91
+ params=query_params,
92
+ cookies=cookies,
93
+ json=request_data if not (is_upload or isinstance(
94
+ request_data, aiohttp.FormData)) else None,
95
+ data=request_data if is_upload or isinstance(
96
+ request_data, aiohttp.FormData) else None,
97
+ timeout=timeout
98
+ ) as response:
99
+ # 处理响应(支持 Pydantic 模型解析)
100
+ return await self._handle_response(response, resp_model)
101
+
102
+ finally:
103
+ if self.session:
104
+ await self.session.close()
105
+ self.session = None
106
+
107
+ return wrapper
108
+
109
+ def _parse_param_meta(self, sig: inspect.Signature) -> Dict[str, Param]:
110
+ param_meta = {}
111
+ for param in sig.parameters.values():
112
+ if param.name == "self":
113
+ continue
114
+ if isinstance(param.default, Param):
115
+ param_meta[param.name] = param.default
116
+ else:
117
+ if param.default == inspect.Parameter.empty:
118
+ param_meta[param.name] = Query(..., description="")
119
+ else:
120
+ param_meta[param.name] = Query(
121
+ param.default, description="")
122
+ return param_meta
123
+
124
+ def _get_response_model(self, sig: inspect.Signature) -> Optional[Type[BaseModel]]:
125
+ """从函数返回类型注解中提取 Pydantic 模型"""
126
+ return_annotation = sig.return_annotation
127
+ # 支持直接注解(如 -> ProductResp)或 Optional(如 -> Optional[ProductResp])
128
+ if hasattr(return_annotation, '__origin__') and return_annotation.__origin__ is Optional:
129
+ return_annotation = return_annotation.__args__[0]
130
+ # 检查是否为 Pydantic 模型
131
+ if inspect.isclass(return_annotation) and issubclass(return_annotation, BaseModel):
132
+ return return_annotation
133
+ return None
134
+
135
+ def _bind_arguments(self, func, sig: inspect.Signature, args, kwargs) -> Dict[str, Any]:
136
+ try:
137
+ bound_args = sig.bind(*args, **kwargs)
138
+ bound_args.apply_defaults()
139
+ return {k: v for k, v in bound_args.arguments.items() if k != "self"}
140
+ except TypeError as e:
141
+ SYLogger.error(f"参数绑定失败 [{func.__name__}]: {str(e)}")
142
+ raise
143
+
144
+ def _validate_required_params(self, param_meta: Dict[str, Param], bound_args: Dict[str, Any]):
145
+ missing = [
146
+ meta.get_key(name) for name, meta in param_meta.items()
147
+ if meta.is_required() and name not in bound_args
148
+ ]
149
+ if missing:
150
+ raise ValueError(f"缺少必填参数: {', '.join(missing)}")
151
+
152
+ def _build_headers(self, param_meta: Dict[str, Param], bound_args: Dict[str, Any], method_headers: Dict[str, str]) -> Dict[str, str]:
153
+ headers = self.default_headers.copy()
154
+ headers.update(method_headers)
155
+ for name, meta in param_meta.items():
156
+ if isinstance(meta, Header) and name in bound_args:
157
+ value = bound_args[name]
158
+ if value is not None:
159
+ headers[meta.get_key(name)] = str(value)
160
+ return headers
161
+
162
+ def _replace_path_params(self, path: str, param_meta: Dict[str, Param], bound_args: Dict[str, Any]) -> str:
163
+ for name, meta in param_meta.items():
164
+ if isinstance(meta, Path) and name in bound_args:
165
+ path = path.replace(
166
+ f"{{{meta.get_key(name)}}}", str(bound_args[name]))
167
+ return path
168
+
169
+ def _get_query_params(self, param_meta: Dict[str, Param], bound_args: Dict[str, Any]) -> Dict[str, str]:
170
+ return {
171
+ param_meta[name].get_key(name): str(value)
172
+ for name, value in bound_args.items()
173
+ if isinstance(param_meta.get(name), Query) and value is not None
174
+ }
175
+
176
+ def _get_cookies(self, param_meta: Dict[str, Param], bound_args: Dict[str, Any]) -> Dict[str, str]:
177
+ return {
178
+ param_meta[name].get_key(name): str(value)
179
+ for name, value in bound_args.items()
180
+ if isinstance(param_meta.get(name), Cookie) and value is not None
181
+ }
182
+
183
+ async def _get_request_data(
184
+ self,
185
+ method: str,
186
+ param_meta: Dict[str, Param],
187
+ bound_args: Dict[str, Any],
188
+ is_upload: bool,
189
+ method_headers: Dict[str, str]
190
+ ) -> Any:
191
+ """处理请求数据(支持 Pydantic 模型转字典)"""
192
+ if is_upload:
193
+ form_data = aiohttp.FormData()
194
+ # 处理文件
195
+ file_params = {
196
+ n: m for n, m in param_meta.items() if isinstance(m, File)}
197
+ for name, meta in file_params.items():
198
+ if name not in bound_args:
199
+ continue
200
+ file_paths = bound_args[name]
201
+ file_paths = [file_paths] if isinstance(
202
+ file_paths, str) else file_paths
203
+ for path in file_paths:
204
+ if not os.path.exists(path):
205
+ raise FileNotFoundError(f"文件不存在: {path}")
206
+ with open(path, "rb") as f:
207
+ form_data.add_field(
208
+ meta.field_name, f.read(), filename=os.path.basename(path)
209
+ )
210
+ # 处理表单字段(支持 Pydantic 模型)
211
+ form_params = {
212
+ n: m for n, m in param_meta.items() if isinstance(m, Form)}
213
+ for name, meta in form_params.items():
214
+ if name not in bound_args or bound_args[name] is None:
215
+ continue
216
+ value = bound_args[name]
217
+ # 若为 Pydantic 模型,转为字典
218
+ if isinstance(value, BaseModel):
219
+ value = value.dict()
220
+ form_data.add_field(meta.get_key(name), str(
221
+ value) if not isinstance(value, dict) else value)
222
+ return form_data
223
+
224
+ # 处理表单提交(x-www-form-urlencoded)
225
+ content_type = self.default_headers.get(
226
+ "Content-Type") or method_headers.get("Content-Type", "")
227
+ if "application/x-www-form-urlencoded" in content_type:
228
+ form_data = {}
229
+ for name, value in bound_args.items():
230
+ meta = param_meta.get(name)
231
+ if isinstance(meta, Form) and value is not None:
232
+ # Pydantic 模型转字典
233
+ if isinstance(value, BaseModel):
234
+ value = value.dict()
235
+ form_data[meta.get_key(name)] = str(
236
+ value) if not isinstance(value, dict) else value
237
+ return form_data
238
+
239
+ # 处理 JSON 请求体(支持 Pydantic 模型)
240
+ if method in ["POST", "PUT", "PATCH", "DELETE"]:
241
+ body_params = [
242
+ name for name, meta in param_meta.items() if isinstance(meta, Body)]
243
+ if body_params:
244
+ body_data = {}
245
+ for name in body_params:
246
+ meta = param_meta[name]
247
+ value = bound_args.get(name)
248
+ if value is None:
249
+ continue
250
+ # 若为 Pydantic 模型,转为字典
251
+ if isinstance(value, BaseModel):
252
+ value = value.dict()
253
+ if meta.embed:
254
+ body_data[meta.get_key(name)] = value
255
+ else:
256
+ body_data = value if not isinstance(value, dict) else {
257
+ ** body_data, **value}
258
+ return body_data
259
+ return None
260
+
261
+ async def _get_service_base_url(self, headers: Dict[str, str]) -> str:
262
+ version = headers.get("s-y-version")
263
+ instances = self.nacos_manager.get_service_instances(
264
+ self.service_name, target_version=version)
265
+ if not instances:
266
+ raise RuntimeError(f"服务 [{self.service_name}] 无可用实例")
267
+ return f"http://{instances[int(time.time()) % len(instances)]['ip']}:{instances[0]['port']}"
268
+
269
+ async def _handle_response(self, response: aiohttp.ClientResponse, resp_model: Optional[Type[BaseModel]]) -> Any:
270
+ """处理响应(支持 Pydantic 模型解析)"""
271
+ status = response.status
272
+ if 200 <= status < 300:
273
+ content_type = response.headers.get("Content-Type", "")
274
+ if "application/json" in content_type:
275
+ json_data = await response.json()
276
+ # 若指定了 Pydantic 响应模型,自动解析
277
+ if resp_model is not None:
278
+ return resp_model(** json_data) # 用响应数据初始化模型
279
+ return json_data
280
+ else:
281
+ return io.BytesIO(await response.read())
282
+ else:
283
+ error_msg = await response.text()
284
+ SYLogger.error(f"请求失败 [{status}]: {error_msg}")
285
+ raise RuntimeError(f"HTTP {status}: {error_msg}")
286
+
287
+ return FeignClient
288
+
289
+ return decorator
290
+
291
+
292
+ def feign_request(
293
+ method: Literal["GET", "POST", "PUT", "DELETE", "PATCH"],
294
+ path: str,
295
+ headers: Optional[Dict[str, str]] = None,
296
+ timeout: Optional[float] = None
297
+ ):
298
+ def decorator(func):
299
+ func._feign_meta = {
300
+ "method": method.upper(),
301
+ "path": path,
302
+ "headers": headers.copy() if headers else {},
303
+ "is_upload": False,
304
+ "timeout": timeout
305
+ }
306
+ return func
307
+ return decorator
308
+
309
+
310
+ def feign_upload(field_name: str = "file"):
311
+ def decorator(func):
312
+ if not hasattr(func, "_feign_meta"):
313
+ raise ValueError("feign_upload必须与feign_request一起使用")
314
+ func._feign_meta["is_upload"] = True
315
+ func._feign_meta["upload_field"] = field_name
316
+ return func
317
+ return decorator
@@ -47,7 +47,7 @@ class NacosService(metaclass=SingletonMeta):
47
47
  self.retry_backoff = self.nacos_config.get('retryBackoff', 1.5)
48
48
  self.max_retry_delay = self.nacos_config.get('maxRetryDelay', 30)
49
49
  self.heartbeat_interval = self.nacos_config.get(
50
- 'heartbeatInterval', 10)
50
+ 'heartbeatInterval', 15)
51
51
  self.register_retry_interval = self.nacos_config.get(
52
52
  'registerRetryInterval', 5) # 注册重试间隔
53
53
 
@@ -87,12 +87,18 @@ class NacosService(metaclass=SingletonMeta):
87
87
  # 心跳相关
88
88
  self._last_heartbeat_time = 0
89
89
  self._heartbeat_fail_count = 0
90
- self._heartbeat_lock = threading.Lock() # 控制心跳线程创建的锁
90
+ self._heartbeat_lock = threading.Lock()
91
91
  self._heartbeat_thread = None
92
92
 
93
93
  self.max_heartbeat_timeout = self.nacos_config.get(
94
- 'maxHeartbeatTimeout', 30) # 最大无心跳时间(秒)
95
- self._last_successful_heartbeat = time.time() # 上次成功心跳时间戳
94
+ 'maxHeartbeatTimeout', 30)
95
+ self._last_successful_heartbeat = time.time()
96
+ # 连接监控检查间隔(新增配置,默认30秒,避免硬编码)
97
+ self.connection_check_interval = self.nacos_config.get(
98
+ 'connectionCheckInterval', 30)
99
+ # 配置监视线程检查间隔(默认30秒)
100
+ self.config_watch_interval = self.nacos_config.get(
101
+ 'configWatchInterval', 30)
96
102
 
97
103
  # 启动配置监视线程
98
104
  self._watch_thread = threading.Thread(
@@ -586,10 +592,9 @@ class NacosService(metaclass=SingletonMeta):
586
592
 
587
593
  def monitor_connection(self):
588
594
  """优化的连接监控线程,缩短检查间隔"""
589
- # 缩短检查间隔(5秒一次)
590
- check_interval = self.nacos_config.get('checkInterval', 5)
591
- thread_start_time = time.time() # 线程启动时间
592
- check_counter = 0 # 检查计数器
595
+ check_interval = self.connection_check_interval
596
+ thread_start_time = time.time()
597
+ check_counter = 0
593
598
 
594
599
  while not self._shutdown_event.is_set():
595
600
  try:
@@ -739,7 +744,7 @@ class NacosService(metaclass=SingletonMeta):
739
744
 
740
745
  def _watch_configs(self):
741
746
  """配置监听线程"""
742
- check_interval = 5 # 固定检查间隔
747
+ check_interval = self.config_watch_interval
743
748
 
744
749
  while not self._shutdown_event.is_set():
745
750
  try:
@@ -750,7 +755,7 @@ class NacosService(metaclass=SingletonMeta):
750
755
  self._config_cache[data_id] = new_config
751
756
  except Exception as e:
752
757
  SYLogger.error(f"nacos:配置监视线程异常: {str(e)}")
753
- self._shutdown_event.wait(check_interval) # 检查间隔
758
+ self._shutdown_event.wait(check_interval)
754
759
 
755
760
  def discover_services(self, service_name: str, group: str = "DEFAULT_GROUP", version: str = None) -> List[Dict]:
756
761
  """发现服务实例列表 (与Java格式兼容)"""
@@ -0,0 +1,75 @@
1
+ from typing import Any, Optional
2
+
3
+ # ------------------------------
4
+ # 参数类型标记类(兼容 Pydantic)
5
+ # ------------------------------
6
+
7
+
8
+ class Param:
9
+ """基础参数元信息类"""
10
+
11
+ def __init__(
12
+ self,
13
+ default: Any = ...,
14
+ description: str = "",
15
+ alias: Optional[str] = None,
16
+ deprecated: bool = False
17
+ ):
18
+ self.default = default # ... 表示必填
19
+ self.description = description
20
+ self.alias = alias
21
+ self.deprecated = deprecated
22
+
23
+ def is_required(self) -> bool:
24
+ return self.default is ...
25
+
26
+ def get_key(self, param_name: str) -> str:
27
+ return self.alias if self.alias is not None else param_name
28
+
29
+
30
+ class Path(Param):
31
+ """路径参数"""
32
+ pass
33
+
34
+
35
+ class Query(Param):
36
+ """查询参数"""
37
+ pass
38
+
39
+
40
+ class Header(Param):
41
+ """请求头参数"""
42
+
43
+ def __init__(self, *args, convert_underscores: bool = True, **kwargs):
44
+ super().__init__(*args, **kwargs)
45
+ self.convert_underscores = convert_underscores
46
+
47
+ def get_key(self, param_name: str) -> str:
48
+ key = super().get_key(param_name)
49
+ return key.replace("_", "-") if self.convert_underscores else key
50
+
51
+
52
+ class Cookie(Param):
53
+ """Cookie参数"""
54
+ pass
55
+
56
+
57
+ class Body(Param):
58
+ """JSON请求体参数(支持Pydantic模型)"""
59
+
60
+ def __init__(self, *args, embed: bool = False, ** kwargs):
61
+ super().__init__(*args, **kwargs)
62
+ self.embed = embed # 是否包装在键中
63
+
64
+
65
+ class Form(Param):
66
+ """表单参数(支持Pydantic模型)"""
67
+ pass
68
+
69
+
70
+ class File(Param):
71
+ """文件上传参数"""
72
+
73
+ def __init__(self, *args, field_name: str = "file", ** kwargs):
74
+ super().__init__(*args, **kwargs)
75
+ self.field_name = field_name
@@ -1,24 +1,24 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sycommon-python-lib
3
- Version: 0.1.26
3
+ Version: 0.1.38
4
4
  Summary: Add your description here
5
5
  Requires-Python: >=3.10
6
6
  Description-Content-Type: text/markdown
7
7
  Requires-Dist: aio-pika>=9.5.7
8
- Requires-Dist: aiohttp>=3.12.15
8
+ Requires-Dist: aiohttp>=3.13.1
9
9
  Requires-Dist: decorator>=5.2.1
10
- Requires-Dist: fastapi>=0.118.0
10
+ Requires-Dist: fastapi>=0.120.0
11
11
  Requires-Dist: kafka-python>=2.2.15
12
12
  Requires-Dist: loguru>=0.7.3
13
- Requires-Dist: mysql-connector-python>=9.4.0
13
+ Requires-Dist: mysql-connector-python>=9.5.0
14
14
  Requires-Dist: nacos-sdk-python>=2.0.9
15
- Requires-Dist: pydantic>=2.11.9
16
- Requires-Dist: python-dotenv>=1.1.1
15
+ Requires-Dist: pydantic>=2.12.3
16
+ Requires-Dist: python-dotenv>=1.2.1
17
17
  Requires-Dist: pyyaml>=6.0.3
18
- Requires-Dist: sqlalchemy>=2.0.43
19
- Requires-Dist: starlette>=0.46.2
18
+ Requires-Dist: sqlalchemy>=2.0.44
19
+ Requires-Dist: starlette>=0.48.0
20
20
  Requires-Dist: uuid>=1.30
21
- Requires-Dist: uvicorn>=0.37.0
21
+ Requires-Dist: uvicorn>=0.38.0
22
22
 
23
23
  # sycommon-python-lib
24
24
 
@@ -1,6 +1,6 @@
1
1
  command/cli.py,sha256=bP2LCLkRvfETIwWkVD70q5xFxMI4D3BpH09Ws1f-ENc,5849
2
2
  sycommon/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- sycommon/services.py,sha256=s9xbXiwehZeO4ZnS_8UKFY-LBkdGwbmsK-BB3pmFZuo,8766
3
+ sycommon/services.py,sha256=e9odPBLUoAAUkFU4s8ITIQUbr1GH7dqb9qSHyUhN4A8,11258
4
4
  sycommon/config/Config.py,sha256=9yO5b8WfvEDvkyrGrlwrLFasgh_-MjcEvGF20Gz5Xo4,3041
5
5
  sycommon/config/DatabaseConfig.py,sha256=ILiUuYT9_xJZE2W-RYuC3JCt_YLKc1sbH13-MHIOPhg,804
6
6
  sycommon/config/EmbeddingConfig.py,sha256=gPKwiDYbeu1GpdIZXMmgqM7JqBIzCXi0yYuGRLZooMI,362
@@ -15,9 +15,9 @@ sycommon/health/health_check.py,sha256=EhfbhspRpQiKJaxdtE-PzpKQO_ucaFKtQxIm16F5M
15
15
  sycommon/health/metrics.py,sha256=fHqO73JuhoZkNPR-xIlxieXiTCvttq-kG-tvxag1s1s,268
16
16
  sycommon/health/ping.py,sha256=FTlnIKk5y1mPfS1ZGOeT5IM_2udF5aqVLubEtuBp18M,250
17
17
  sycommon/logging/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
- sycommon/logging/kafka_log.py,sha256=3HjBg3WoDd3DmjtAlpyLcAVTKI-AHKrKlKmmPerq9tU,20751
18
+ sycommon/logging/kafka_log.py,sha256=qHq4sU42aGrTm9DWYKxGDp1pe9ENfYSbzI4iPDPNvJQ,21128
19
19
  sycommon/logging/logger_wrapper.py,sha256=TiHsrIIHiQMzXgXK12-0KIpU9GhwQJOoHslakzmq2zc,357
20
- sycommon/logging/sql_logger.py,sha256=fu-sDqEOM9ovoUo6NNu9EIj2tQSE4stcF1maTPTBS64,2505
20
+ sycommon/logging/sql_logger.py,sha256=aEU3OGnI_51Tjyuuf4FpUi9KPTceFRuKAOyQbPzGhzM,2021
21
21
  sycommon/middleware/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
22
  sycommon/middleware/context.py,sha256=_5ghpv4u_yAvjkgM-XDx8OnO-YI1XtntHrXsHJHZkwo,88
23
23
  sycommon/middleware/cors.py,sha256=0B5d_ovD56wcH9TfktRs88Q09R9f8Xx5h5ALWYvE8Iw,600
@@ -31,25 +31,29 @@ sycommon/middleware/traceid.py,sha256=oGTJ2jtdea_3NgaAwXLpUug5dGUYRQeM4r1n2icuvC
31
31
  sycommon/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
32
32
  sycommon/models/base_http.py,sha256=EICAAibx3xhjBsLqm35Mi3DCqxp0FME4rD_3iQVjT_E,3051
33
33
  sycommon/models/log.py,sha256=rZpj6VkDRxK3B6H7XSeWdYZshU8F0Sks8bq1p6pPlDw,500
34
- sycommon/models/mqlistener_config.py,sha256=PPwhAVJ2AWvVAvNox_1t0fuBKTyRH3Ui9cuuU-q7Byo,1590
34
+ sycommon/models/mqlistener_config.py,sha256=vXp2uMmd0XQ5B9noSRXWHewTy-juQ2y7IsWtISJD5aI,1661
35
35
  sycommon/models/mqmsg_model.py,sha256=cxn0M5b0utQK6crMYmL-1waeGYHvK3AlGaRy23clqTE,277
36
36
  sycommon/models/mqsend_config.py,sha256=NQX9dc8PpuquMG36GCVhJe8omAW1KVXXqr6lSRU6D7I,268
37
37
  sycommon/models/sso_user.py,sha256=i1WAN6k5sPcPApQEdtjpWDy7VrzWLpOrOQewGLGoGIw,2702
38
- sycommon/rabbitmq/rabbitmq_client.py,sha256=Grjl_vDFe8fzyjw-bjOE_0keQwi-MQgB_GejCcBssTQ,27099
38
+ sycommon/rabbitmq/rabbitmq_client.py,sha256=eLfYuLSZuhMJ0Y-gn8dG1BBVvvKPrQLipAf1-Fub63I,42660
39
39
  sycommon/rabbitmq/rabbitmq_pool.py,sha256=_NMOO4CZy-I_anMqpzfYinz-8373_rg5FM9eqzdjGyU,3598
40
- sycommon/rabbitmq/rabbitmq_service.py,sha256=NWoMtRhvLjEsIX3sMgaSkrguE3gT5wLYj0u7laWZh8c,29997
40
+ sycommon/rabbitmq/rabbitmq_service.py,sha256=fylrwIBYJfR2D7o2k_WxAbK5ZNNFV__vMcLBrmXe8-k,36589
41
41
  sycommon/sse/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
42
42
  sycommon/sse/event.py,sha256=k_rBJy23R7crtzQeetT0Q73D8o5-5p-eESGSs_BPOj0,2797
43
43
  sycommon/sse/sse.py,sha256=__CfWEcYxOxQ-HpLor4LTZ5hLWqw9-2X7CngqbVHsfw,10128
44
44
  sycommon/synacos/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
45
- sycommon/synacos/feign.py,sha256=qALBl3YwVGvAzgx6tvwW84GptfS1u8WpapTRTygZROM,21282
46
- sycommon/synacos/nacos_service.py,sha256=kFGtOTKL6ZuFLebDK6gK6YNqdthhFW0aaXfG2eWzrzY,34493
45
+ sycommon/synacos/example.py,sha256=61XL03tU8WTNOo3FUduf93F2fAwah1S0lbH1ufhRhRk,5739
46
+ sycommon/synacos/example2.py,sha256=adUaru3Hy482KrOA17DfaC4nwvLj8etIDS_KrWLWmCU,4811
47
+ sycommon/synacos/feign.py,sha256=0cmnyExXcr1qIV0B_POdQ-_u4-t5K3LjJD_8rDaXwSE,7467
48
+ sycommon/synacos/feign_client.py,sha256=JxzxohrsscQNlAjRVo_3ZQrMQSfVHFOtRYyEnP6sDGk,15205
49
+ sycommon/synacos/nacos_service.py,sha256=QG1lShrVZNKbExYV_IUwGXTHDnU09RYXooVy_llhW6c,34661
50
+ sycommon/synacos/param.py,sha256=KcfSkxnXOa0TGmCjY8hdzU9pzUsA8-4PeyBKWI2-568,1765
47
51
  sycommon/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
48
52
  sycommon/tools/docs.py,sha256=OPj2ETheuWjXLyaXtaZPbwmJKfJaYXV5s4XMVAUNrms,1607
49
53
  sycommon/tools/snowflake.py,sha256=DdEj3T5r5OEvikp3puxqmmmz6BrggxomoSlnsRFb5dM,1174
50
54
  sycommon/tools/timing.py,sha256=OiiE7P07lRoMzX9kzb8sZU9cDb0zNnqIlY5pWqHcnkY,2064
51
- sycommon_python_lib-0.1.26.dist-info/METADATA,sha256=9dmi_waOOjJUIgDQipHgAs5ka-HBz3rXC00ZeMCitR8,7038
52
- sycommon_python_lib-0.1.26.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
53
- sycommon_python_lib-0.1.26.dist-info/entry_points.txt,sha256=q_h2nbvhhmdnsOUZEIwpuoDjaNfBF9XqppDEmQn9d_A,46
54
- sycommon_python_lib-0.1.26.dist-info/top_level.txt,sha256=98CJ-cyM2WIKxLz-Pf0AitWLhJyrfXvyY8slwjTXNuc,17
55
- sycommon_python_lib-0.1.26.dist-info/RECORD,,
55
+ sycommon_python_lib-0.1.38.dist-info/METADATA,sha256=ttyk1WD6XP7AfWf4usymgNcm0ILuA_T5gijUTf3FCJ4,7037
56
+ sycommon_python_lib-0.1.38.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
57
+ sycommon_python_lib-0.1.38.dist-info/entry_points.txt,sha256=q_h2nbvhhmdnsOUZEIwpuoDjaNfBF9XqppDEmQn9d_A,46
58
+ sycommon_python_lib-0.1.38.dist-info/top_level.txt,sha256=98CJ-cyM2WIKxLz-Pf0AitWLhJyrfXvyY8slwjTXNuc,17
59
+ sycommon_python_lib-0.1.38.dist-info/RECORD,,