docs: explain Tessera modules and execution flows in Chinese
This commit is contained in:
@@ -1,3 +1,7 @@
|
||||
//! 本机 HTTP API 入口:路由请求、限制输入大小、观察活动,并将执行工作送入串行 worker。
|
||||
//! HTTP 线程不操作 VM;共享 NamespaceState 只保存最近完整发布文档和资源命令。提交序号用来拒绝已被较新 PUT/DELETE 取代的结果。
|
||||
//! 关闭流程先请求运行时有界清理,再通过完成通知让原生事件循环退出。
|
||||
//!
|
||||
mod guide;
|
||||
mod worker;
|
||||
|
||||
@@ -35,18 +39,21 @@ const MAX_CODE_SIZE: u64 = endor_host::MAX_SOURCE_BYTES as u64;
|
||||
type Notify = Arc<dyn Fn() + Send + Sync>;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
/// 运行时清理的摘要与可选错误,供最终原生退出结果报告。
|
||||
pub struct ShutdownOutcome {
|
||||
pub summary: String,
|
||||
pub error: Option<String>,
|
||||
}
|
||||
type ShutdownCompletion = Arc<(Mutex<Option<ShutdownOutcome>>, Condvar)>;
|
||||
#[derive(Clone)]
|
||||
/// 跨线程的退出控制句柄,使用有界通知和完成条件变量,不携带 VM。
|
||||
pub struct RuntimeControl {
|
||||
sender: SyncSender<()>,
|
||||
requested: Arc<AtomicBool>,
|
||||
completion: ShutdownCompletion,
|
||||
}
|
||||
impl RuntimeControl {
|
||||
/// 只发出一次退出请求,唤醒 worker 执行清理,并通过完成句柄通知原生循环。
|
||||
pub fn request_shutdown(&self) -> bool {
|
||||
if self.requested.swap(true, Ordering::AcqRel) {
|
||||
return true;
|
||||
@@ -58,9 +65,11 @@ impl RuntimeControl {
|
||||
false
|
||||
}
|
||||
}
|
||||
/// 读取退出标志,使窗口事件和新输入尽早停止进入运行时。
|
||||
pub fn is_exiting(&self) -> bool {
|
||||
self.requested.load(Ordering::Acquire)
|
||||
}
|
||||
/// 在明确超时内等待 worker 的清理结果,不能无限阻塞退出。
|
||||
pub fn wait_shutdown(&self, timeout: std::time::Duration) -> Option<ShutdownOutcome> {
|
||||
let (lock, ready) = &*self.completion;
|
||||
let result = lock.lock().ok()?;
|
||||
@@ -70,6 +79,7 @@ impl RuntimeControl {
|
||||
result.clone()
|
||||
}
|
||||
}
|
||||
/// worker 持有的关闭接收端、控制状态和 GUI 完成通知代理。
|
||||
struct Shutdown {
|
||||
receiver: Receiver<()>,
|
||||
control: RuntimeControl,
|
||||
@@ -77,6 +87,7 @@ struct Shutdown {
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
/// 送入执行队列的请求类别,区分完整源码、持久输入、事件与重置。
|
||||
enum RequestKind {
|
||||
Event,
|
||||
Code,
|
||||
@@ -85,6 +96,7 @@ enum RequestKind {
|
||||
ResetRepl,
|
||||
}
|
||||
|
||||
/// 保留原 HTTP 请求与提交身份的执行工作,完成或失败后由 worker 回应。
|
||||
struct BuildRequest {
|
||||
request: ObservedRequest,
|
||||
kind: RequestKind,
|
||||
@@ -93,6 +105,7 @@ struct BuildRequest {
|
||||
submission: u64,
|
||||
}
|
||||
|
||||
/// 建立本模块的执行/服务上下文,并把后续推进交给返回的句柄或驱动。
|
||||
pub fn start(
|
||||
namespace: Arc<RwLock<NamespaceState>>,
|
||||
proxy: EventLoopProxy<AppEvent>,
|
||||
@@ -127,6 +140,7 @@ pub fn start(
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
/// 为本地监听服务建立请求处理线程,并把执行请求转交有界队列。
|
||||
fn start_server(
|
||||
server: Arc<Server>,
|
||||
namespace: Arc<RwLock<NamespaceState>>,
|
||||
@@ -142,6 +156,7 @@ fn start_server(
|
||||
)
|
||||
}
|
||||
|
||||
/// 启动带活动观察的 HTTP 服务,将请求状态变化通知管理界面。
|
||||
fn start_server_observed(
|
||||
server: Arc<Server>,
|
||||
namespace: Arc<RwLock<NamespaceState>>,
|
||||
@@ -283,6 +298,7 @@ fn start_server_observed(
|
||||
}
|
||||
|
||||
// Capture only allowlisted headers: credentials and cookies never enter the inspector.
|
||||
/// HTTP 请求的观察包装,在读取正文和响应时维护 Network 工具记录。
|
||||
struct ObservedRequest {
|
||||
inner: Request,
|
||||
activity: Activity,
|
||||
@@ -290,6 +306,7 @@ struct ObservedRequest {
|
||||
notify: Notify,
|
||||
}
|
||||
impl ObservedRequest {
|
||||
/// 构造本类型并初始化其状态;资源建立和默认字段以函数体为准。
|
||||
fn new(inner: Request, activity: Activity, notify: Notify) -> Self {
|
||||
let headers = inner
|
||||
.headers()
|
||||
@@ -322,10 +339,12 @@ impl ObservedRequest {
|
||||
notify,
|
||||
}
|
||||
}
|
||||
/// 将受限请求正文记录到活动预览,不在观察器中执行源码。
|
||||
fn record_body(&self, body: &str) {
|
||||
self.activity.lock().unwrap().body(self.id, body);
|
||||
(self.notify)();
|
||||
}
|
||||
/// 发送最终 HTTP 响应,并同步结束该条活动记录。
|
||||
fn respond(self, response: Response<std::io::Cursor<Vec<u8>>>) -> std::io::Result<()> {
|
||||
let status = response.status_code();
|
||||
let headers = response.headers().to_vec();
|
||||
@@ -348,16 +367,19 @@ impl ObservedRequest {
|
||||
}
|
||||
impl Deref for ObservedRequest {
|
||||
type Target = Request;
|
||||
/// 将包装类型的只读访问转交给内部当前上下文。
|
||||
fn deref(&self) -> &Request {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
impl DerefMut for ObservedRequest {
|
||||
/// 将包装类型的可变访问转交给内部当前上下文。
|
||||
fn deref_mut(&mut self) -> &mut Request {
|
||||
&mut self.inner
|
||||
}
|
||||
}
|
||||
|
||||
/// 解析 HTTP 方法和路径;只读路由读取发布值,执行路由交给 worker。
|
||||
fn handle(
|
||||
request: Request,
|
||||
namespace: &Arc<RwLock<NamespaceState>>,
|
||||
@@ -410,6 +432,7 @@ fn handle(
|
||||
let _ = request.respond(response);
|
||||
}
|
||||
|
||||
/// 处理源码资源的 GET/DELETE 等请求,返回对应版本头或撤销运行时所有权。
|
||||
fn code_request(
|
||||
method: Method,
|
||||
addressed_namespace: &str,
|
||||
@@ -510,6 +533,7 @@ fn code_request(
|
||||
}
|
||||
}
|
||||
|
||||
/// 读取并检查请求体,分配提交身份,再把工作送进有界执行队列。
|
||||
fn submit(
|
||||
mut request: ObservedRequest,
|
||||
addressed: &str,
|
||||
@@ -576,6 +600,7 @@ fn submit(
|
||||
}
|
||||
}
|
||||
|
||||
/// 生成较旧请求已被新提交取代的响应,拒绝晚到结果覆盖当前文档。
|
||||
fn superseded(submission: u64) -> Response<std::io::Cursor<Vec<u8>>> {
|
||||
json(
|
||||
StatusCode(409),
|
||||
@@ -584,15 +609,18 @@ fn superseded(submission: u64) -> Response<std::io::Cursor<Vec<u8>>> {
|
||||
)
|
||||
}
|
||||
|
||||
/// 从固定路由格式提取命名空间,避免把不匹配的路径当作代码资源。
|
||||
fn namespace_from_route<'a>(path: &'a str, suffix: &str) -> Option<&'a str> {
|
||||
path.strip_prefix("/v1/namespaces/")?
|
||||
.strip_suffix(suffix)
|
||||
.filter(|namespace| !namespace.is_empty() && !namespace.contains('/'))
|
||||
}
|
||||
/// 从固定路由格式提取命名空间,避免把不匹配的路径当作代码资源。
|
||||
fn namespace_from_path(path: &str) -> Option<&str> {
|
||||
namespace_from_route(path, "/code")
|
||||
}
|
||||
|
||||
/// 按源码字节上限读取 UTF-8 请求体,读取失败或超限时返回诊断。
|
||||
fn read_code(request: &mut Request) -> Result<String> {
|
||||
if request
|
||||
.body_length()
|
||||
@@ -612,6 +640,7 @@ fn read_code(request: &mut Request) -> Result<String> {
|
||||
Ok(code)
|
||||
}
|
||||
|
||||
/// 将前端/编译/执行诊断编码为 API 错误响应,保留用户可理解的位置和消息。
|
||||
fn compile_error(error: anyhow::Error) -> Response<std::io::Cursor<Vec<u8>>> {
|
||||
let mut diagnostic =
|
||||
serde_json::json!({ "severity": "error", "message": format!("{error:#}") });
|
||||
@@ -630,6 +659,7 @@ fn compile_error(error: anyhow::Error) -> Response<std::io::Cursor<Vec<u8>>> {
|
||||
)
|
||||
}
|
||||
|
||||
/// 生成统一 JSON 错误响应,使调用方能区分协议错误与成功结果。
|
||||
fn error_response(
|
||||
status: StatusCode,
|
||||
message: impl Into<String>,
|
||||
@@ -637,6 +667,7 @@ fn error_response(
|
||||
json(status, serde_json::json!({ "error": message.into() }))
|
||||
}
|
||||
|
||||
/// 以明确的内容类型和状态码构造响应,并应用本机 API 的公共响应头。
|
||||
fn json(status: StatusCode, value: serde_json::Value) -> Response<std::io::Cursor<Vec<u8>>> {
|
||||
text(
|
||||
status,
|
||||
@@ -645,10 +676,12 @@ fn json(status: StatusCode, value: serde_json::Value) -> Response<std::io::Curso
|
||||
)
|
||||
}
|
||||
|
||||
/// 以明确的内容类型和状态码构造响应,并应用本机 API 的公共响应头。
|
||||
fn markdown(status: StatusCode, value: String) -> Response<std::io::Cursor<Vec<u8>>> {
|
||||
text(status, &value, "text/markdown; charset=utf-8")
|
||||
}
|
||||
|
||||
/// 以明确的内容类型和状态码构造响应,并应用本机 API 的公共响应头。
|
||||
fn text(status: StatusCode, value: &str, content_type: &str) -> Response<std::io::Cursor<Vec<u8>>> {
|
||||
let mut response = Response::from_string(value).with_status_code(status);
|
||||
add_header(&mut response, "Content-Type", content_type);
|
||||
@@ -670,6 +703,7 @@ fn text(status: StatusCode, value: &str, content_type: &str) -> Response<std::io
|
||||
response
|
||||
}
|
||||
|
||||
/// 向响应追加经过 HTTP 库检查的头字段,不直接拼接未验证的原始报文。
|
||||
fn add_header(response: &mut Response<std::io::Cursor<Vec<u8>>>, name: &str, value: &str) {
|
||||
if let Ok(header) = Header::from_bytes(name, value) {
|
||||
response.add_header(header);
|
||||
|
||||
Reference in New Issue
Block a user