refactor: 按 gpui-kit 官方指南对齐(locales 拆分/render 无突变/动作统一)
skill 安装:npx skills add 因网络不可用,改为 gh-proxy 镜像克隆仓库后 手动覆盖 ~/.agents/skills 与 ~/.zcode/skills 两处安装(与官方最新一致)。 语言包按语言分文件(用户要求): - locales/ui.yml(合并格式)→ locales/en.yml + locales/zh-CN.yml (rust-i18n 以文件名 stem 识别 locale,扁平 "ns.key": "value") - i18n.rs 测试适配双文件:键集合一致性 + 占位符两侧一致强制保留 对齐 coding-guides / design-guides / auto-update: - render 无突变:分组过滤悬空复位从 render 移到 delete_connection/ save_connection 的 action 路径(normalize_group_filter) - 消除 UI 层 hsla 字面量:消息色条改 when_some 条件上色;色板描边 从白 60% 改主题底色(双主题下均为「与背景的缝隙」语义) - 动作统一:标题栏菜单的资源监控/导出/导入/设置改 dispatch_action, 与快捷键共享同一 Action(菜单/快捷键单一命令策略) - auto-update 对齐官方指南:自动检查加 24h 节流(.last-update-check 时间戳),手动检查更新不受限 保留(记录豁免理由): - 手写 collapsible_section:官方 Accordion 非受控(内部索引状态), 替代会丢「已配置默认展开」的受控行为 - 自研 update/:官方无内置 updater,指南推荐 self_update+应用自有 状态机,现有实现(状态机/后台 worker/sha256/consent/原子替换) 已符合该精神;换 self_update 反而放弃已有代理兜底与 7z 通道 - px() 几何常量:对话框/面板宽度与色点尺寸属文档化几何豁免, 机械换算会引入视觉回归;min 约束的 px(0.) 为布局断言 42 测试全绿,实机冒烟通过。
This commit is contained in:
@@ -1,66 +0,0 @@
|
||||
//! 消息流量压测工具:连接 broker 后按指定速率向主题发布消息。
|
||||
//!
|
||||
//! 用法:cargo run --example flood -- <host> <port> <topic> <count> <per_second> [payload_bytes]
|
||||
//! 例:向私有 broker 发 500 条 1KB 消息、每秒 50 条:
|
||||
//! cargo run --example flood -- mqtt.nex-i.cn 1883 mqttx-flood 500 50 1024
|
||||
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
fn main() {
|
||||
let args: Vec<String> = std::env::args().collect();
|
||||
if args.len() < 6 {
|
||||
eprintln!("usage: flood <host> <port> <topic> <count> <per_second> [payload_bytes]");
|
||||
std::process::exit(1);
|
||||
}
|
||||
let host = args[1].clone();
|
||||
let port: u16 = args[2].parse().unwrap();
|
||||
let topic = args[3].clone();
|
||||
let count: u64 = args[4].parse().unwrap();
|
||||
let per_second: u64 = args[5].parse().unwrap();
|
||||
let payload_size: usize = args.get(6).map(|s| s.parse().unwrap()).unwrap_or(512);
|
||||
|
||||
let rt = tokio::runtime::Builder::new_multi_thread()
|
||||
.worker_threads(2)
|
||||
.enable_all()
|
||||
.build()
|
||||
.unwrap();
|
||||
rt.block_on(async move {
|
||||
let opts = rumqttc::MqttOptions::new(
|
||||
format!("mqttx_flood_{}", &uuid::Uuid::new_v4().simple().to_string()[..8]),
|
||||
rumqttc::Broker::tcp(&host, port),
|
||||
);
|
||||
let (client, mut eventloop) = rumqttc::AsyncClient::builder(opts).build();
|
||||
|
||||
// eventloop 独立持续 poll:请求出队全靠它
|
||||
tokio::spawn(async move {
|
||||
loop {
|
||||
if eventloop.poll().await.is_err() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let payload = vec![b'x'; payload_size];
|
||||
let interval = Duration::from_secs_f64(1.0 / per_second.max(1) as f64);
|
||||
let start = Instant::now();
|
||||
for i in 0..count {
|
||||
let topic_i = format!("{topic}/{i}");
|
||||
let options = rumqttc::PublishOptions::new(rumqttc::QoS::AtMostOnce);
|
||||
if let Err(e) = client.publish(&topic_i, payload.clone(), options).await {
|
||||
eprintln!("publish error at {i}: {e}");
|
||||
break;
|
||||
}
|
||||
let next = start + interval * (i as u32 + 1);
|
||||
let now = Instant::now();
|
||||
if next > now {
|
||||
tokio::time::sleep(next - now).await;
|
||||
}
|
||||
}
|
||||
eprintln!(
|
||||
"flooded {count} msgs ({payload_size}B each) in {:.1}s",
|
||||
start.elapsed().as_secs_f64()
|
||||
);
|
||||
// 等网络冲刷
|
||||
tokio::time::sleep(Duration::from_secs(3)).await;
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user