sycommon-python-lib 0.1.55__py3-none-any.whl → 0.1.55a0__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.
sycommon/synacos/feign.py CHANGED
@@ -2,7 +2,6 @@ import io
2
2
  import os
3
3
  import time
4
4
 
5
- from sycommon.tools.merge_headers import merge_headers
6
5
  from sycommon.tools.snowflake import Snowflake
7
6
 
8
7
  import aiohttp
@@ -25,18 +24,14 @@ async def feign(service_name, api_path, method='GET', params=None, headers=None,
25
24
  try:
26
25
  # 初始化headers,确保是可修改的字典
27
26
  headers = headers.copy() if headers else {}
28
- headers = merge_headers(SYLogger.get_headers(), headers)
29
27
  if "x-traceId-header" not in headers:
30
- headers["x-traceId-header"] = SYLogger.get_trace_id() or Snowflake.id
28
+ headers["x-traceId-header"] = SYLogger.get_trace_id() or Snowflake.next_id()
31
29
 
32
30
  # 处理JSON请求的Content-Type
33
31
  is_json_request = method.upper() in ["POST", "PUT", "PATCH"] and not (
34
32
  files or form_data or file_path)
35
- if is_json_request:
36
- # 将headers的key全部转为小写,统一判断
37
- headers_lower = {k.lower(): v for k, v in headers.items()}
38
- if "content-type" not in headers_lower:
39
- headers["Content-Type"] = "application/json"
33
+ if is_json_request and "Content-Type" not in headers:
34
+ headers["Content-Type"] = "application/json"
40
35
 
41
36
  nacos_service = NacosService(None)
42
37
  version = headers.get('s-y-version')
@@ -52,7 +47,7 @@ async def feign(service_name, api_path, method='GET', params=None, headers=None,
52
47
  instance = instances[int(time.time()) % len(instances)]
53
48
 
54
49
  SYLogger.info(f"nacos:开始调用服务: {service_name}")
55
- # SYLogger.info(f"nacos:请求头: {headers}")
50
+ SYLogger.info(f"nacos:请求头: {headers}")
56
51
 
57
52
  ip = instance.get('ip')
58
53
  port = instance.get('port')
@@ -5,7 +5,6 @@ import inspect
5
5
  from typing import Any, Dict, Optional, Literal, Type, TypeVar
6
6
  from urllib.parse import urljoin
7
7
 
8
- from sycommon.tools.merge_headers import merge_headers
9
8
  from sycommon.tools.snowflake import Snowflake
10
9
 
11
10
  import aiohttp
@@ -29,9 +28,7 @@ def feign_client(
29
28
  default_headers: Optional[Dict[str, str]] = None
30
29
  ):
31
30
  default_headers = default_headers or {}
32
- default_headers = {k.lower(): v for k, v in default_headers.items()}
33
- default_headers = merge_headers(SYLogger.get_headers(), default_headers)
34
- default_headers["x-traceId-header"] = SYLogger.get_trace_id() or Snowflake.id
31
+ default_headers["x-traceId-header"] = SYLogger.get_trace_id() or Snowflake.next_id()
35
32
 
36
33
  def decorator(cls):
37
34
  class FeignClient:
@@ -39,8 +36,7 @@ def feign_client(
39
36
  self.service_name = service_name
40
37
  self.path_prefix = path_prefix
41
38
  self.default_timeout = default_timeout
42
- self.default_headers = {
43
- k.lower(): v for k, v in default_headers.copy().items()}
39
+ self.default_headers = default_headers.copy()
44
40
  self.nacos_manager: Optional[NacosService] = None
45
41
  self.session: Optional[aiohttp.ClientSession] = None
46
42
 
@@ -69,8 +65,7 @@ def feign_client(
69
65
  method = request_meta.get("method", "GET").upper()
70
66
  path = request_meta.get("path", "")
71
67
  is_upload = request_meta.get("is_upload", False)
72
- method_headers = {
73
- k.lower(): v for k, v in request_meta.get("headers", {}).items()}
68
+ method_headers = request_meta.get("headers", {})
74
69
  timeout = request_meta.get(
75
70
  "timeout", self.default_timeout)
76
71
 
@@ -160,16 +155,12 @@ def feign_client(
160
155
  def _build_headers(self, param_meta: Dict[str, Param], bound_args: Dict[str, Any], method_headers: Dict[str, str]) -> Dict[str, str]:
161
156
  headers = self.default_headers.copy()
162
157
  headers.update(method_headers)
163
- headers = merge_headers(SYLogger.get_headers(), headers)
164
- headers["x-traceId-header"] = SYLogger.get_trace_id() or Snowflake.id
165
-
166
- # 处理参数中的Header类型
158
+ headers["x-traceId-header"] = SYLogger.get_trace_id() or Snowflake.next_id()
167
159
  for name, meta in param_meta.items():
168
160
  if isinstance(meta, Header) and name in bound_args:
169
161
  value = bound_args[name]
170
162
  if value is not None:
171
- header_key = meta.get_key(name).lower()
172
- headers[header_key] = str(value)
163
+ headers[meta.get_key(name)] = str(value)
173
164
  return headers
174
165
 
175
166
  def _replace_path_params(self, path: str, param_meta: Dict[str, Param], bound_args: Dict[str, Any]) -> str:
@@ -234,14 +225,10 @@ def feign_client(
234
225
  value) if not isinstance(value, dict) else value)
235
226
  return form_data
236
227
 
237
- # 从headers中获取Content-Type(已小写key)
238
- content_type = self.default_headers.get(
239
- "content-type") or method_headers.get("content-type", "")
240
- # 转为小写进行判断
241
- content_type_lower = content_type.lower()
242
-
243
228
  # 处理表单提交(x-www-form-urlencoded)
244
- if "application/x-www-form-urlencoded" in content_type_lower:
229
+ content_type = self.default_headers.get(
230
+ "Content-Type") or method_headers.get("Content-Type", "")
231
+ if "application/x-www-form-urlencoded" in content_type:
245
232
  form_data = {}
246
233
  for name, value in bound_args.items():
247
234
  meta = param_meta.get(name)
@@ -287,8 +274,7 @@ def feign_client(
287
274
  """处理响应(支持 Pydantic 模型解析)"""
288
275
  status = response.status
289
276
  if 200 <= status < 300:
290
- content_type = response.headers.get(
291
- "content-type", "").lower()
277
+ content_type = response.headers.get("Content-Type", "")
292
278
  if "application/json" in content_type:
293
279
  json_data = await response.json()
294
280
  # 若指定了 Pydantic 响应模型,自动解析
@@ -317,7 +303,7 @@ def feign_request(
317
303
  func._feign_meta = {
318
304
  "method": method.upper(),
319
305
  "path": path,
320
- "headers": {k.lower(): v for k, v in headers.items()} if headers else {},
306
+ "headers": headers.copy() if headers else {},
321
307
  "is_upload": False,
322
308
  "timeout": timeout
323
309
  }
@@ -15,6 +15,8 @@ import random
15
15
  from sycommon.config.Config import SingletonMeta
16
16
  from sycommon.logging.kafka_log import SYLogger
17
17
 
18
+ logging.getLogger("nacos.client").setLevel(logging.WARNING)
19
+
18
20
 
19
21
  class NacosService(metaclass=SingletonMeta):
20
22
  def __init__(self, config):
@@ -3,29 +3,13 @@ import threading
3
3
  import socket
4
4
  import hashlib
5
5
  import random
6
- import os
7
- from typing import Optional, Type, Any
6
+ from typing import Optional
8
7
  from os import environ
9
- import psutil
10
-
11
-
12
- class ClassProperty:
13
- """
14
- 自定义类属性描述符,替代 @classmethod + @property 的废弃写法
15
- 支持通过 类.属性 的方式访问,无需实例化
16
- """
17
-
18
- def __init__(self, func):
19
- self.func = func
20
-
21
- def __get__(self, instance: Any, cls: Type) -> str:
22
- # 调用传入的函数,并传入类本身作为第一个参数
23
- return self.func(cls)
8
+ import netifaces
24
9
 
25
10
 
26
11
  class Snowflake:
27
- """雪花算法生成器(生产级优化版,无公网依赖,适配内网/K8s环境)"""
28
- # 基础配置(可根据业务调整)
12
+ """雪花算法生成器(无公网依赖,适配内网环境)"""
29
13
  START_TIMESTAMP = 1388534400000 # 2014-01-01 00:00:00
30
14
  SEQUENCE_BITS = 12
31
15
  MACHINE_ID_BITS = 10
@@ -33,10 +17,8 @@ class Snowflake:
33
17
  MAX_SEQUENCE = (1 << SEQUENCE_BITS) - 1
34
18
  MACHINE_ID_SHIFT = SEQUENCE_BITS
35
19
  TIMESTAMP_SHIFT = SEQUENCE_BITS + MACHINE_ID_BITS
36
- CLOCK_BACKWARD_THRESHOLD = 5 # 容忍的时钟回拨阈值(毫秒)
37
- _MAX_JAVA_LONG = 9223372036854775807 # Java Long最大值
38
20
 
39
- # 类级别的单例实例(线程安全)
21
+ # 类级别的单例实例
40
22
  _instance = None
41
23
  _instance_lock = threading.Lock()
42
24
 
@@ -45,38 +27,22 @@ class Snowflake:
45
27
  初始化:优先使用传入的machine_id,否则自动从K8s环境获取
46
28
  :param machine_id: 手动指定机器ID(None则自动计算)
47
29
  """
48
- # 前置校验:确保雪花ID不会超过Java Long最大值
49
- self._validate_timestamp_range()
50
-
51
30
  # 自动计算K8s环境下的machine_id
52
31
  if machine_id is None:
53
32
  machine_id = self._get_k8s_machine_id()
54
33
 
55
- # 校验machine_id合法性
56
34
  if not (0 <= machine_id <= self.MAX_MACHINE_ID):
57
35
  raise ValueError(f"机器ID必须在0~{self.MAX_MACHINE_ID}之间")
58
36
 
59
- # 初始化核心参数
60
37
  self.machine_id = machine_id
61
38
  self.last_timestamp = -1
62
39
  self.sequence = 0
63
40
  self.lock = threading.Lock()
64
41
 
65
- def _validate_timestamp_range(self):
66
- """校验当前时间戳是否在雪花ID支持的范围内,避免超过Java Long最大值"""
67
- max_support_timestamp = self.START_TIMESTAMP + \
68
- (1 << (64 - self.TIMESTAMP_SHIFT)) - 1
69
- current_timestamp = self._get_current_timestamp()
70
- if current_timestamp > max_support_timestamp:
71
- raise RuntimeError(
72
- f"当前时间戳({current_timestamp})超过雪花ID支持的最大时间戳({max_support_timestamp}),"
73
- f"请调整START_TIMESTAMP或减少TIMESTAMP_SHIFT位数"
74
- )
75
-
76
42
  def _get_k8s_machine_id(self) -> int:
77
43
  """
78
- 从K8s环境自动计算唯一machine_id(无公网依赖,多层兜底,降低重复风险):
79
- 优先级:POD_NAME > POD_IP > 容器内网IP(psutil读取) > 容器主机名 > 进程+时间+随机数(最终兜底)
44
+ 从K8s环境自动计算唯一machine_id(无公网依赖,多层兜底):
45
+ 优先级:POD_NAME > POD_IP > 容器内网IP(网卡读取) > 容器主机名 > 随机数(最终兜底)
80
46
  """
81
47
  # 1. 优先读取K8s内置的POD_NAME(默认注入,优先级最高)
82
48
  pod_name = environ.get("POD_NAME")
@@ -88,73 +54,72 @@ class Snowflake:
88
54
  if pod_ip:
89
55
  return self._hash_to_machine_id(pod_ip)
90
56
 
91
- # 3. 兜底1:读取本机网卡获取内网IP(替换netifaces,使用psutil)
57
+ # 3. 兜底1:读取本机网卡获取内网IP(无公网依赖)
92
58
  try:
93
59
  local_ip = self._get_local_internal_ip()
94
60
  if local_ip:
95
61
  return self._hash_to_machine_id(local_ip)
96
- except Exception:
62
+ else:
63
+ # logger.warning("读取网卡信息成功,但未找到非回环内网IP")
64
+ pass
65
+ except Exception as e:
66
+ # logger.warning(f"读取本机网卡IP失败: {e},尝试使用主机名")
97
67
  pass
98
68
 
99
69
  # 4. 兜底2:获取容器主机名(K8s中默认等于Pod名称,保证唯一)
100
70
  hostname = socket.gethostname()
101
71
  if hostname:
72
+ # logger.info(
73
+ # f"未读取到POD_NAME/POD_IP/内网IP,使用主机名: {hostname}生成machine_id")
102
74
  return self._hash_to_machine_id(hostname)
103
75
 
104
- # 5. 最终兜底:增加熵值(进程ID+毫秒时间戳+随机数),大幅降低重复概率
105
- fallback_text = f"{os.getpid()}_{int(time.time()*1000)}_{random.randint(0, 100000)}"
106
- return self._hash_to_machine_id(fallback_text)
76
+ # 5. 最终兜底:生成随机数(仅极端情况使用,日志告警)
77
+ random_id = random.randint(0, self.MAX_MACHINE_ID)
78
+ # logger.warning(f"所有方式均失败,使用随机数生成machine_id: {random_id}(可能重复!)")
79
+ return random_id
107
80
 
108
81
  def _get_local_internal_ip(self) -> Optional[str]:
109
82
  """
110
- 使用psutil读取本机网卡信息,获取非回环的内网IP(跨平台兼容,过滤lo/lo0等回环网卡)
83
+ 读取本机网卡信息,获取非回环的内网IP(无公网依赖)
111
84
  :return: 内网IP字符串,失败返回None
112
85
  """
113
86
  try:
114
- # 遍历所有网卡接口
115
- net_if_addrs = psutil.net_if_addrs()
116
- for interface_name, addrs in net_if_addrs.items():
117
- # 过滤回环/虚拟网卡(兼容lo、lo0、lo1、Loopback、virtual等)
118
- if (interface_name.lower().startswith("lo")
119
- or interface_name.lower() in ["loopback", "virtual"]):
120
- continue
121
- # 遍历该网卡的所有地址,优先返回第一个非回环IPv4
122
- for addr in addrs:
123
- if addr.family == psutil.AF_INET:
124
- ip = addr.address
87
+ # 遍历所有网卡
88
+ for interface in netifaces.interfaces():
89
+ # 获取网卡的IP地址信息
90
+ addrs = netifaces.ifaddresses(interface)
91
+ # 只取IPv4地址
92
+ if netifaces.AF_INET in addrs:
93
+ for addr in addrs[netifaces.AF_INET]:
94
+ ip = addr.get('addr')
95
+ # 过滤回环地址(127.0.0.1)和docker虚拟地址(172.17.0.0/16可选过滤)
125
96
  if ip and not ip.startswith('127.'):
97
+ # 可选:过滤docker0的默认地址段(根据实际内网段调整)
98
+ # if not ip.startswith('172.17.'):
126
99
  return ip
127
100
  return None
128
- except Exception:
129
- # psutil调用失败,降级到纯内置方法
101
+ except ImportError:
102
+ # 若未安装netifaces,降级为socket方式(仅尝试本地解析,无公网连接)
103
+ # logger.warning("未安装netifaces库,尝试降级方式获取IP")
130
104
  return self._get_local_ip_fallback()
131
105
 
132
106
  def _get_local_ip_fallback(self) -> Optional[str]:
133
107
  """
134
- 增强版降级方案:纯Python内置方法,多维度获取内网IP(无第三方依赖)
108
+ 降级方案:不连接公网,仅通过本地socket获取IP(兼容无netifaces的场景)
135
109
  """
136
- # 方案1:socket绑定内网地址(避免访问公网)
137
110
  try:
111
+ # 创建socket但不连接任何地址,仅绑定到本地
138
112
  s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
139
- s.connect(("192.168.0.1", 80))
113
+ # 绑定到0.0.0.0:0(仅用于获取本机IP,不发送数据)
114
+ s.bind(('', 0))
140
115
  local_ip = s.getsockname()[0]
141
116
  s.close()
117
+ # 过滤回环地址
142
118
  if not local_ip.startswith('127.'):
143
119
  return local_ip
120
+ return None
144
121
  except Exception:
145
- pass
146
-
147
- # 方案2:遍历所有本地IP(通过hostname解析)
148
- try:
149
- hostname = socket.gethostname()
150
- ip_list = socket.gethostbyname_ex(hostname)[2]
151
- for ip in ip_list:
152
- if not ip.startswith('127.'):
153
- return ip
154
- except Exception:
155
- pass
156
-
157
- return None
122
+ return None
158
123
 
159
124
  def _hash_to_machine_id(self, text: str) -> int:
160
125
  """将字符串哈希后取模,得到0~1023的machine_id(保证分布均匀)"""
@@ -163,60 +128,42 @@ class Snowflake:
163
128
  return hash_int % self.MAX_MACHINE_ID
164
129
 
165
130
  def _get_current_timestamp(self) -> int:
166
- """获取当前毫秒级时间戳"""
167
131
  return int(time.time() * 1000)
168
132
 
169
133
  def _wait_next_millisecond(self, current_timestamp: int) -> int:
170
- """等待直到下一个毫秒,避免序列耗尽"""
171
134
  while current_timestamp <= self.last_timestamp:
172
135
  current_timestamp = self._get_current_timestamp()
173
136
  return current_timestamp
174
137
 
175
138
  def generate_id(self) -> int:
176
- """生成雪花ID(生产级优化:优化锁粒度,容忍轻微时钟回拨)"""
177
- current_timestamp = self._get_current_timestamp()
139
+ with self.lock:
140
+ current_timestamp = self._get_current_timestamp()
178
141
 
179
- # 1. 处理时钟回拨:容忍CLOCK_BACKWARD_THRESHOLD内的微调,超过则抛异常
180
- time_diff = self.last_timestamp - current_timestamp
181
- if time_diff > 0:
182
- if time_diff > self.CLOCK_BACKWARD_THRESHOLD:
142
+ if current_timestamp < self.last_timestamp:
183
143
  raise RuntimeError(
184
- f"时钟回拨检测:当前时间戳({current_timestamp}) < 上一次时间戳({self.last_timestamp})"
185
- f"差值{time_diff}ms(阈值{self.CLOCK_BACKWARD_THRESHOLD}ms)"
144
+ f"时钟回拨检测:当前时间戳({current_timestamp}) < 上一次时间戳({self.last_timestamp})"
186
145
  )
187
- # 轻微回拨:等待时钟追上
188
- current_timestamp = self._wait_next_millisecond(current_timestamp)
189
146
 
190
- # 2. 优化锁粒度:仅在同一毫秒内递增序列时加锁
191
- if current_timestamp != self.last_timestamp:
192
- with self.lock:
193
- self.last_timestamp = current_timestamp
194
- self.sequence = 0
195
- else:
196
- with self.lock:
147
+ if current_timestamp == self.last_timestamp:
197
148
  self.sequence = (self.sequence + 1) & self.MAX_SEQUENCE
198
149
  if self.sequence == 0:
199
150
  current_timestamp = self._wait_next_millisecond(
200
151
  current_timestamp)
201
- self.last_timestamp = current_timestamp
152
+ else:
153
+ self.sequence = 0
202
154
 
203
- # 3. 计算最终雪花ID
204
- snowflake_id = (
205
- ((current_timestamp - self.START_TIMESTAMP) << self.TIMESTAMP_SHIFT)
206
- | (self.machine_id << self.MACHINE_ID_SHIFT)
207
- | self.sequence
208
- )
155
+ self.last_timestamp = current_timestamp
209
156
 
210
- # 最终校验:确保不超过Java Long最大值
211
- if snowflake_id > self._MAX_JAVA_LONG:
212
- raise RuntimeError(
213
- f"生成的雪花ID({snowflake_id})超过Java Long最大值({self._MAX_JAVA_LONG})")
157
+ snowflake_id = (
158
+ ((current_timestamp - self.START_TIMESTAMP) << self.TIMESTAMP_SHIFT)
159
+ | (self.machine_id << self.MACHINE_ID_SHIFT)
160
+ | self.sequence
161
+ )
214
162
 
215
- return snowflake_id
163
+ return snowflake_id
216
164
 
217
165
  @staticmethod
218
166
  def parse_id(snowflake_id: int) -> dict:
219
- """解析雪花ID,返回生成时间、机器ID、序列等信息"""
220
167
  from datetime import datetime
221
168
  sequence = snowflake_id & Snowflake.MAX_SEQUENCE
222
169
  machine_id = (snowflake_id >>
@@ -230,71 +177,45 @@ class Snowflake:
230
177
  "snowflake_id": snowflake_id,
231
178
  "generate_time": generate_time,
232
179
  "machine_id": machine_id,
233
- "sequence": sequence,
234
- "is_java_long_safe": snowflake_id <= Snowflake._MAX_JAVA_LONG
180
+ "sequence": sequence
235
181
  }
236
182
 
237
183
  @classmethod
238
184
  def next_id(cls) -> str:
239
185
  """
240
- 生成雪花ID(线程安全单例模式,避免重复创建实例,锁内完成所有初始化)
186
+ 生成雪花ID(单例模式,避免重复创建实例)
241
187
  :return: 雪花ID字符串
242
188
  """
189
+ # 单例模式创建实例
243
190
  if cls._instance is None:
244
191
  with cls._instance_lock:
245
192
  if cls._instance is None:
246
- # 锁内初始化,避免多线程重复计算machine_id
247
193
  cls._instance = cls()
194
+ # 生成ID并转为字符串返回
248
195
  return str(cls._instance.generate_id())
249
196
 
250
- @ClassProperty
251
- def id(cls) -> str:
252
- """
253
- 直接通过 `Snowflake.id` 属性生成雪花ID(兼容Python 3.11+)
254
- :return: 雪花ID字符串
255
- """
256
- return cls.next_id()
257
-
258
197
 
259
198
  if __name__ == "__main__":
260
- print("=== 生产级雪花算法ID生成测试 ===")
261
- # 1. 基础生成测试
262
- id1 = Snowflake.id
263
- id2 = Snowflake.id
264
- id3 = Snowflake.id
265
- print(f"生成ID1: {id1}")
266
- print(f"生成ID2: {id2}")
267
- print(f"生成ID3: {id3}")
268
- print(f"ID是否唯一: {len({id1, id2, id3}) == 3}")
269
-
270
- # 2. 解析ID信息
271
- print("\n=== 雪花ID解析 ===")
272
- parse_info = Snowflake.parse_id(int(id3))
273
- for key, value in parse_info.items():
274
- print(f"{key}: {value}")
275
-
276
- # 3. 批量唯一性验证(10000个ID)
277
- print("\n=== 批量唯一性验证(10000个)===")
278
- id_set = set()
279
- duplicate_count = 0
280
- for i in range(10000):
281
- snow_id = Snowflake.id
282
- if snow_id in id_set:
283
- duplicate_count += 1
284
- id_set.add(snow_id)
285
- print(f"总生成数量: 10000")
286
- print(f"唯一ID数量: {len(id_set)}")
287
- print(f"重复ID数量: {duplicate_count}")
288
- print(f"机器ID: {Snowflake._instance.machine_id}")
289
-
290
- # 4. 高并发测试
291
- import concurrent.futures
292
- print("\n=== 高并发测试(100线程)===")
293
- id_set_concurrent = set()
294
- with concurrent.futures.ThreadPoolExecutor(max_workers=100) as executor:
295
- futures = [executor.submit(lambda: Snowflake.id) for _ in range(10000)]
296
- for future in concurrent.futures.as_completed(futures):
297
- id_set_concurrent.add(future.result())
298
- print(f"高并发生成唯一ID数量: {len(id_set_concurrent)}")
299
-
300
- print("\n=== 生产级雪花算法验证通过 ===")
199
+ # 生成1000个ID并验证
200
+ id_set = set() # 用于检测重复ID
201
+ _MAX_JAVA_LONG = 9223372036854775807
202
+
203
+ for i in range(1000):
204
+ id_str = Snowflake.next_id()
205
+ id_num = int(id_str)
206
+
207
+ # 验证ID不超过Java long最大值
208
+ assert id_num <= _MAX_JAVA_LONG, f"ID超过Java long最大值: {id_num}"
209
+
210
+ # 验证ID不重复
211
+ assert id_str not in id_set, f"重复生成ID: {id_str}"
212
+ id_set.add(id_str)
213
+
214
+ # 每100个ID打印一次解析结果
215
+ if i % 100 == 0:
216
+ parse_result = Snowflake.parse_id(id_num)
217
+ print(f"生成ID: {id_str}")
218
+ print(f"解析结果: {parse_result}")
219
+ print("-" * 50)
220
+
221
+ print(f"成功生成{len(id_set)}个唯一雪花ID,验证通过!")
@@ -1,25 +1,25 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sycommon-python-lib
3
- Version: 0.1.55
3
+ Version: 0.1.55a0
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.8
8
8
  Requires-Dist: aiohttp>=3.13.2
9
- Requires-Dist: aiomysql>=0.3.2
10
9
  Requires-Dist: decorator>=5.2.1
11
- Requires-Dist: fastapi>=0.127.0
12
- Requires-Dist: kafka-python>=2.3.0
10
+ Requires-Dist: fastapi>=0.121.2
11
+ Requires-Dist: kafka-python>=2.2.16
13
12
  Requires-Dist: loguru>=0.7.3
14
13
  Requires-Dist: mysql-connector-python>=9.5.0
15
14
  Requires-Dist: nacos-sdk-python<3.0,>=2.0.9
16
- Requires-Dist: psutil>=7.1.3
17
- Requires-Dist: pydantic>=2.12.5
15
+ Requires-Dist: netifaces>=0.11.0
16
+ Requires-Dist: pydantic>=2.12.4
18
17
  Requires-Dist: python-dotenv>=1.2.1
19
18
  Requires-Dist: pyyaml>=6.0.3
20
- Requires-Dist: sqlalchemy[asyncio]>=2.0.45
21
- Requires-Dist: starlette>=0.50.0
22
- Requires-Dist: uvicorn>=0.40.0
19
+ Requires-Dist: sqlalchemy>=2.0.44
20
+ Requires-Dist: starlette>=0.49.3
21
+ Requires-Dist: uuid>=1.30
22
+ Requires-Dist: uvicorn>=0.38.0
23
23
 
24
24
  # sycommon-python-lib
25
25
 
@@ -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=pioA4E2RrV6nyAY8EuETUt4mKzCYoxD1rTMYCcppqjE,11581
3
+ sycommon/services.py,sha256=66YUddNJsbx8axuxUZ6ERr95yphlhLOUbBUJ_tgNseI,11851
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
@@ -8,8 +8,6 @@ sycommon/config/LLMConfig.py,sha256=yU-aIqePIeF6msfRVEtGq7SXZVDfHyTi6JduKjhMO_4,
8
8
  sycommon/config/MQConfig.py,sha256=_RDcmIdyWKjmgM5ZnriOoI-DpaxgXs7CD0awdAD6z88,252
9
9
  sycommon/config/RerankerConfig.py,sha256=dohekaY_eTynmMimIuKHBYGXXQO6rJjSkm94OPLuMik,322
10
10
  sycommon/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
- sycommon/database/async_base_db_service.py,sha256=w6ONUiTtF4-bXRnkBt9QpL9BAy0XUDbQG7F9Hf2rfjw,1337
12
- sycommon/database/async_database_service.py,sha256=4Ag5PH6DFEcJOXR8MRF9V_Jho5uCoU9Ibo3PqulDsXw,3916
13
11
  sycommon/database/base_db_service.py,sha256=J5ELHMNeGfzA6zVcASPSPZ0XNKrRY3_gdGmVkZw3Mto,946
14
12
  sycommon/database/database_service.py,sha256=mun5vgM7nkuH6_UyHLHqQ2Qk_5gRgMxJu4_obIKLT6o,3253
15
13
  sycommon/health/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -17,13 +15,11 @@ sycommon/health/health_check.py,sha256=EhfbhspRpQiKJaxdtE-PzpKQO_ucaFKtQxIm16F5M
17
15
  sycommon/health/metrics.py,sha256=fHqO73JuhoZkNPR-xIlxieXiTCvttq-kG-tvxag1s1s,268
18
16
  sycommon/health/ping.py,sha256=FTlnIKk5y1mPfS1ZGOeT5IM_2udF5aqVLubEtuBp18M,250
19
17
  sycommon/logging/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
- sycommon/logging/async_sql_logger.py,sha256=_OY36XkUm__U3NhMgiecy-qd-nptZ_0gpE3J8lGAr58,2619
21
- sycommon/logging/kafka_log.py,sha256=sVw-dFZKEgCosjSUqgTj7YrpK-ggXhleZFwMUVhl-K0,21416
22
- sycommon/logging/logger_levels.py,sha256=_-uQ_T1N8NkNgcAmLrMmJ83nHTDw5ZNvXFPvdk89XGY,1144
18
+ sycommon/logging/kafka_log.py,sha256=Ctjpch9clULhRcSKFVlAjXDmEZ63KVHqch4xzXAQZdQ,21174
23
19
  sycommon/logging/logger_wrapper.py,sha256=TiHsrIIHiQMzXgXK12-0KIpU9GhwQJOoHslakzmq2zc,357
24
20
  sycommon/logging/sql_logger.py,sha256=aEU3OGnI_51Tjyuuf4FpUi9KPTceFRuKAOyQbPzGhzM,2021
25
21
  sycommon/middleware/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
- sycommon/middleware/context.py,sha256=sc1UjN55dYww2tT9KdFMJV8mgpGro67SnETzbVzty-s,155
22
+ sycommon/middleware/context.py,sha256=_5ghpv4u_yAvjkgM-XDx8OnO-YI1XtntHrXsHJHZkwo,88
27
23
  sycommon/middleware/cors.py,sha256=0B5d_ovD56wcH9TfktRs88Q09R9f8Xx5h5ALWYvE8Iw,600
28
24
  sycommon/middleware/docs.py,sha256=bVdDBIHXGVBv562MQLSroa1DgHoObxR9gFzv71PIejg,1187
29
25
  sycommon/middleware/exception.py,sha256=Bk8IchNND1wg6tUX9hf4xWeEJhvA-E_zE9ysBpRZrqE,3010
@@ -31,7 +27,7 @@ sycommon/middleware/middleware.py,sha256=SzZ4wufSNdwC4Ppw99TE7a6AVGkrZRc55NHSrA3
31
27
  sycommon/middleware/monitor_memory.py,sha256=pYRK-wRuDd6enSg9Pf8tQxPdYQS6S0AyjyXeKFRLKEs,628
32
28
  sycommon/middleware/mq.py,sha256=4wBqiT5wJGcrfjk2GSr0_U3TStBxoNpHTzcRxVlMEHE,183
33
29
  sycommon/middleware/timeout.py,sha256=fImlAPLm4Oa8N9goXtT_0os1GZPCi9F92OgXU81DgDU,656
34
- sycommon/middleware/traceid.py,sha256=0WYLV5PR6sGeqhLdviHYW94UhUC7NJua2g5HWf2Zhbc,13447
30
+ sycommon/middleware/traceid.py,sha256=ugqPgHdUydj7m481rM_RH-yrIK9hAdkLemdPSSOnQvw,6821
35
31
  sycommon/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
32
  sycommon/models/base_http.py,sha256=EICAAibx3xhjBsLqm35Mi3DCqxp0FME4rD_3iQVjT_E,3051
37
33
  sycommon/models/log.py,sha256=rZpj6VkDRxK3B6H7XSeWdYZshU8F0Sks8bq1p6pPlDw,500
@@ -48,17 +44,16 @@ sycommon/sse/sse.py,sha256=__CfWEcYxOxQ-HpLor4LTZ5hLWqw9-2X7CngqbVHsfw,10128
48
44
  sycommon/synacos/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
49
45
  sycommon/synacos/example.py,sha256=61XL03tU8WTNOo3FUduf93F2fAwah1S0lbH1ufhRhRk,5739
50
46
  sycommon/synacos/example2.py,sha256=adUaru3Hy482KrOA17DfaC4nwvLj8etIDS_KrWLWmCU,4811
51
- sycommon/synacos/feign.py,sha256=frB3D5LeFDtT3pJLFOwFzEOrNAJKeQNGk-BzUg9T3WM,8295
52
- sycommon/synacos/feign_client.py,sha256=ExO7Pd5B3eFKDjXqBRc260K1jkI49IYguLwJJaD2R-o,16166
53
- sycommon/synacos/nacos_service.py,sha256=jeg7Bd-SYb0nB1vpjN4sJdw_0nXuI8GjebdM7zu_Z8c,35404
47
+ sycommon/synacos/feign.py,sha256=U7RJFV8qPgWyFDpeIgmYpYnpXPrWj01kkigDf1k8sBY,8023
48
+ sycommon/synacos/feign_client.py,sha256=qEJNQFX5irDnD6VwN79im42h9FKzoELPmdEAXzgwPT0,15435
49
+ sycommon/synacos/nacos_service.py,sha256=tyh_JOjjoCGiKCr1xfU7MAmu7dDQCZmTzmYsSqNjiQY,35465
54
50
  sycommon/synacos/param.py,sha256=KcfSkxnXOa0TGmCjY8hdzU9pzUsA8-4PeyBKWI2-568,1765
55
51
  sycommon/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
56
52
  sycommon/tools/docs.py,sha256=OPj2ETheuWjXLyaXtaZPbwmJKfJaYXV5s4XMVAUNrms,1607
57
- sycommon/tools/merge_headers.py,sha256=HV_i52Q-9se3SP8qh7ZGYl8bP7Fxtal4CGVkyMwEdM8,4373
58
- sycommon/tools/snowflake.py,sha256=lVEe5mNCOgz5OqGQpf5_nXaGnRJlI2STX2s-ppTtanA,11947
53
+ sycommon/tools/snowflake.py,sha256=S3KWKFUKhgZ9QnzLvvaGTt2MavF9RvjDQqeUM99u6Kk,8589
59
54
  sycommon/tools/timing.py,sha256=OiiE7P07lRoMzX9kzb8sZU9cDb0zNnqIlY5pWqHcnkY,2064
60
- sycommon_python_lib-0.1.55.dist-info/METADATA,sha256=P0jS9Alm326fol0Jzj_u7HcpJtsugkCpMyCv9z0OLzc,7084
61
- sycommon_python_lib-0.1.55.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
62
- sycommon_python_lib-0.1.55.dist-info/entry_points.txt,sha256=q_h2nbvhhmdnsOUZEIwpuoDjaNfBF9XqppDEmQn9d_A,46
63
- sycommon_python_lib-0.1.55.dist-info/top_level.txt,sha256=98CJ-cyM2WIKxLz-Pf0AitWLhJyrfXvyY8slwjTXNuc,17
64
- sycommon_python_lib-0.1.55.dist-info/RECORD,,
55
+ sycommon_python_lib-0.1.55a0.dist-info/METADATA,sha256=hlbD-d9IAS0lnH_ZdWhyA3c0ewXabuEFjcxeFetwBJw,7077
56
+ sycommon_python_lib-0.1.55a0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
57
+ sycommon_python_lib-0.1.55a0.dist-info/entry_points.txt,sha256=q_h2nbvhhmdnsOUZEIwpuoDjaNfBF9XqppDEmQn9d_A,46
58
+ sycommon_python_lib-0.1.55a0.dist-info/top_level.txt,sha256=98CJ-cyM2WIKxLz-Pf0AitWLhJyrfXvyY8slwjTXNuc,17
59
+ sycommon_python_lib-0.1.55a0.dist-info/RECORD,,
@@ -1,36 +0,0 @@
1
- from contextlib import asynccontextmanager
2
- from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker
3
- from sycommon.config.Config import SingletonMeta
4
- from sycommon.database.async_database_service import AsyncDatabaseService
5
- from sycommon.logging.kafka_log import SYLogger
6
-
7
-
8
- class AsyncBaseDBService(metaclass=SingletonMeta):
9
- """数据库操作基础服务类,封装异步会话管理功能"""
10
-
11
- def __init__(self):
12
- # 获取异步引擎 (假设 DatabaseService.engine() 返回的是 AsyncEngine)
13
- self.engine = AsyncDatabaseService.engine()
14
-
15
- # 创建异步 Session 工厂
16
- # class_=AsyncSession 是必须的,用于指定生成的是异步会话
17
- self.Session = async_sessionmaker(
18
- bind=self.engine,
19
- class_=AsyncSession,
20
- expire_on_commit=False
21
- )
22
-
23
- @asynccontextmanager
24
- async def session(self):
25
- """
26
- 异步数据库会话上下文管理器
27
- 自动处理会话的创建、提交、回滚和关闭
28
- """
29
- async with self.Session() as session:
30
- try:
31
- yield session
32
- await session.commit()
33
- except Exception as e:
34
- await session.rollback()
35
- SYLogger.error(f"Database operation failed: {str(e)}")
36
- raise