ErisPulse 1.1.14.dev1__py3-none-any.whl → 1.1.16__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.
- ErisPulse/__init__.py +189 -164
- ErisPulse/__main__.py +74 -2
- ErisPulse/adapter.py +211 -32
- ErisPulse/db.py +408 -36
- ErisPulse/logger.py +101 -57
- ErisPulse/mods.py +235 -19
- ErisPulse/raiserr.py +65 -38
- {erispulse-1.1.14.dev1.dist-info → erispulse-1.1.16.dist-info}/METADATA +78 -45
- erispulse-1.1.16.dist-info/RECORD +13 -0
- {erispulse-1.1.14.dev1.dist-info → erispulse-1.1.16.dist-info}/entry_points.txt +2 -2
- erispulse-1.1.14.dev1.dist-info/RECORD +0 -13
- {erispulse-1.1.14.dev1.dist-info → erispulse-1.1.16.dist-info}/WHEEL +0 -0
- {erispulse-1.1.14.dev1.dist-info → erispulse-1.1.16.dist-info}/licenses/LICENSE +0 -0
ErisPulse/adapter.py
CHANGED
|
@@ -1,46 +1,225 @@
|
|
|
1
1
|
"""
|
|
2
2
|
# 适配器系统
|
|
3
3
|
|
|
4
|
-
提供平台适配器基类、消息发送DSL
|
|
5
|
-
|
|
6
|
-
## 主要功能
|
|
7
|
-
- BaseAdapter: 适配器基类
|
|
8
|
-
- SendDSL: 链式消息发送接口
|
|
9
|
-
- AdapterManager: 适配器管理
|
|
10
|
-
- 适配器注册和生命周期管理
|
|
4
|
+
提供平台适配器基类、消息发送DSL和适配器管理功能。支持多平台消息处理、事件驱动和生命周期管理。
|
|
11
5
|
|
|
12
6
|
## API 文档
|
|
13
|
-
### 适配器基类 (BaseAdapter):
|
|
14
|
-
- call_api(): 必须实现的API调用方法
|
|
15
|
-
- start(): 启动适配器
|
|
16
|
-
- shutdown(): 关闭适配器
|
|
17
|
-
- on(): 事件监听装饰器
|
|
18
|
-
- emit(): 触发事件
|
|
19
|
-
|
|
20
|
-
### 消息发送DSL (SendDSL):
|
|
21
|
-
- To(): 设置消息目标
|
|
22
|
-
- Text(): 发送文本消息
|
|
23
|
-
- 可扩展其他消息类型
|
|
24
|
-
|
|
25
|
-
### 适配器管理 (AdapterManager):
|
|
26
|
-
- register(): 注册适配器
|
|
27
|
-
- startup(): 启动适配器
|
|
28
|
-
- shutdown(): 关闭所有适配器
|
|
29
|
-
- get(): 获取适配器实例
|
|
30
|
-
|
|
31
|
-
### 示例用法:
|
|
32
7
|
|
|
8
|
+
### 适配器基类 (BaseAdapter)
|
|
9
|
+
适配器基类提供了与外部平台交互的标准接口。
|
|
10
|
+
|
|
11
|
+
#### call_api(endpoint: str, **params) -> Any
|
|
12
|
+
调用平台API的抽象方法。
|
|
13
|
+
- 参数:
|
|
14
|
+
- endpoint: API端点
|
|
15
|
+
- **params: API参数
|
|
16
|
+
- 返回:
|
|
17
|
+
- Any: API调用结果
|
|
18
|
+
- 说明:
|
|
19
|
+
- 必须由子类实现
|
|
20
|
+
- 处理与平台的实际通信
|
|
21
|
+
- 示例:
|
|
22
|
+
```python
|
|
23
|
+
class MyPlatformAdapter(BaseAdapter):
|
|
24
|
+
async def call_api(self, endpoint: str, **params):
|
|
25
|
+
if endpoint == "/send":
|
|
26
|
+
return await self._send_message(params)
|
|
27
|
+
elif endpoint == "/upload":
|
|
28
|
+
return await self._upload_file(params)
|
|
29
|
+
raise NotImplementedError(f"未实现的端点: {endpoint}")
|
|
33
30
|
```
|
|
34
|
-
from ErisPulse import sdk
|
|
35
31
|
|
|
36
|
-
|
|
37
|
-
|
|
32
|
+
#### start() -> None
|
|
33
|
+
启动适配器的抽象方法。
|
|
34
|
+
- 参数: 无
|
|
35
|
+
- 返回:
|
|
36
|
+
- None
|
|
37
|
+
- 说明:
|
|
38
|
+
- 必须由子类实现
|
|
39
|
+
- 处理适配器的初始化和启动逻辑
|
|
40
|
+
- 示例:
|
|
41
|
+
```python
|
|
42
|
+
class MyPlatformAdapter(BaseAdapter):
|
|
43
|
+
async def start(self):
|
|
44
|
+
self.client = await self._create_client()
|
|
45
|
+
self.ws = await self.client.create_websocket()
|
|
46
|
+
self._start_heartbeat()
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
#### shutdown() -> None
|
|
50
|
+
关闭适配器的抽象方法。
|
|
51
|
+
- 参数: 无
|
|
52
|
+
- 返回:
|
|
53
|
+
- None
|
|
54
|
+
- 说明:
|
|
55
|
+
- 必须由子类实现
|
|
56
|
+
- 处理资源清理和关闭逻辑
|
|
57
|
+
- 示例:
|
|
58
|
+
```python
|
|
59
|
+
class MyPlatformAdapter(BaseAdapter):
|
|
60
|
+
async def shutdown(self):
|
|
61
|
+
if self.ws:
|
|
62
|
+
await self.ws.close()
|
|
63
|
+
if self.client:
|
|
64
|
+
await self.client.close()
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
#### on(event_type: str = "*") -> Callable
|
|
68
|
+
事件监听装饰器。
|
|
69
|
+
- 参数:
|
|
70
|
+
- event_type: 事件类型,默认"*"表示所有事件
|
|
71
|
+
- 返回:
|
|
72
|
+
- Callable: 装饰器函数
|
|
73
|
+
- 示例:
|
|
74
|
+
```python
|
|
75
|
+
adapter = MyPlatformAdapter()
|
|
76
|
+
|
|
77
|
+
@adapter.on("message")
|
|
78
|
+
async def handle_message(data):
|
|
79
|
+
print(f"收到消息: {data}")
|
|
80
|
+
|
|
81
|
+
@adapter.on("error")
|
|
82
|
+
async def handle_error(error):
|
|
83
|
+
print(f"发生错误: {error}")
|
|
84
|
+
|
|
85
|
+
# 处理所有事件
|
|
86
|
+
@adapter.on()
|
|
87
|
+
async def handle_all(event):
|
|
88
|
+
print(f"事件: {event}")
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
#### emit(event_type: str, data: Any) -> None
|
|
92
|
+
触发事件。
|
|
93
|
+
- 参数:
|
|
94
|
+
- event_type: 事件类型
|
|
95
|
+
- data: 事件数据
|
|
96
|
+
- 返回:
|
|
97
|
+
- None
|
|
98
|
+
- 示例:
|
|
99
|
+
```python
|
|
100
|
+
class MyPlatformAdapter(BaseAdapter):
|
|
101
|
+
async def _handle_websocket_message(self, message):
|
|
102
|
+
# 处理消息并触发相应事件
|
|
103
|
+
if message.type == "chat":
|
|
104
|
+
await self.emit("message", {
|
|
105
|
+
"type": "chat",
|
|
106
|
+
"content": message.content,
|
|
107
|
+
"sender": message.sender
|
|
108
|
+
})
|
|
109
|
+
```
|
|
38
110
|
|
|
39
|
-
|
|
40
|
-
|
|
111
|
+
#### middleware(func: Callable) -> Callable
|
|
112
|
+
添加中间件处理器。
|
|
113
|
+
- 参数:
|
|
114
|
+
- func: 中间件函数
|
|
115
|
+
- 返回:
|
|
116
|
+
- Callable: 中间件函数
|
|
117
|
+
- 示例:
|
|
118
|
+
```python
|
|
119
|
+
adapter = MyPlatformAdapter()
|
|
120
|
+
|
|
121
|
+
@adapter.middleware
|
|
122
|
+
async def log_middleware(data):
|
|
123
|
+
print(f"处理数据: {data}")
|
|
124
|
+
return data
|
|
125
|
+
|
|
126
|
+
@adapter.middleware
|
|
127
|
+
async def filter_middleware(data):
|
|
128
|
+
if "spam" in data.get("content", ""):
|
|
129
|
+
return None
|
|
130
|
+
return data
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### 消息发送DSL (SendDSL)
|
|
134
|
+
提供链式调用风格的消息发送接口。
|
|
135
|
+
|
|
136
|
+
#### To(target_type: str = None, target_id: str = None) -> 'SendDSL'
|
|
137
|
+
设置消息目标。
|
|
138
|
+
- 参数:
|
|
139
|
+
- target_type: 目标类型(可选)
|
|
140
|
+
- target_id: 目标ID
|
|
141
|
+
- 返回:
|
|
142
|
+
- SendDSL: 发送器实例
|
|
143
|
+
- 示例:
|
|
144
|
+
```python
|
|
145
|
+
# 发送到用户
|
|
146
|
+
sdk.adapter.Platform.Send.To("user", "123").Text("Hello")
|
|
147
|
+
|
|
148
|
+
# 发送到群组
|
|
149
|
+
sdk.adapter.Platform.Send.To("group", "456").Text("Hello Group")
|
|
150
|
+
|
|
151
|
+
# 简化形式(只有ID)
|
|
152
|
+
sdk.adapter.Platform.Send.To("123").Text("Hello")
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
#### Text(text: str) -> Task
|
|
156
|
+
发送文本消息。
|
|
157
|
+
- 参数:
|
|
158
|
+
- text: 文本内容
|
|
159
|
+
- 返回:
|
|
160
|
+
- Task: 异步任务
|
|
161
|
+
- 示例:
|
|
162
|
+
```python
|
|
163
|
+
# 发送简单文本
|
|
164
|
+
await sdk.adapter.Platform.Send.To("user", "123").Text("Hello")
|
|
165
|
+
|
|
166
|
+
# 发送格式化文本
|
|
167
|
+
name = "Alice"
|
|
168
|
+
await sdk.adapter.Platform.Send.To("123").Text(f"Hello {name}")
|
|
169
|
+
```
|
|
41
170
|
|
|
42
|
-
|
|
171
|
+
### 适配器管理 (AdapterManager)
|
|
172
|
+
管理多个平台适配器的注册、启动和关闭。
|
|
173
|
+
|
|
174
|
+
#### register(platform: str, adapter_class: Type[BaseAdapter]) -> bool
|
|
175
|
+
注册新的适配器类。
|
|
176
|
+
- 参数:
|
|
177
|
+
- platform: 平台名称
|
|
178
|
+
- adapter_class: 适配器类
|
|
179
|
+
- 返回:
|
|
180
|
+
- bool: 注册是否成功
|
|
181
|
+
- 示例:
|
|
182
|
+
```python
|
|
183
|
+
# 注册适配器
|
|
184
|
+
sdk.adapter.register("MyPlatform", MyPlatformAdapter)
|
|
185
|
+
|
|
186
|
+
# 注册多个适配器
|
|
187
|
+
adapters = {
|
|
188
|
+
"Platform1": Platform1Adapter,
|
|
189
|
+
"Platform2": Platform2Adapter
|
|
190
|
+
}
|
|
191
|
+
for name, adapter in adapters.items():
|
|
192
|
+
sdk.adapter.register(name, adapter)
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
#### startup(platforms: List[str] = None) -> None
|
|
196
|
+
启动指定的适配器。
|
|
197
|
+
- 参数:
|
|
198
|
+
- platforms: 要启动的平台列表,None表示所有平台
|
|
199
|
+
- 返回:
|
|
200
|
+
- None
|
|
201
|
+
- 示例:
|
|
202
|
+
```python
|
|
203
|
+
# 启动所有适配器
|
|
43
204
|
await sdk.adapter.startup()
|
|
205
|
+
|
|
206
|
+
# 启动指定适配器
|
|
207
|
+
await sdk.adapter.startup(["Platform1", "Platform2"])
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
#### shutdown() -> None
|
|
211
|
+
关闭所有适配器。
|
|
212
|
+
- 参数: 无
|
|
213
|
+
- 返回:
|
|
214
|
+
- None
|
|
215
|
+
- 示例:
|
|
216
|
+
```python
|
|
217
|
+
# 关闭所有适配器
|
|
218
|
+
await sdk.adapter.shutdown()
|
|
219
|
+
|
|
220
|
+
# 在程序退出时关闭
|
|
221
|
+
import atexit
|
|
222
|
+
atexit.register(lambda: asyncio.run(sdk.adapter.shutdown()))
|
|
44
223
|
```
|
|
45
224
|
|
|
46
225
|
"""
|
ErisPulse/db.py
CHANGED
|
@@ -1,55 +1,427 @@
|
|
|
1
1
|
"""
|
|
2
2
|
# 环境配置
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
提供键值存储、事务支持、快照和恢复功能,用于管理框架配置数据。基于SQLite实现持久化存储,支持复杂数据类型和原子操作。
|
|
5
5
|
|
|
6
6
|
## API 文档
|
|
7
|
-
### 基本操作:
|
|
8
|
-
- get(key, default=None) -> any: 获取配置项
|
|
9
|
-
- set(key, value) -> bool: 设置配置项
|
|
10
|
-
- delete(key) -> bool: 删除配置项
|
|
11
|
-
- get_all_keys() -> list[str]: 获取所有键名
|
|
12
7
|
|
|
13
|
-
###
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
8
|
+
### 基本操作
|
|
9
|
+
#### get(key: str, default: Any = None) -> Any
|
|
10
|
+
获取配置项的值。
|
|
11
|
+
- 参数:
|
|
12
|
+
- key: 配置项键名
|
|
13
|
+
- default: 如果键不存在时返回的默认值
|
|
14
|
+
- 返回:
|
|
15
|
+
- Any: 配置项的值,如果是JSON格式则自动解析为Python对象
|
|
16
|
+
- 示例:
|
|
17
|
+
```python
|
|
18
|
+
# 获取基本配置
|
|
19
|
+
timeout = sdk.env.get("network.timeout", 30)
|
|
20
|
+
|
|
21
|
+
# 获取结构化数据
|
|
22
|
+
user_settings = sdk.env.get("user.settings", {})
|
|
23
|
+
if "theme" in user_settings:
|
|
24
|
+
apply_theme(user_settings["theme"])
|
|
25
|
+
|
|
26
|
+
# 条件获取
|
|
27
|
+
debug_mode = sdk.env.get("app.debug", False)
|
|
28
|
+
if debug_mode:
|
|
29
|
+
enable_debug_features()
|
|
30
|
+
```
|
|
17
31
|
|
|
18
|
-
|
|
19
|
-
|
|
32
|
+
#### set(key: str, value: Any) -> bool
|
|
33
|
+
设置配置项的值。
|
|
34
|
+
- 参数:
|
|
35
|
+
- key: 配置项键名
|
|
36
|
+
- value: 配置项的值,复杂类型会自动序列化为JSON
|
|
37
|
+
- 返回:
|
|
38
|
+
- bool: 操作是否成功
|
|
39
|
+
- 示例:
|
|
40
|
+
```python
|
|
41
|
+
# 设置基本配置
|
|
42
|
+
sdk.env.set("app.name", "MyApplication")
|
|
43
|
+
|
|
44
|
+
# 设置结构化数据
|
|
45
|
+
sdk.env.set("server.config", {
|
|
46
|
+
"host": "localhost",
|
|
47
|
+
"port": 8080,
|
|
48
|
+
"workers": 4
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
# 更新现有配置
|
|
52
|
+
current_settings = sdk.env.get("user.settings", {})
|
|
53
|
+
current_settings["last_login"] = datetime.now().isoformat()
|
|
54
|
+
sdk.env.set("user.settings", current_settings)
|
|
55
|
+
```
|
|
20
56
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
57
|
+
#### delete(key: str) -> bool
|
|
58
|
+
删除配置项。
|
|
59
|
+
- 参数:
|
|
60
|
+
- key: 要删除的配置项键名
|
|
61
|
+
- 返回:
|
|
62
|
+
- bool: 操作是否成功
|
|
63
|
+
- 示例:
|
|
64
|
+
```python
|
|
65
|
+
# 删除临时配置
|
|
66
|
+
sdk.env.delete("temp.session")
|
|
67
|
+
|
|
68
|
+
# 条件删除
|
|
69
|
+
if not is_feature_enabled():
|
|
70
|
+
sdk.env.delete("feature.config")
|
|
71
|
+
|
|
72
|
+
# 清理旧配置
|
|
73
|
+
for key in sdk.env.get_all_keys():
|
|
74
|
+
if key.startswith("deprecated."):
|
|
75
|
+
sdk.env.delete(key)
|
|
76
|
+
```
|
|
27
77
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
78
|
+
#### get_all_keys() -> list[str]
|
|
79
|
+
获取所有配置项的键名。
|
|
80
|
+
- 参数: 无
|
|
81
|
+
- 返回:
|
|
82
|
+
- list[str]: 所有配置项的键名列表
|
|
83
|
+
- 示例:
|
|
84
|
+
```python
|
|
85
|
+
# 列出所有配置
|
|
86
|
+
all_keys = sdk.env.get_all_keys()
|
|
87
|
+
print(f"当前有 {len(all_keys)} 个配置项")
|
|
88
|
+
|
|
89
|
+
# 按前缀过滤
|
|
90
|
+
user_keys = [k for k in sdk.env.get_all_keys() if k.startswith("user.")]
|
|
91
|
+
print(f"用户相关配置: {user_keys}")
|
|
92
|
+
|
|
93
|
+
# 导出配置摘要
|
|
94
|
+
config_summary = {}
|
|
95
|
+
for key in sdk.env.get_all_keys():
|
|
96
|
+
parts = key.split(".")
|
|
97
|
+
if len(parts) > 1:
|
|
98
|
+
category = parts[0]
|
|
99
|
+
if category not in config_summary:
|
|
100
|
+
config_summary[category] = 0
|
|
101
|
+
config_summary[category] += 1
|
|
102
|
+
print("配置分类统计:", config_summary)
|
|
103
|
+
```
|
|
31
104
|
|
|
32
|
-
###
|
|
105
|
+
### 批量操作
|
|
106
|
+
#### get_multi(keys: list) -> dict
|
|
107
|
+
批量获取多个配置项的值。
|
|
108
|
+
- 参数:
|
|
109
|
+
- keys: 要获取的配置项键名列表
|
|
110
|
+
- 返回:
|
|
111
|
+
- dict: 键值对字典,只包含存在的键
|
|
112
|
+
- 示例:
|
|
113
|
+
```python
|
|
114
|
+
# 批量获取配置
|
|
115
|
+
settings = sdk.env.get_multi([
|
|
116
|
+
"app.name",
|
|
117
|
+
"app.version",
|
|
118
|
+
"app.debug"
|
|
119
|
+
])
|
|
120
|
+
print(f"应用: {settings.get('app.name')} v{settings.get('app.version')}")
|
|
121
|
+
|
|
122
|
+
# 获取相关配置组
|
|
123
|
+
db_keys = ["database.host", "database.port", "database.user", "database.password"]
|
|
124
|
+
db_config = sdk.env.get_multi(db_keys)
|
|
125
|
+
connection = create_db_connection(**db_config)
|
|
126
|
+
|
|
127
|
+
# 配置存在性检查
|
|
128
|
+
required_keys = ["api.key", "api.endpoint", "api.version"]
|
|
129
|
+
config = sdk.env.get_multi(required_keys)
|
|
130
|
+
missing = [k for k in required_keys if k not in config]
|
|
131
|
+
if missing:
|
|
132
|
+
raise ValueError(f"缺少必要配置: {missing}")
|
|
133
|
+
```
|
|
33
134
|
|
|
135
|
+
#### set_multi(items: dict) -> bool
|
|
136
|
+
批量设置多个配置项的值。
|
|
137
|
+
- 参数:
|
|
138
|
+
- items: 要设置的键值对字典
|
|
139
|
+
- 返回:
|
|
140
|
+
- bool: 操作是否成功
|
|
141
|
+
- 示例:
|
|
142
|
+
```python
|
|
143
|
+
# 批量设置基本配置
|
|
144
|
+
sdk.env.set_multi({
|
|
145
|
+
"app.name": "MyApp",
|
|
146
|
+
"app.version": "1.0.0",
|
|
147
|
+
"app.debug": True
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
# 更新系统设置
|
|
151
|
+
sdk.env.set_multi({
|
|
152
|
+
"system.max_connections": 100,
|
|
153
|
+
"system.timeout": 30,
|
|
154
|
+
"system.retry_count": 3
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
# 从外部配置导入
|
|
158
|
+
import json
|
|
159
|
+
with open("config.json", "r") as f:
|
|
160
|
+
external_config = json.load(f)
|
|
161
|
+
|
|
162
|
+
# 转换为扁平结构
|
|
163
|
+
flat_config = {}
|
|
164
|
+
for section, values in external_config.items():
|
|
165
|
+
for key, value in values.items():
|
|
166
|
+
flat_config[f"{section}.{key}"] = value
|
|
167
|
+
|
|
168
|
+
sdk.env.set_multi(flat_config)
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
#### delete_multi(keys: list) -> bool
|
|
172
|
+
批量删除多个配置项。
|
|
173
|
+
- 参数:
|
|
174
|
+
- keys: 要删除的配置项键名列表
|
|
175
|
+
- 返回:
|
|
176
|
+
- bool: 操作是否成功
|
|
177
|
+
- 示例:
|
|
178
|
+
```python
|
|
179
|
+
# 批量删除临时配置
|
|
180
|
+
temp_keys = [k for k in sdk.env.get_all_keys() if k.startswith("temp.")]
|
|
181
|
+
sdk.env.delete_multi(temp_keys)
|
|
182
|
+
|
|
183
|
+
# 删除特定模块的所有配置
|
|
184
|
+
module_keys = [k for k in sdk.env.get_all_keys() if k.startswith("module_name.")]
|
|
185
|
+
sdk.env.delete_multi(module_keys)
|
|
186
|
+
|
|
187
|
+
# 清理测试数据
|
|
188
|
+
test_keys = ["test.user", "test.data", "test.results"]
|
|
189
|
+
sdk.env.delete_multi(test_keys)
|
|
34
190
|
```
|
|
35
|
-
from ErisPulse import sdk
|
|
36
191
|
|
|
37
|
-
|
|
192
|
+
### 事务管理
|
|
193
|
+
#### transaction() -> contextmanager
|
|
194
|
+
创建事务上下文,确保多个操作的原子性。
|
|
195
|
+
- 参数: 无
|
|
196
|
+
- 返回:
|
|
197
|
+
- contextmanager: 事务上下文管理器
|
|
198
|
+
- 示例:
|
|
199
|
+
```python
|
|
200
|
+
# 基本事务
|
|
201
|
+
with sdk.env.transaction():
|
|
202
|
+
sdk.env.set("user.id", user_id)
|
|
203
|
+
sdk.env.set("user.name", user_name)
|
|
204
|
+
sdk.env.set("user.email", user_email)
|
|
205
|
+
|
|
206
|
+
# 带有条件检查的事务
|
|
207
|
+
def update_user_safely(user_id, new_data):
|
|
208
|
+
with sdk.env.transaction():
|
|
209
|
+
current = sdk.env.get(f"user.{user_id}", None)
|
|
210
|
+
if not current:
|
|
211
|
+
return False
|
|
212
|
+
|
|
213
|
+
for key, value in new_data.items():
|
|
214
|
+
sdk.env.set(f"user.{user_id}.{key}", value)
|
|
215
|
+
|
|
216
|
+
sdk.env.set(f"user.{user_id}.updated_at", time.time())
|
|
217
|
+
return True
|
|
218
|
+
|
|
219
|
+
# 复杂业务逻辑事务
|
|
220
|
+
def transfer_credits(from_user, to_user, amount):
|
|
221
|
+
with sdk.env.transaction():
|
|
222
|
+
# 检查余额
|
|
223
|
+
from_balance = sdk.env.get(f"user.{from_user}.credits", 0)
|
|
224
|
+
if from_balance < amount:
|
|
225
|
+
raise ValueError("余额不足")
|
|
226
|
+
|
|
227
|
+
# 更新余额
|
|
228
|
+
sdk.env.set(f"user.{from_user}.credits", from_balance - amount)
|
|
229
|
+
|
|
230
|
+
to_balance = sdk.env.get(f"user.{to_user}.credits", 0)
|
|
231
|
+
sdk.env.set(f"user.{to_user}.credits", to_balance + amount)
|
|
232
|
+
|
|
233
|
+
# 记录交易
|
|
234
|
+
transaction_id = str(uuid.uuid4())
|
|
235
|
+
sdk.env.set(f"transaction.{transaction_id}", {
|
|
236
|
+
"from": from_user,
|
|
237
|
+
"to": to_user,
|
|
238
|
+
"amount": amount,
|
|
239
|
+
"timestamp": time.time()
|
|
240
|
+
})
|
|
241
|
+
```
|
|
38
242
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
243
|
+
### 快照管理
|
|
244
|
+
#### snapshot(name: str = None) -> str
|
|
245
|
+
创建数据库快照。
|
|
246
|
+
- 参数:
|
|
247
|
+
- name: 快照名称,默认使用当前时间戳
|
|
248
|
+
- 返回:
|
|
249
|
+
- str: 快照文件路径
|
|
250
|
+
- 示例:
|
|
251
|
+
```python
|
|
252
|
+
# 创建命名快照
|
|
253
|
+
sdk.env.snapshot("before_migration")
|
|
254
|
+
|
|
255
|
+
# 创建定期备份
|
|
256
|
+
def create_daily_backup():
|
|
257
|
+
date_str = datetime.now().strftime("%Y%m%d")
|
|
258
|
+
return sdk.env.snapshot(f"daily_{date_str}")
|
|
259
|
+
|
|
260
|
+
# 在重要操作前创建快照
|
|
261
|
+
def safe_operation():
|
|
262
|
+
snapshot_path = sdk.env.snapshot("pre_operation")
|
|
263
|
+
try:
|
|
264
|
+
perform_risky_operation()
|
|
265
|
+
except Exception as e:
|
|
266
|
+
sdk.logger.error(f"操作失败: {e}")
|
|
267
|
+
sdk.env.restore(snapshot_path)
|
|
268
|
+
return False
|
|
269
|
+
return True
|
|
270
|
+
```
|
|
44
271
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
272
|
+
#### restore(snapshot_name: str) -> bool
|
|
273
|
+
从快照恢复数据库。
|
|
274
|
+
- 参数:
|
|
275
|
+
- snapshot_name: 快照名称或路径
|
|
276
|
+
- 返回:
|
|
277
|
+
- bool: 恢复是否成功
|
|
278
|
+
- 示例:
|
|
279
|
+
```python
|
|
280
|
+
# 恢复到指定快照
|
|
281
|
+
success = sdk.env.restore("before_migration")
|
|
282
|
+
if success:
|
|
283
|
+
print("成功恢复到之前的状态")
|
|
284
|
+
else:
|
|
285
|
+
print("恢复失败")
|
|
286
|
+
|
|
287
|
+
# 回滚到最近的每日备份
|
|
288
|
+
def rollback_to_last_daily():
|
|
289
|
+
snapshots = sdk.env.list_snapshots()
|
|
290
|
+
daily_snapshots = [s for s in snapshots if s[0].startswith("daily_")]
|
|
291
|
+
if daily_snapshots:
|
|
292
|
+
latest = daily_snapshots[0] # 列表已按时间排序
|
|
293
|
+
return sdk.env.restore(latest[0])
|
|
294
|
+
return False
|
|
295
|
+
|
|
296
|
+
# 灾难恢复
|
|
297
|
+
def disaster_recovery():
|
|
298
|
+
snapshots = sdk.env.list_snapshots()
|
|
299
|
+
if not snapshots:
|
|
300
|
+
print("没有可用的快照")
|
|
301
|
+
return False
|
|
302
|
+
|
|
303
|
+
print("可用快照:")
|
|
304
|
+
for i, (name, date, size) in enumerate(snapshots):
|
|
305
|
+
print(f"{i+1}. {name} - {date} ({size/1024:.1f} KB)")
|
|
306
|
+
|
|
307
|
+
choice = input("选择要恢复的快照编号: ")
|
|
308
|
+
try:
|
|
309
|
+
index = int(choice) - 1
|
|
310
|
+
if 0 <= index < len(snapshots):
|
|
311
|
+
return sdk.env.restore(snapshots[index][0])
|
|
312
|
+
except ValueError:
|
|
313
|
+
pass
|
|
314
|
+
return False
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
#### list_snapshots() -> list
|
|
318
|
+
列出所有可用的快照。
|
|
319
|
+
- 参数: 无
|
|
320
|
+
- 返回:
|
|
321
|
+
- list: 快照信息列表,每项包含(名称, 创建时间, 大小)
|
|
322
|
+
- 示例:
|
|
323
|
+
```python
|
|
324
|
+
# 列出所有快照
|
|
325
|
+
snapshots = sdk.env.list_snapshots()
|
|
326
|
+
print(f"共有 {len(snapshots)} 个快照")
|
|
327
|
+
|
|
328
|
+
# 显示快照详情
|
|
329
|
+
for name, date, size in snapshots:
|
|
330
|
+
print(f"名称: {name}")
|
|
331
|
+
print(f"创建时间: {date}")
|
|
332
|
+
print(f"大小: {size/1024:.2f} KB")
|
|
333
|
+
print("-" * 30)
|
|
334
|
+
|
|
335
|
+
# 查找特定快照
|
|
336
|
+
def find_snapshot(prefix):
|
|
337
|
+
snapshots = sdk.env.list_snapshots()
|
|
338
|
+
return [s for s in snapshots if s[0].startswith(prefix)]
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
#### delete_snapshot(name: str) -> bool
|
|
342
|
+
删除指定的快照。
|
|
343
|
+
- 参数:
|
|
344
|
+
- name: 要删除的快照名称
|
|
345
|
+
- 返回:
|
|
346
|
+
- bool: 删除是否成功
|
|
347
|
+
- 示例:
|
|
348
|
+
```python
|
|
349
|
+
# 删除指定快照
|
|
350
|
+
sdk.env.delete_snapshot("old_backup")
|
|
351
|
+
|
|
352
|
+
# 清理过期快照
|
|
353
|
+
def cleanup_old_snapshots(days=30):
|
|
354
|
+
snapshots = sdk.env.list_snapshots()
|
|
355
|
+
cutoff = datetime.now() - timedelta(days=days)
|
|
356
|
+
for name, date, _ in snapshots:
|
|
357
|
+
if date < cutoff:
|
|
358
|
+
sdk.env.delete_snapshot(name)
|
|
359
|
+
print(f"已删除过期快照: {name}")
|
|
360
|
+
|
|
361
|
+
# 保留最新的N个快照
|
|
362
|
+
def retain_latest_snapshots(count=5):
|
|
363
|
+
snapshots = sdk.env.list_snapshots()
|
|
364
|
+
if len(snapshots) > count:
|
|
365
|
+
for name, _, _ in snapshots[count:]:
|
|
366
|
+
sdk.env.delete_snapshot(name)
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
## 最佳实践
|
|
370
|
+
|
|
371
|
+
1. 配置组织
|
|
372
|
+
```python
|
|
373
|
+
# 使用层次结构组织配置
|
|
374
|
+
sdk.env.set("app.server.host", "localhost")
|
|
375
|
+
sdk.env.set("app.server.port", 8080)
|
|
376
|
+
sdk.env.set("app.database.url", "postgresql://localhost/mydb")
|
|
377
|
+
|
|
378
|
+
# 使用命名空间避免冲突
|
|
379
|
+
sdk.env.set("module1.config.timeout", 30)
|
|
380
|
+
sdk.env.set("module2.config.timeout", 60)
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
2. 事务使用
|
|
384
|
+
```python
|
|
385
|
+
# 确保数据一致性
|
|
386
|
+
def update_configuration(config_data):
|
|
387
|
+
with sdk.env.transaction():
|
|
388
|
+
# 验证
|
|
389
|
+
for key, value in config_data.items():
|
|
390
|
+
if not validate_config(key, value):
|
|
391
|
+
raise ValueError(f"无效的配置: {key}")
|
|
392
|
+
|
|
393
|
+
# 更新
|
|
394
|
+
for key, value in config_data.items():
|
|
395
|
+
sdk.env.set(key, value)
|
|
396
|
+
|
|
397
|
+
# 记录更新
|
|
398
|
+
sdk.env.set("config.last_updated", time.time())
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
3. 快照管理
|
|
402
|
+
```python
|
|
403
|
+
# 定期创建快照
|
|
404
|
+
def schedule_backups():
|
|
405
|
+
# 每日快照
|
|
406
|
+
if not sdk.env.snapshot(f"daily_{datetime.now().strftime('%Y%m%d')}"):
|
|
407
|
+
sdk.logger.error("每日快照创建失败")
|
|
408
|
+
|
|
409
|
+
# 清理旧快照
|
|
410
|
+
cleanup_old_snapshots(days=30)
|
|
411
|
+
|
|
412
|
+
# 自动备份重要操作
|
|
413
|
+
def safe_bulk_update(updates):
|
|
414
|
+
snapshot_name = f"pre_update_{time.time()}"
|
|
415
|
+
sdk.env.snapshot(snapshot_name)
|
|
49
416
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
417
|
+
try:
|
|
418
|
+
with sdk.env.transaction():
|
|
419
|
+
for key, value in updates.items():
|
|
420
|
+
sdk.env.set(key, value)
|
|
421
|
+
except Exception as e:
|
|
422
|
+
sdk.logger.error(f"批量更新失败: {e}")
|
|
423
|
+
sdk.env.restore(snapshot_name)
|
|
424
|
+
raise
|
|
53
425
|
```
|
|
54
426
|
|
|
55
427
|
"""
|