@shundoo-ai/dsh-cosmic 1.0.7 → 1.0.8
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.
package/package.json
CHANGED
|
@@ -90,6 +90,8 @@ description: >
|
|
|
90
90
|
> **build + 热部署**:R0 → R1 → R2 → R3 → R4 → R5。
|
|
91
91
|
> 每一步都给「期望」与「失败处置」;**不做即兴发挥**,缺规则就回写手册(见文末自检)。
|
|
92
92
|
|
|
93
|
+
> 🔁 **执行方式**:可以逐步执行,也可以把本手册**物化**成工作区内的临时脚本一次跑完(实测:Windows 会话把它写成 `<cwd>/.dsh/cosmic/scripts/hotdeploy.ps1`,此后"构建+热部署"每次只花 1 次调用)。**若物化,遵守四条**:① 放在 `.dsh/` 下(git 忽略、不入库);② **本手册是唯一权威**——手册更新后重新生成,不得反向以脚本为准;③ 脚本只做编排(发现 → 构建 → 注入),**不得引入手册之外的行为**;④ **不得写死本机路径**(工作区 / Gradle 根 / profile 名 / JDK 安装路径),工作区与 Gradle 根按 R1.1 推导、profile 用 `$DSH_PROFILE_DIR`、JDK 按 R2.1 顺位选择 —— 实测有脚本写死 `$cwd` 与 `profiles\web`,换机器即失效。**生成后自查**:在脚本里 grep 一遍本机绝对路径与写死的 profile 名,应当**只出现推导逻辑、不出现具体值**。
|
|
94
|
+
|
|
93
95
|
> **平台约定:本手册三平台通用**(Windows / macOS / Linux 各步骤都可用)。平台差异见下表;
|
|
94
96
|
> 失败分支表里**未标注平台的条目三平台通用**,标 `[Win]` 的只会发生在 Windows。
|
|
95
97
|
>
|
|
@@ -179,6 +181,7 @@ $proc.CommandLine # 必须含 kd.bos.service.webserver.JettyServer
|
|
|
179
181
|
|
|
180
182
|
> ⚠️ 跨大版本 attach(JDK17 attach JDK8)会报 `AgentLoadException`。
|
|
181
183
|
> ⚠️ Windows 注册表 `HKLM\SOFTWARE\JavaSoft\Java Development Kit\JavaHome` 可能被 JRE 安装包改写 → Gradle 报 `Could not find tools.jar`;**必须显式设 `JAVA_HOME`**。
|
|
184
|
+
> ✅ **别把"两套安装"当成配置错误**:编译类路径来自 `gradle.properties` 的 `systemProp.cosmic_home`(**编译期 SDK**),而 Attacher JDK 取**目标进程自身** —— 实测两者可以是完全不同的安装(如编译期 `F:/xhhome8`、运行实例 `F:\cosmic\xinghan8`),这是**正常布局**,与"能否构建 / 热部署成功"无关,**不要建议用户去改成一致**。唯一固有代价:用到的 API 必须**编译期在 SDK 里、运行期在实例里都存在**(缺前者编译失败,缺后者运行时 `NoSuchMethodError`)。
|
|
182
185
|
|
|
183
186
|
#### R2.2 Gradle(按 wrapper 锁定,不取"最新 dist")
|
|
184
187
|
|
|
@@ -255,12 +258,44 @@ try { & $GRADLE ":<模块>:build" -x test --console=plain } finally { Pop-Locati
|
|
|
255
258
|
|
|
256
259
|
> 真编译判据(三条同时看):① `compileJava` 后**没有** `UP-TO-DATE`/`FROM-CACHE`;② 出现 javac 的 `deprecation`/`unchecked`;③ `build/classes` 下 class 的 mtime 是**刚刚**。
|
|
257
260
|
> ⚠️ 本模板 `gradle.properties` 带 `org.gradle.caching=true`,`clean` 后仍可能 `FROM-CACHE`(macOS 实测 **879ms**、Windows 约 **2 秒** 跑完)。**要真编译必须加 `--no-build-cache`**(必要时再加 `--rerun-tasks` 强制重跑整任务图 —— 注意它在大模块上会连 jar transform 一起重跑,见 R3.2)。
|
|
261
|
+
> 🔬 **一个可复用的诊断手法**:想逼出"真实 javac"又不想全量重编,可**删掉某一个产出的 `.class`** 再构建 —— 如果它 **1~2 秒就从 `FROM-CACHE` 还原**,说明构建缓存(`org.gradle.caching=true`)在起作用、**javac 依然没跑**;此时要真编译必须 `--no-build-cache`。(实测:Windows 1.5s `FROM-CACHE`。)
|
|
262
|
+
|
|
263
|
+
#### R3.2 构建耗时:先看"该花多少"的基准,再判异常
|
|
264
|
+
|
|
265
|
+
**实测基准**(Windows,模块 ~100 class,编译类路径 **4497 jar**;同机同 daemon):
|
|
266
|
+
|
|
267
|
+
| 场景 | Wall | javac 真跑了吗 |
|
|
268
|
+
|------|------|----------------|
|
|
269
|
+
| no-op(只做配置 + UP-TO-DATE 检查) | **1.4s** | 否 |
|
|
270
|
+
| 删产物 class → 构建缓存还原 | **1.5s** | 否(`FROM-CACHE`) |
|
|
271
|
+
| 真 javac(1 个文件,daemon 已预热) | **4.7s** | 是 |
|
|
272
|
+
| 完整 `:build`(1 个文件变更) | **3~4s** | 是 |
|
|
273
|
+
| 完整 build + 热部署(daemon 已预热) | **3.1s** | 否/是 |
|
|
274
|
+
| 同上,但**该 daemon 生命周期内第一次真编译** | **~140s** | 是 |
|
|
275
|
+
|
|
276
|
+
**两种"冷"必须分开,判据不同:**
|
|
277
|
+
|
|
278
|
+
| 触发 | 判据 | 量级 | 处置 |
|
|
279
|
+
|---|---|---|---|
|
|
280
|
+
| ① 快照**从零建**(新工作区 / 新类路径) | `javaCompile/classAnalysis.bin` **持续增长** | 20 分钟级(4000+ jar / 1.9 GB) | 搬运现成快照(见下),或预热一次后等 |
|
|
281
|
+
| ② daemon 首次真编译的一次性开销(**疑为快照载入,未直证**) | `classAnalysis.bin` 已存在(实测 ~370MB)**且不再增长**,而 **wall ≫ 进程 CPU**(实测 140s wall / 累计 ~37s CPU → **≥3/4 的时间不烧 CPU**;**阻塞点未直证** —— 可能在 I/O,也可能在锁) | **~140s,每个 daemon 生命周期只付一次** | 等它跑完(**不要 kill**);之后稳定 3–5s |
|
|
282
|
+
|
|
283
|
+
> 🔁 **独立复现**(另一 daemon、另一日期,**同机同工作区**;源文件 `<Gradle根>/.gradle/user-home/daemon/<ver>/daemon-28568.out.log`):9/23 该 daemon **首次构建 157s** → 同一 daemon 第 2 次构建 **8.7s**。与今天的 139.7s → 3.1s 同一形态 → 结论「每个 daemon 生命周期只付一次」不是偶发。
|
|
284
|
+
> ⚠️ 边界:9/23 那次只留存了 wall(构建期 daemon 日志 0 行、客户端输出未留存),**无法确认当次 javac 是否真跑**,所以写"首次构建"而非"首次真编译";上条结论不受影响。
|
|
285
|
+
> ⚠️ 这 ~140s 的**成因**目前只到「现象吻合」层次:371 MB 分析数据的首次载入,叠加 AV 实时扫描 / 虚拟化磁盘(本机为 Hyper-V 虚拟化环境),**未做 A/B**。别把它写成已证结论。
|
|
286
|
+
|
|
287
|
+
规则:
|
|
258
288
|
|
|
259
|
-
|
|
289
|
+
- **不要 `--no-daemon`**(`org.gradle.daemon=true` 默认开)—— 否则这笔 ~140s 预热每次都要重付。
|
|
290
|
+
- **daemon 重启 / 被回收后,先跑一次哑编译预热**(如 `:<模块>:compileJava`),之后每次改代码 → build + 热部署都在 3–5s。
|
|
291
|
+
- 判"卡住"必须**两个信号同时看**:进程 CPU 增量 ≈ 0 **且** `classAnalysis.bin` 不再增长。只看"没有输出"会把 ② 误判成死锁(这条是实测踩出来的)。
|
|
292
|
+
- **"低 CPU 不是活干在别的进程"的佐证**:Gradle 7.6 默认在 daemon 进程内执行 javac(未显式配 `options.fork`),且实测构建后 `Get-Process java` 只有 Gradle daemon + cosmic + MC 三个 JVM、**无额外 worker**(Gradle worker daemon 默认 idle 3 小时不会自动退,若 fork 过必然还在)。
|
|
293
|
+
- ⚠️ **别用 daemon 的 `.out.log` 去证明这件事**:客户端连着构建时,daemon 会把日志**全部转发给客户端**,`.out.log` 在构建期间**一行都不落** —— 日志里 `Starting process / fork` 计数为 0 是**结构性为零**,不是"观测到没 fork"(实测两份 daemon 日志在构建时段各 0 行;唯一像"编译"的行出现在 daemon **关闭**时释放缓存锁,属假阳性)。
|
|
294
|
+
- ⚠️ **`--rerun-tasks` 非必要不加**:它会强制重跑**整个任务图**(含 `jar transform`),在大模块上更慢,且实测在 `org.gradle.parallel=true` 下撞过 `AsyncCacheAccessDecoratedCache` 的跨进程缓存锁等待(54 线程 parked、守护进程 CPU≈0,12 分钟无进展)。怀疑缓存欺骗时,先试 `clean` + `--no-build-cache`(R3.1),仍不够再考虑它。
|
|
295
|
+
- 🔍 **别把这条与 ② 的 ~140s 合并成一条结论**:本条由 `--rerun-tasks` 触发,且跨**进程**锁需要 ≥2 个 Gradle 进程 —— 实测 ② 发生时机器上只有 **1 个** Gradle 进程(另有 cosmic、MC),条件不满足,两者是不同现象。
|
|
296
|
+
- 可选缓解(**未直证,仅现象吻合**):把安装根(含 `mservice-cosmic/lib`)与 `<Gradle根>/.gradle` 加入 **Defender 实时扫描排除**(需管理员)—— 411 MB 分析文件首次读入被 AV 拦一遍,与百秒级等待吻合,但没有做过 A/B。
|
|
260
297
|
|
|
261
|
-
|
|
262
|
-
- **判据**:`<Gradle根>/.gradle/user-home/caches/<ver>/javaCompile/classAnalysis.bin` **持续增长 = 正在建快照(正常)**;12 秒内该文件不涨**且**守护进程 CPU 增量 ≈ 0 = 可能真卡住。
|
|
263
|
-
- **加速**:从系统 Gradle 主目录搬现成快照(按内容哈希寻址,同机同 jar 可复用):
|
|
298
|
+
**加速(① 的解法)**:从系统 Gradle 主目录搬现成快照(按内容哈希寻址,同机同 jar 可复用):
|
|
264
299
|
|
|
265
300
|
```powershell
|
|
266
301
|
# Windows
|