forked from bot/app
📝 添加shared_memory文档
This commit is contained in:
parent
85a13251a5
commit
b356524a9e
@ -5,13 +5,15 @@ order: 4
|
|||||||
category: 开发
|
category: 开发
|
||||||
---
|
---
|
||||||
|
|
||||||
## 简介
|
## **通道通信**
|
||||||
|
|
||||||
|
### 简介
|
||||||
|
|
||||||
轻雪运行在主进程 MainProcess 里,其他插件框架进程是伴随的子进程,因此无法通过内存共享和直接对象传递的方式进行通信,轻雪提供了一个通道`Channel`用于跨进程通信,你可以通过`Channel`发送消息给其他进程,也可以监听其他进程的消息。
|
轻雪运行在主进程 MainProcess 里,其他插件框架进程是伴随的子进程,因此无法通过内存共享和直接对象传递的方式进行通信,轻雪提供了一个通道`Channel`用于跨进程通信,你可以通过`Channel`发送消息给其他进程,也可以监听其他进程的消息。
|
||||||
|
|
||||||
例如子进程接收到用户信息需要重启机器人,这时可以通过通道对主进程发送消息,主进程接收到消息后重启对应子进程。
|
例如子进程接收到用户信息需要重启机器人,这时可以通过通道对主进程发送消息,主进程接收到消息后重启对应子进程。
|
||||||
|
|
||||||
## 快速开始
|
### 快速开始
|
||||||
|
|
||||||
通道是全双工的,有两种接收模式,但一个通道只能使用一种,即被动模式和主动模式,被动模式由`chan.on_receive()`装饰回调函数实现,主动模式需调用`chan.receive()`实现
|
通道是全双工的,有两种接收模式,但一个通道只能使用一种,即被动模式和主动模式,被动模式由`chan.on_receive()`装饰回调函数实现,主动模式需调用`chan.receive()`实现
|
||||||
|
|
||||||
@ -78,3 +80,23 @@ async def on_startup():
|
|||||||
..-..-.. ..:..:.. [ℹ️信息] Active receive: I am liteyuki main process active
|
..-..-.. ..:..:.. [ℹ️信息] Active receive: I am liteyuki main process active
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## **共享内存通信**
|
||||||
|
|
||||||
|
### 简介
|
||||||
|
|
||||||
|
- 相比于普通进程通信,内存共享使得代码编写更加简洁,轻雪框架提供了一个内存共享通信的接口,你可以通过`storage`模块实现内存共享通信
|
||||||
|
- 内存共享是线程安全的,你可以在多个线程中读写共享内存,线程锁会自动保护共享内存的读写操作
|
||||||
|
|
||||||
|
### 快速开始
|
||||||
|
|
||||||
|
- 在任意进程中均可使用
|
||||||
|
|
||||||
|
```python
|
||||||
|
from liteyuki.comm.storage import shared_memory
|
||||||
|
|
||||||
|
shared_memory.set("key", "value") # 设置共享内存
|
||||||
|
value = shared_memory.get("key") # 获取共享内存
|
||||||
|
```
|
||||||
|
|
||||||
|
- 源代码:[liteyuki/comm/storage.py](https://github.com/LiteyukiStudio/LiteyukiBot/blob/main/liteyuki/comm/storage.py)
|
24
docs/dev/dev_shared_memory.md
Normal file
24
docs/dev/dev_shared_memory.md
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
---
|
||||||
|
title: 内存共享通信
|
||||||
|
icon: exchange-alt
|
||||||
|
order: 5
|
||||||
|
category: 开发
|
||||||
|
---
|
||||||
|
|
||||||
|
# 简介
|
||||||
|
|
||||||
|
相比于普通进程通信,内存共享使得代码编写更加简洁,轻雪框架提供了一个内存共享通信的接口,你可以通过`shared_memory`模块实现内存共享通信
|
||||||
|
内存共享是线程安全的,你可以在多个线程中读写共享内存,线程锁会自动保护共享内存的读写操作
|
||||||
|
|
||||||
|
## 快速开始
|
||||||
|
|
||||||
|
- 在任意进程中均可使用
|
||||||
|
|
||||||
|
```python
|
||||||
|
from liteyuki.comm.storage import shared_memory
|
||||||
|
|
||||||
|
shared_memory.set("key", "value") # 设置共享内存
|
||||||
|
value = shared_memory.get("key") # 获取共享内存
|
||||||
|
```
|
||||||
|
|
||||||
|
- 源代码:[liteyuki/comm/storage.py](https://github.com/LiteyukiStudio/LiteyukiBot/blob/main/liteyuki/comm/storage.py)
|
@ -1,13 +1,10 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""
|
"""
|
||||||
Copyright (C) 2020-2024 LiteyukiStudio. All Rights Reserved
|
|
||||||
|
|
||||||
@Time : 2024/7/26 下午10:36
|
|
||||||
@Author : snowykami
|
|
||||||
@Email : snowykami@outlook.com
|
|
||||||
@File : __init__.py
|
|
||||||
@Software: PyCharm
|
|
||||||
该模块用于轻雪主进程和Nonebot子进程之间的通信
|
该模块用于轻雪主进程和Nonebot子进程之间的通信
|
||||||
|
依赖关系
|
||||||
|
event -> _
|
||||||
|
storage -> channel
|
||||||
|
rpc -> channel, storage
|
||||||
"""
|
"""
|
||||||
from liteyuki.comm.channel import (
|
from liteyuki.comm.channel import (
|
||||||
Channel,
|
Channel,
|
||||||
|
@ -136,8 +136,9 @@ class KeyValueStoreNoLock:
|
|||||||
if IS_MAIN_PROCESS:
|
if IS_MAIN_PROCESS:
|
||||||
return self._store.get(key, default)
|
return self._store.get(key, default)
|
||||||
else:
|
else:
|
||||||
self.passive_chan.send(("get", key, default))
|
temp_chan = Channel("temp_chan")
|
||||||
return self.active_chan.receive()
|
self.passive_chan.send(("get", key, default, temp_chan))
|
||||||
|
return temp_chan.receive()
|
||||||
|
|
||||||
def delete(self, key: str, ignore_key_error: bool = True) -> None:
|
def delete(self, key: str, ignore_key_error: bool = True) -> None:
|
||||||
"""
|
"""
|
||||||
@ -169,8 +170,9 @@ class KeyValueStoreNoLock:
|
|||||||
if IS_MAIN_PROCESS:
|
if IS_MAIN_PROCESS:
|
||||||
return self._store
|
return self._store
|
||||||
else:
|
else:
|
||||||
self.passive_chan.send(("get_all",))
|
temp_chan = Channel("temp_chan")
|
||||||
return self.active_chan.receive()
|
self.passive_chan.send(("get_all", temp_chan))
|
||||||
|
return temp_chan.receive()
|
||||||
|
|
||||||
|
|
||||||
class GlobalKeyValueStore:
|
class GlobalKeyValueStore:
|
||||||
@ -197,28 +199,29 @@ if IS_MAIN_PROCESS:
|
|||||||
|
|
||||||
|
|
||||||
@shared_memory.passive_chan.on_receive(lambda d: d[0] == "get")
|
@shared_memory.passive_chan.on_receive(lambda d: d[0] == "get")
|
||||||
def on_get(d):
|
def on_get(data: tuple[str, str, any, Channel]):
|
||||||
shared_memory.active_chan.send(shared_memory.get(d[1], d[2]))
|
data[3].send(shared_memory.get(data[1], data[2]))
|
||||||
|
|
||||||
|
|
||||||
@shared_memory.passive_chan.on_receive(lambda d: d[0] == "set")
|
@shared_memory.passive_chan.on_receive(lambda d: d[0] == "set")
|
||||||
def on_set(d):
|
def on_set(data: tuple[str, str, any]):
|
||||||
shared_memory.set(d[1], d[2])
|
shared_memory.set(data[1], data[2])
|
||||||
|
|
||||||
|
|
||||||
@shared_memory.passive_chan.on_receive(lambda d: d[0] == "delete")
|
@shared_memory.passive_chan.on_receive(lambda d: d[0] == "delete")
|
||||||
def on_delete(d):
|
def on_delete(data: tuple[str, str]):
|
||||||
shared_memory.delete(d[1])
|
shared_memory.delete(data[1])
|
||||||
|
|
||||||
|
|
||||||
@shared_memory.passive_chan.on_receive(lambda d: d[0] == "get_all")
|
@shared_memory.passive_chan.on_receive(lambda d: d[0] == "get_all")
|
||||||
def on_get_all(d):
|
def on_get_all(data: tuple[str, Channel]):
|
||||||
if d[0] == "get_all":
|
if data[0] == "get_all":
|
||||||
shared_memory.active_chan.send(shared_memory.get_all())
|
data[1].send(shared_memory.get_all())
|
||||||
else:
|
else:
|
||||||
|
# 子进程在入口函数中对shared_memory进行初始化
|
||||||
shared_memory = None
|
shared_memory = None
|
||||||
|
|
||||||
_ref_count = 0 # 引用计数
|
_ref_count = 0 # import 引用计数, 防止获取空指针
|
||||||
if not IS_MAIN_PROCESS:
|
if not IS_MAIN_PROCESS:
|
||||||
if (shared_memory is None) and _ref_count > 1:
|
if (shared_memory is None) and _ref_count > 1:
|
||||||
raise RuntimeError("Shared memory not initialized.")
|
raise RuntimeError("Shared memory not initialized.")
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import threading
|
import threading
|
||||||
|
|
||||||
from nonebot import logger
|
|
||||||
from liteyuki.comm.channel import active_channel
|
from liteyuki.comm.channel import active_channel
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user