design.md 3.5 Phase 2(PEN D reason 专用名为可选项,复用 PREASON_NO_RESOURCE
已带资源名,跳过):
① esd stale 标记与 WARN
- esd_source_t 增 stale_limit/last_ok_time;esd_source_is_stale(): 从未有值
不算 stale、时钟超前钳到 0、严格大于(interval==limit 不抖动)、
ESD_STALE_LIMIT_DEFAULT 150;fail-open 保持旧值不变
- 采集失败首轮一次性 WARN,过限后每轮升级为 STALE WARN(带 age/limit/kept
值),恢复即静默
- status 文件 esd_status_write(): daemon/pid/started_at/generated_at/
pushes ok/fail/sources[{name,last_value,last_ok_time,stale}],tmp+rename
原子写;写失败仅状态转换时告警一次,绝不拖垮 poll 循环
② `xce resources` 展示 last-updated
- controller worker.c: EXTERNAL 共享值被接受时盖 last_report——同时盖
live resmgr 对象与 myconf 配置树副本(apiserver 定义 store 只由 join 时
config push 供给,串行的是配置树,缺后者 CLI 永远显示 never)
- scheduler core_events.c: RESOURCES_PUSH 原地更新拷贝 last_report(纯
metadata,resobj.c 比较本就排除)
- apiserver: model 带 last_report + 默认列(SelectFields 只投影默认列,
缺失即 API/CLI 全链不可见);convert cResourceToModel 透传
- apiserver handler.go: OnResourceLocationUpdated 对 host=="" 且定义带
EXTERNAL(0x10) 的推送刷新 store 内 LastReport——config push 快照之外
的活刷新;host 来源值与非 EXTERNAL 资源绝不触碰
- xcecli: LAST_UPDATED 列(-l verbose 表格/详情/JSON 三态),0 显示 "-"
④ `xceadmin extres status`
- 本机读 status 文件(远程读取留待 PR-2,需新 wire 协议;LAST_UPDATED
已覆盖远程新鲜度语义)——--status-file 显式路径或
/var/run/xce/esd-status.json 默认,无 controller 连接依赖
- XceExtresStatusError 本地文件类错误;click default=None 装饰期冻结坑
用调用期解析
TDD:test_extres_resvals +2(配置树盖戳/非 EXTERNAL 不盖戳)、test_esd_core
+4(stale 判式/状态文件)、apiserver models +2(默认列/json tag)、backend
integration +2(EXTERNAL 刷新/非 EXTERNAL 不刷新)、xceadmin +11(渲染/
本地读/容错)。全绿:controller 1360、scheduler 100、apiserver(cgo+nocgo)、
esd 11、xceadmin 385。
t1 E2E 实证:esd join 即推送→API last_report=join 时刻→CLI LAST_UPDATED
"Oct 27 13:52";破坏采集器后 60s 过限转 per-round STALE WARN + status
stale:true + fail-open 保值,恢复脚本即回 false;liccheck 作业提交→运行→
DONE,五 daemon 全健康。
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
||
|---|---|---|
| .claude | ||
| .kiro | ||
| .wolf | ||
| docs | ||
| issues | ||
| raft | ||
| scripts | ||
| src | ||
| .clang-format | ||
| .gitignore | ||
| .mcp.json | ||
| .opencode.json | ||
| admin-plane-gaps.md | ||
| CLAUDE.md | ||
| DEPS.md | ||
| gaps.md | ||
| Makefile | ||
| README.md | ||
1. commit 规则
- 每个人 fork 自己的 branch, 从自己的 branch 做 PR,review 完再 commit
2. code format
2.1. C
推荐使用 clang-format,公共配置放在源码里面 xce/.clang-format
(理论上直接使用源码里面 xce/.clang-format 文件格式不会变)
2.1.1. vscode 可以在配置中加上如下内容
"C_Cpp.clang_format_style": "WebKit",
"C_Cpp.clang_format_fallbackStyle": "WebKit",
2.1.2. vim & emacs
clang-format -style="{BasedOnStyle: webkit}" -i XX.c
2.2. golang
使用默认 gofmt
3. build environment and build (example of ubuntu)
构建不依赖 nix:直接在 Ubuntu(24.04 基线)上用 apt 系统库 + meson wrap subprojects 构建。完整的依赖清单(工具链 + 11 个 apt 库的版本下限 + 6 个随仓库 提交的 wrap subproject 源码闭包)见 DEPS.md。
3.1 build environment
一次性安装构建工具链与系统库(与 CI 的 scripts/ci-ubuntu.sh 完全一致):
sudo apt-get update
# 工具链
sudo apt-get install -y build-essential pkg-config ninja-build \
python3 python3-pip python3-venv git
# meson >= 1.5(Ubuntu 24.04 自带 1.3,pip 原地升级)
sudo apt-get install -y meson
meson --version | grep -qE '^1\.[5-9]' || pip3 install --break-system-packages 'meson>=1.5'
# cap'n proto(schema 编译器 + pycapnp 链接的 C++ 运行时)
sudo apt-get install -y capnproto libcapnp-dev
# C 库(DEPS.md "apt 可直接安装" 表)
sudo apt-get install -y libuv1-dev libssl-dev libedit-dev libsqlite3-dev \
libhwloc-dev libcgroup-dev libtirpc-dev libcyaml-dev libyaml-dev \
zlib1g-dev libsystemd-dev
# Go(apiserver/xcecli 依赖已全部 vendored,构建离线)
sudo apt-get install -y golang-go
其余依赖(c-capnproto、librtti、struct2json、tinylog、unity、packcc)不在系统里装——
它们以 meson wrap subproject 的形式提交在 src/subprojects/(源码闭包),meson
配置时自动拉取/构建,无需手动处理。
3.2 checkout source code
git clone ssh://forgejo@gitea.shenrs.eu/rshen/xce.git
cd xce
(参考第 1 节,fork 自己的 branch 再提交 PR)
3.3 build (for daily develop)
日常开发直接用 src/tools/xce-build.sh(若在 Claude Code 中开发,对应 /xce-build
skill)。脚本开头有依赖预检(缺工具/缺库时报出具体的 apt 包名,而不是构建中途的
晦涩报错),然后执行 meson setup / meson compile,asan profile 下还会自动跑测试:
cd xce/src
tools/xce-build.sh # 全部组件 + 全部测试 (asan profile, 输出到 xce.build/)
tools/xce-build.sh controller # 只构建/测试 controller (lib + controller + xce_test)
tools/xce-build.sh worker # 只构建 worker
tools/xce-build.sh scheduler # 只构建/测试 scheduler
tools/xce-build.sh apiserver # 只构建/测试 apiserver + xcecli (Go)
支持三种 profile(tools/xce-build.sh [component] [profile]):
asan(默认):debug + AddressSanitizer,输出目录xce.build/,会运行测试debug:-O0 -g3无 sanitizer,输出目录build.dbg/,仅编译,用于 gdb 调试release:-O3无 sanitizer,输出目录build.release/,仅编译,用于 soak/性能测试
注意:单组件构建默认会先 rm -rf 对应的 build 目录再重新配置,若同一目录下已有其他
组件的产物会被清掉;需要在同一目录下累积多个组件时加 --incremental(增量
reconfigure,不清空目录;capnp 生成目标存在未修的依赖边缺失,增量构建若结果可疑
请退回全量重建,见脚本内 bug-1565 注释)。
也可以手动执行底层的 meson 命令(xce-build.sh 是对下面步骤的封装):
cd xce/src
# generate build configuration (debug + address sanitizer)
meson setup xce.build --buildtype=debug -Db_sanitize=address
# build
meson compile -C xce.build
# The generated files will be in xce.build/
3.3.1 更新 Go 依赖(vendor 维护)
Go 模块(frontend/apiserver、frontend/xcecli、
autoscaler/providers/baidu/src/bcctool)的依赖以 vendor/ 目录的形式提交进仓库,
构建时 tools/go_build 使用 GOFLAGS=-mod=vendor、GOPROXY=off 完全离线编译。
修改了某个模块的 go.mod / go.sum(新增、升级、删除依赖)后,重新生成对应模块
的 vendor/ 并提交(普通环境即可,无需任何特殊 shell):
cd xce/src/frontend/apiserver # 其他两个模块同理
go mod tidy
go mod vendor
git add go.mod go.sum vendor
3.4 package (tarball 分发)
产品分发形态是自包含 tarball(daemon + CLI + $ORIGIN RPATH 的 bundled 非基础库
- systemd unit 样例 + configs/schema + ttyd),打包规则见
src/tools/xce-package.sh头部注释与 DEPS.md "运行期 bundle 规则":
cd xce/src
tools/xce-build.sh all release # 先出 release 构建(build.release/)
tools/xce-package.sh # 默认从 build.release/ 打到 dist/
# 或显式指定: tools/xce-package.sh build.release dist
产物:dist/xce-<version>-<commit>-<fingerprint>-linux-x86_64.tar.gz。目标机上:
tar -xzf xce-*.tar.gz && cd xce-*/
sudo ./install.sh # 默认装到 /opt/xce,PREFIX=... 可覆盖
3.5 CI
scripts/ci-ubuntu.sh 在裸 Ubuntu 24.04 容器里跑完整流水线(装依赖 → asan 全量
构建+测试 → release 构建 → 打 tarball smoke),与客户环境同构:
bash scripts/ci-ubuntu.sh
4. misc
4.1. Windows remap ctrl and alt key
create a reg file, e.g. remapkey.reg
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout]
"Scancode Map"=hex:00,00,00,00,00,00,00,00,05,00,00,00,38,00,1d,00,1d,00,38,00,38,e0,1d,e0,1d,e0,38,e0,00,00,00,00
then double click remapkey.reg to import it. Restart OS.