ai-engineering-init 1.3.3 → 1.4.0

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.
Files changed (228) hide show
  1. package/.claude/hooks/skill-forced-eval.js +4 -1
  2. package/.claude/settings.json +3 -3
  3. package/.claude/skills/add-skill/SKILL.md +252 -116
  4. package/.claude/skills/api-development/SKILL.md +83 -377
  5. package/.claude/skills/architecture-design/SKILL.md +138 -632
  6. package/.claude/skills/backend-annotations/SKILL.md +134 -506
  7. package/.claude/skills/banana-image/SKILL.md +10 -3
  8. package/.claude/skills/brainstorm/SKILL.md +103 -535
  9. package/.claude/skills/bug-detective/SKILL.md +147 -1097
  10. package/.claude/skills/bug-detective/references/error-patterns.md +242 -0
  11. package/.claude/skills/code-patterns/SKILL.md +116 -426
  12. package/.claude/skills/code-patterns/references/leniu-code-patterns.md +87 -0
  13. package/.claude/skills/crud-development/SKILL.md +64 -304
  14. package/.claude/skills/data-permission/SKILL.md +105 -412
  15. package/.claude/skills/data-permission/references/custom-data-scope.md +90 -0
  16. package/.claude/skills/file-oss-management/SKILL.md +106 -714
  17. package/.claude/skills/file-oss-management/references/entities.md +105 -0
  18. package/.claude/skills/file-oss-management/references/service-impl.md +104 -0
  19. package/.claude/skills/leniu-api-development/SKILL.md +142 -626
  20. package/.claude/skills/leniu-api-development/references/real-examples.md +273 -0
  21. package/.claude/skills/leniu-architecture-design/SKILL.md +176 -391
  22. package/.claude/skills/leniu-backend-annotations/SKILL.md +132 -519
  23. package/.claude/skills/leniu-brainstorm/SKILL.md +132 -541
  24. package/.claude/skills/leniu-brainstorm/references/business-scenarios.md +162 -0
  25. package/.claude/skills/leniu-crud-development/SKILL.md +232 -938
  26. package/.claude/skills/leniu-crud-development/references/templates.md +597 -0
  27. package/.claude/skills/leniu-customization-location/SKILL.md +410 -0
  28. package/.claude/skills/leniu-data-permission/SKILL.md +70 -0
  29. package/.claude/skills/leniu-java-entity/SKILL.md +76 -590
  30. package/.claude/skills/leniu-java-entity/references/templates.md +237 -0
  31. package/.claude/skills/leniu-java-export/SKILL.md +94 -379
  32. package/.claude/skills/leniu-java-logging/SKILL.md +106 -709
  33. package/.claude/skills/leniu-java-logging/references/data-mask.md +46 -0
  34. package/.claude/skills/leniu-java-logging/references/logging-scenarios.md +113 -0
  35. package/.claude/skills/leniu-java-mybatis/SKILL.md +73 -446
  36. package/.claude/skills/leniu-java-mybatis/references/report-mapper.md +88 -0
  37. package/.claude/skills/leniu-report-customization/SKILL.md +111 -325
  38. package/.claude/skills/leniu-report-customization/references/table-fields.md +93 -0
  39. package/.claude/skills/leniu-report-standard-customization/SKILL.md +328 -0
  40. package/.claude/skills/leniu-report-standard-customization/references/analysis-module.md +64 -0
  41. package/.claude/skills/leniu-report-standard-customization/references/table-fields.md +113 -0
  42. package/.claude/skills/leniu-security-guard/SKILL.md +133 -347
  43. package/.claude/skills/mysql-debug/SKILL.md +364 -0
  44. package/.claude/skills/openspec-apply-change/SKILL.md +10 -1
  45. package/.claude/skills/openspec-archive-change/SKILL.md +9 -1
  46. package/.claude/skills/openspec-bulk-archive-change/SKILL.md +9 -1
  47. package/.claude/skills/openspec-continue-change/SKILL.md +9 -1
  48. package/.claude/skills/openspec-explore/SKILL.md +10 -1
  49. package/.claude/skills/openspec-ff-change/SKILL.md +9 -1
  50. package/.claude/skills/openspec-new-change/SKILL.md +9 -1
  51. package/.claude/skills/openspec-onboard/SKILL.md +15 -130
  52. package/.claude/skills/openspec-sync-specs/SKILL.md +9 -1
  53. package/.claude/skills/openspec-verify-change/SKILL.md +9 -1
  54. package/.claude/skills/performance-doctor/SKILL.md +110 -434
  55. package/.claude/skills/redis-cache/SKILL.md +89 -595
  56. package/.claude/skills/redis-cache/references/listeners.md +23 -0
  57. package/.claude/skills/scheduled-jobs/SKILL.md +88 -407
  58. package/.claude/skills/security-guard/SKILL.md +137 -532
  59. package/.claude/skills/security-guard/references/encrypt-config.md +103 -0
  60. package/.claude/skills/security-guard/references/sensitive-strategies.md +42 -0
  61. package/.claude/skills/sms-mail/SKILL.md +116 -574
  62. package/.claude/skills/sms-mail/references/mail-config.md +88 -0
  63. package/.claude/skills/sms-mail/references/sms-config.md +74 -0
  64. package/.claude/skills/social-login/SKILL.md +112 -514
  65. package/.claude/skills/social-login/references/provider-configs.md +118 -0
  66. package/.claude/skills/tenant-management/SKILL.md +129 -444
  67. package/.claude/skills/tenant-management/references/tenant-scenarios.md +91 -0
  68. package/.claude/skills/test-development/SKILL.md +86 -540
  69. package/.claude/skills/test-development/references/parameterized-examples.md +119 -0
  70. package/.claude/skills/utils-toolkit/SKILL.md +52 -305
  71. package/.claude/skills/utils-toolkit/references/redis-utils-api.md +56 -0
  72. package/.claude/skills/websocket-sse/SKILL.md +105 -550
  73. package/.claude/skills/workflow-engine/SKILL.md +147 -502
  74. package/.codex/skills/add-skill/SKILL.md +252 -116
  75. package/.codex/skills/api-development/SKILL.md +172 -599
  76. package/.codex/skills/architecture-design/SKILL.md +138 -504
  77. package/.codex/skills/backend-annotations/SKILL.md +134 -496
  78. package/.codex/skills/banana-image/SKILL.md +10 -3
  79. package/.codex/skills/brainstorm/SKILL.md +103 -535
  80. package/.codex/skills/bug-detective/SKILL.md +147 -1097
  81. package/.codex/skills/bug-detective/references/error-patterns.md +242 -0
  82. package/.codex/skills/code-patterns/SKILL.md +120 -282
  83. package/.codex/skills/code-patterns/references/leniu-code-patterns.md +87 -0
  84. package/.codex/skills/crud-development/SKILL.md +64 -292
  85. package/.codex/skills/data-permission/SKILL.md +108 -407
  86. package/.codex/skills/data-permission/references/custom-data-scope.md +90 -0
  87. package/.codex/skills/database-ops/SKILL.md +8 -154
  88. package/.codex/skills/error-handler/SKILL.md +10 -0
  89. package/.codex/skills/file-oss-management/SKILL.md +106 -714
  90. package/.codex/skills/file-oss-management/references/entities.md +105 -0
  91. package/.codex/skills/file-oss-management/references/service-impl.md +104 -0
  92. package/.codex/skills/git-workflow/SKILL.md +27 -5
  93. package/.codex/skills/leniu-api-development/SKILL.md +142 -626
  94. package/.codex/skills/leniu-api-development/references/real-examples.md +273 -0
  95. package/.codex/skills/leniu-architecture-design/SKILL.md +176 -391
  96. package/.codex/skills/leniu-backend-annotations/SKILL.md +132 -519
  97. package/.codex/skills/leniu-brainstorm/SKILL.md +132 -541
  98. package/.codex/skills/leniu-brainstorm/references/business-scenarios.md +162 -0
  99. package/.codex/skills/leniu-crud-development/SKILL.md +232 -938
  100. package/.codex/skills/leniu-crud-development/references/templates.md +597 -0
  101. package/.codex/skills/leniu-customization-location/SKILL.md +410 -0
  102. package/.codex/skills/leniu-data-permission/SKILL.md +70 -0
  103. package/.codex/skills/leniu-java-code-style/SKILL.md +510 -0
  104. package/.codex/skills/leniu-java-entity/SKILL.md +76 -590
  105. package/.codex/skills/leniu-java-entity/references/templates.md +237 -0
  106. package/.codex/skills/leniu-java-export/SKILL.md +94 -379
  107. package/.codex/skills/leniu-java-logging/SKILL.md +106 -709
  108. package/.codex/skills/leniu-java-logging/references/data-mask.md +46 -0
  109. package/.codex/skills/leniu-java-logging/references/logging-scenarios.md +113 -0
  110. package/.codex/skills/leniu-java-mybatis/SKILL.md +73 -446
  111. package/.codex/skills/leniu-java-mybatis/references/report-mapper.md +88 -0
  112. package/.codex/skills/leniu-report-customization/SKILL.md +111 -325
  113. package/.codex/skills/leniu-report-customization/references/table-fields.md +93 -0
  114. package/.codex/skills/leniu-report-standard-customization/SKILL.md +328 -0
  115. package/.codex/skills/leniu-report-standard-customization/references/analysis-module.md +64 -0
  116. package/.codex/skills/leniu-report-standard-customization/references/table-fields.md +113 -0
  117. package/.codex/skills/leniu-security-guard/SKILL.md +133 -347
  118. package/.codex/skills/mysql-debug/SKILL.md +364 -0
  119. package/.codex/skills/openspec-apply-change/SKILL.md +10 -1
  120. package/.codex/skills/openspec-archive-change/SKILL.md +9 -1
  121. package/.codex/skills/openspec-bulk-archive-change/SKILL.md +9 -1
  122. package/.codex/skills/openspec-continue-change/SKILL.md +9 -1
  123. package/.codex/skills/openspec-explore/SKILL.md +10 -1
  124. package/.codex/skills/openspec-ff-change/SKILL.md +9 -1
  125. package/.codex/skills/openspec-new-change/SKILL.md +9 -1
  126. package/.codex/skills/openspec-onboard/SKILL.md +15 -130
  127. package/.codex/skills/openspec-sync-specs/SKILL.md +9 -1
  128. package/.codex/skills/openspec-verify-change/SKILL.md +9 -1
  129. package/.codex/skills/performance-doctor/SKILL.md +110 -434
  130. package/.codex/skills/project-navigator/SKILL.md +20 -1
  131. package/.codex/skills/redis-cache/SKILL.md +93 -589
  132. package/.codex/skills/redis-cache/references/listeners.md +23 -0
  133. package/.codex/skills/scheduled-jobs/SKILL.md +88 -407
  134. package/.codex/skills/security-guard/SKILL.md +141 -527
  135. package/.codex/skills/security-guard/references/encrypt-config.md +103 -0
  136. package/.codex/skills/security-guard/references/sensitive-strategies.md +42 -0
  137. package/.codex/skills/sms-mail/SKILL.md +116 -574
  138. package/.codex/skills/sms-mail/references/mail-config.md +88 -0
  139. package/.codex/skills/sms-mail/references/sms-config.md +74 -0
  140. package/.codex/skills/social-login/SKILL.md +112 -514
  141. package/.codex/skills/social-login/references/provider-configs.md +118 -0
  142. package/.codex/skills/store-pc/SKILL.md +258 -383
  143. package/.codex/skills/tenant-management/SKILL.md +129 -444
  144. package/.codex/skills/tenant-management/references/tenant-scenarios.md +91 -0
  145. package/.codex/skills/test-development/SKILL.md +86 -540
  146. package/.codex/skills/test-development/references/parameterized-examples.md +119 -0
  147. package/.codex/skills/ui-pc/SKILL.md +350 -387
  148. package/.codex/skills/utils-toolkit/SKILL.md +52 -283
  149. package/.codex/skills/utils-toolkit/references/redis-utils-api.md +56 -0
  150. package/.codex/skills/websocket-sse/SKILL.md +105 -550
  151. package/.codex/skills/workflow-engine/SKILL.md +147 -502
  152. package/.cursor/hooks.json +3 -3
  153. package/.cursor/rules/skill-activation.mdc +2 -0
  154. package/.cursor/skills/add-skill/SKILL.md +252 -116
  155. package/.cursor/skills/api-development/SKILL.md +83 -377
  156. package/.cursor/skills/architecture-design/SKILL.md +138 -632
  157. package/.cursor/skills/backend-annotations/SKILL.md +134 -506
  158. package/.cursor/skills/banana-image/SKILL.md +10 -3
  159. package/.cursor/skills/brainstorm/SKILL.md +103 -535
  160. package/.cursor/skills/bug-detective/SKILL.md +147 -1097
  161. package/.cursor/skills/bug-detective/references/error-patterns.md +242 -0
  162. package/.cursor/skills/code-patterns/SKILL.md +116 -426
  163. package/.cursor/skills/code-patterns/references/leniu-code-patterns.md +87 -0
  164. package/.cursor/skills/crud-development/SKILL.md +64 -304
  165. package/.cursor/skills/data-permission/SKILL.md +105 -412
  166. package/.cursor/skills/data-permission/references/custom-data-scope.md +90 -0
  167. package/.cursor/skills/file-oss-management/SKILL.md +106 -714
  168. package/.cursor/skills/file-oss-management/references/entities.md +105 -0
  169. package/.cursor/skills/file-oss-management/references/service-impl.md +104 -0
  170. package/.cursor/skills/git-workflow/SKILL.md +27 -5
  171. package/.cursor/skills/leniu-api-development/SKILL.md +142 -626
  172. package/.cursor/skills/leniu-api-development/references/real-examples.md +273 -0
  173. package/.cursor/skills/leniu-architecture-design/SKILL.md +176 -391
  174. package/.cursor/skills/leniu-backend-annotations/SKILL.md +132 -519
  175. package/.cursor/skills/leniu-brainstorm/SKILL.md +132 -541
  176. package/.cursor/skills/leniu-brainstorm/references/business-scenarios.md +162 -0
  177. package/.cursor/skills/leniu-crud-development/SKILL.md +232 -938
  178. package/.cursor/skills/leniu-crud-development/references/templates.md +597 -0
  179. package/.cursor/skills/leniu-customization-location/SKILL.md +410 -0
  180. package/.cursor/skills/leniu-data-permission/SKILL.md +70 -0
  181. package/.cursor/skills/leniu-java-code-style/SKILL.md +510 -0
  182. package/.cursor/skills/leniu-java-entity/SKILL.md +76 -590
  183. package/.cursor/skills/leniu-java-entity/references/templates.md +237 -0
  184. package/.cursor/skills/leniu-java-export/SKILL.md +94 -379
  185. package/.cursor/skills/leniu-java-logging/SKILL.md +106 -709
  186. package/.cursor/skills/leniu-java-logging/references/data-mask.md +46 -0
  187. package/.cursor/skills/leniu-java-logging/references/logging-scenarios.md +113 -0
  188. package/.cursor/skills/leniu-java-mybatis/SKILL.md +73 -446
  189. package/.cursor/skills/leniu-java-mybatis/references/report-mapper.md +88 -0
  190. package/.cursor/skills/leniu-report-customization/SKILL.md +111 -325
  191. package/.cursor/skills/leniu-report-customization/references/table-fields.md +93 -0
  192. package/.cursor/skills/leniu-report-standard-customization/SKILL.md +328 -0
  193. package/.cursor/skills/leniu-report-standard-customization/references/analysis-module.md +64 -0
  194. package/.cursor/skills/leniu-report-standard-customization/references/table-fields.md +113 -0
  195. package/.cursor/skills/leniu-security-guard/SKILL.md +133 -347
  196. package/.cursor/skills/mysql-debug/SKILL.md +364 -0
  197. package/.cursor/skills/openspec-apply-change/SKILL.md +10 -1
  198. package/.cursor/skills/openspec-archive-change/SKILL.md +9 -1
  199. package/.cursor/skills/openspec-bulk-archive-change/SKILL.md +9 -1
  200. package/.cursor/skills/openspec-continue-change/SKILL.md +9 -1
  201. package/.cursor/skills/openspec-explore/SKILL.md +10 -1
  202. package/.cursor/skills/openspec-ff-change/SKILL.md +9 -1
  203. package/.cursor/skills/openspec-new-change/SKILL.md +9 -1
  204. package/.cursor/skills/openspec-onboard/SKILL.md +15 -130
  205. package/.cursor/skills/openspec-sync-specs/SKILL.md +9 -1
  206. package/.cursor/skills/openspec-verify-change/SKILL.md +9 -1
  207. package/.cursor/skills/performance-doctor/SKILL.md +110 -434
  208. package/.cursor/skills/redis-cache/SKILL.md +89 -595
  209. package/.cursor/skills/redis-cache/references/listeners.md +23 -0
  210. package/.cursor/skills/scheduled-jobs/SKILL.md +88 -407
  211. package/.cursor/skills/security-guard/SKILL.md +137 -532
  212. package/.cursor/skills/security-guard/references/encrypt-config.md +103 -0
  213. package/.cursor/skills/security-guard/references/sensitive-strategies.md +42 -0
  214. package/.cursor/skills/sms-mail/SKILL.md +116 -574
  215. package/.cursor/skills/sms-mail/references/mail-config.md +88 -0
  216. package/.cursor/skills/sms-mail/references/sms-config.md +74 -0
  217. package/.cursor/skills/social-login/SKILL.md +112 -514
  218. package/.cursor/skills/social-login/references/provider-configs.md +118 -0
  219. package/.cursor/skills/tenant-management/SKILL.md +129 -444
  220. package/.cursor/skills/tenant-management/references/tenant-scenarios.md +91 -0
  221. package/.cursor/skills/test-development/SKILL.md +86 -540
  222. package/.cursor/skills/test-development/references/parameterized-examples.md +119 -0
  223. package/.cursor/skills/utils-toolkit/SKILL.md +52 -305
  224. package/.cursor/skills/utils-toolkit/references/redis-utils-api.md +56 -0
  225. package/.cursor/skills/websocket-sse/SKILL.md +105 -550
  226. package/.cursor/skills/workflow-engine/SKILL.md +147 -502
  227. package/AGENTS.md +1 -0
  228. package/package.json +1 -1
@@ -4,7 +4,7 @@ description: |
4
4
  定时任务开发指南。涵盖 @Scheduled、SnailJob 两种方案,支持分布式任务调度、失败重试、工作流编排。
5
5
 
6
6
  触发场景:
7
- - 每日数据汇总、定期清理等周期性任务(@Scheduled)
7
+ - 每日数据汇总、定期清理等周期性任务
8
8
  - 分布式复杂业务、失败重试、可视化管理(SnailJob)
9
9
  - 任务分片、Map/MapReduce 分布式计算
10
10
  - 广播任务(所有节点执行)
@@ -12,108 +12,26 @@ description: |
12
12
  触发词:定时任务、SnailJob、任务调度、重试机制、工作流、@JobExecutor、@Scheduled、分布式任务、广播任务、分片任务、MapReduce
13
13
 
14
14
  核心特性:
15
- - 方案 1:@Scheduled(简单周期任务、框架内置)
16
- - 方案 2:SnailJob(分布式集群、可视化管理、失败重试、工作流编排)
15
+ - @Scheduled:简单周期任务、框架内置
16
+ - SnailJob:分布式集群、可视化管理、失败重试、工作流编排
17
17
  ---
18
18
 
19
19
  # 定时任务开发指南
20
20
 
21
21
  > 模块位置:`ruoyi-modules/ruoyi-job`
22
22
 
23
- ## 快速索引
23
+ ## 方案选择
24
24
 
25
- | 场景 | 推荐方案 | 理由 |
26
- |------|---------|------|
27
- | 简单周期任务(日报、清理) | `@Scheduled` | 框架内置、无依赖 |
28
- | 分布式任务、失败重试 | **SnailJob** | 可视化管理、完整重试 |
29
- | 广播任务(所有节点执行) | **SnailJob** | 支持广播模式 |
30
- | 任务分片(海量数据) | **SnailJob** | 支持静态分片/Map/MapReduce |
25
+ | 场景 | 推荐 | 理由 |
26
+ |------|------|------|
27
+ | 简单周期任务(日报、清理) | `@Scheduled` | 内置、无依赖 |
28
+ | 分布式/需重试/需监控 | **SnailJob** | 可视化管理、完整重试 |
29
+ | 广播(所有节点执行) | **SnailJob** | 支持广播模式 |
30
+ | 海量数据分片 | **SnailJob** | 静态分片/Map/MapReduce |
31
31
 
32
32
  ---
33
33
 
34
- ## 一、@Scheduled 方案(简单场景)
35
-
36
- ### 1.1 快速开始
37
-
38
- ```java
39
- import org.springframework.scheduling.annotation.Scheduled;
40
- import lombok.extern.slf4j.Slf4j;
41
-
42
- @Slf4j
43
- @Component
44
- public class SimpleScheduledTask {
45
-
46
- // ✅ 每天凌晨 2 点执行
47
- @Scheduled(cron = "0 0 2 * * ?")
48
- public void dailyCleanup() {
49
- log.info("开始清理过期数据");
50
- // 业务逻辑
51
- }
52
-
53
- // ✅ 固定频率:每隔 60 秒执行
54
- @Scheduled(fixedRate = 60000)
55
- public void syncData() {
56
- log.info("同步数据");
57
- }
58
-
59
- // ✅ 固定延迟:上次执行结束后延迟 30 秒
60
- @Scheduled(fixedDelay = 30000)
61
- public void checkStatus() {
62
- log.info("检查状态");
63
- }
64
-
65
- // ✅ 初始延迟:启动 10 秒后才开始
66
- @Scheduled(initialDelay = 10000, fixedRate = 60000)
67
- public void reportStats() {
68
- log.info("生成统计");
69
- }
70
- }
71
- ```
72
-
73
- ### 1.2 CRON 表达式
74
-
75
- ```
76
- ┌───────────── 秒 (0-59)
77
- │ ┌───────────── 分钟 (0-59)
78
- │ │ ┌───────────── 小时 (0-23)
79
- │ │ │ ┌───────────── 日期 (1-31)
80
- │ │ │ │ ┌───────────── 月份 (1-12)
81
- │ │ │ │ │ ┌───────────── 星期 (0-7, 0和7都是周日)
82
- * * * * * *
83
- ```
84
-
85
- | 表达式 | 说明 |
86
- |--------|------|
87
- | `0 0 2 * * ?` | 每天 2:00 |
88
- | `0 */5 * * * ?` | 每 5 分钟 |
89
- | `0 0 */6 * * ?` | 每 6 小时 |
90
- | `0 0 0 * * MON` | 每周一 0:00 |
91
- | `0 0 0 1 * ?` | 每月 1 号 0:00 |
92
-
93
- ### 1.3 适用场景
94
-
95
- - ✅ 任务数 < 100
96
- - ✅ 简单逻辑、无需重试
97
- - ✅ 单机执行即可
98
- - ❌ 不适合:需要可视化管理、失败重试、分布式
99
-
100
- ---
101
-
102
- ## 二、SnailJob 方案(分布式场景)
103
-
104
- > 源码位置:`ruoyi-modules/ruoyi-job/src/main/java/org/dromara/job/`
105
-
106
- ### 2.1 核心特性
107
-
108
- | 特性 | 说明 |
109
- |------|------|
110
- | 可视化管理 | Web 界面管理任务 |
111
- | 失败重试 | 多策略:指数退避、固定间隔 |
112
- | 执行模式 | 集群、广播、静态分片、Map、MapReduce |
113
- | 任务监控 | 实时日志、告警通知 |
114
- | 工作流编排 | 可视化流程、决策节点 |
115
-
116
- ### 2.2 配置
34
+ ## SnailJob 配置
117
35
 
118
36
  ```yaml
119
37
  # application-dev.yml
@@ -128,23 +46,20 @@ snail-job:
128
46
  port: 2${server.port}
129
47
  ```
130
48
 
131
- ### 2.3 启用配置
132
-
133
49
  ```java
134
- // 位置:ruoyi-common/ruoyi-common-job/.../config/SnailJobConfig.java
50
+ // ruoyi-common/ruoyi-common-job/.../config/SnailJobConfig.java
135
51
  @AutoConfiguration
136
52
  @ConditionalOnProperty(prefix = "snail-job", name = "enabled", havingValue = "true")
137
53
  @EnableScheduling
138
54
  @EnableSnailJob
139
- public class SnailJobConfig {
140
- }
55
+ public class SnailJobConfig {}
141
56
  ```
142
57
 
143
58
  ---
144
59
 
145
- ## 三、SnailJob 任务类型
60
+ ## SnailJob 任务类型
146
61
 
147
- ### 3.1 基础任务(注解方式)
62
+ ### 基础任务(注解方式,推荐)
148
63
 
149
64
  > 源码:`ruoyi-job/.../snailjob/TestAnnoJobExecutor.java`
150
65
 
@@ -159,361 +74,157 @@ import com.aizuda.snailjob.common.core.util.JsonUtil;
159
74
  @JobExecutor(name = "testJobExecutor")
160
75
  public class TestAnnoJobExecutor {
161
76
 
162
- /**
163
- * 任务执行方法
164
- *
165
- * @param jobArgs 任务参数(包含 jobParams、executorInfo 等)
166
- * @return ExecuteResult 执行结果
167
- */
168
77
  public ExecuteResult jobExecute(JobArgs jobArgs) {
169
- // 本地日志(输出到控制台)
170
- SnailJobLog.LOCAL.info("任务执行,参数: {}", JsonUtil.toJsonString(jobArgs));
171
-
172
- // 远程日志(上报到 SnailJob 控制台)
173
78
  SnailJobLog.REMOTE.info("任务执行,参数: {}", JsonUtil.toJsonString(jobArgs));
174
-
175
- // 获取任务参数
176
79
  String jobParams = jobArgs.getJobParams();
177
-
178
80
  // 业务逻辑...
179
-
180
81
  return ExecuteResult.success("执行成功");
181
82
  }
182
83
  }
183
84
  ```
184
85
 
185
- ### 3.2 基础任务(类方式)
186
-
187
- > 源码:`ruoyi-job/.../snailjob/TestClassJobExecutor.java`
188
-
189
- ```java
190
- import com.aizuda.snailjob.client.job.core.executor.AbstractJobExecutor;
191
- import com.aizuda.snailjob.client.job.core.annotation.JobExecutor;
192
- import com.aizuda.snailjob.client.job.core.dto.JobArgs;
193
- import com.aizuda.snailjob.model.dto.ExecuteResult;
194
- import com.aizuda.snailjob.common.log.SnailJobLog;
195
-
196
- @Component
197
- public class TestClassJobExecutor extends AbstractJobExecutor {
198
-
199
- @Override
200
- protected ExecuteResult doJobExecute(JobArgs jobArgs) {
201
- SnailJobLog.REMOTE.info("类方式执行器,参数: {}", jobArgs.getJobParams());
202
- return ExecuteResult.success("类方式执行成功");
203
- }
204
- }
205
- ```
206
-
207
- ### 3.3 广播任务
86
+ ### 广播任务
208
87
 
209
88
  > 源码:`ruoyi-job/.../snailjob/TestBroadcastJob.java`
210
89
 
211
- 广播任务会在**所有节点**上执行,适用于清理本地缓存等场景。
90
+ 所有节点都执行,适用于清理本地缓存等场景。
212
91
 
213
92
  ```java
214
- import cn.hutool.core.util.RandomUtil;
215
- import com.aizuda.snailjob.client.job.core.annotation.JobExecutor;
216
- import com.aizuda.snailjob.client.job.core.dto.JobArgs;
217
- import com.aizuda.snailjob.model.dto.ExecuteResult;
218
- import com.aizuda.snailjob.common.log.SnailJobLog;
219
- import org.springframework.beans.factory.annotation.Value;
220
-
221
- @Slf4j
222
93
  @Component
223
94
  @JobExecutor(name = "testBroadcastJob")
224
95
  public class TestBroadcastJob {
225
96
 
226
- @Value("${snail-job.port}")
227
- private int clientPort;
228
-
229
97
  public ExecuteResult jobExecute(JobArgs jobArgs) {
230
- int randomInt = RandomUtil.randomInt(100);
231
- SnailJobLog.REMOTE.info("广播任务执行,客户端端口: {}, 随机数: {}", clientPort, randomInt);
232
-
233
- if (randomInt < 50) {
234
- // 抛出异常会触发重试
235
- throw new RuntimeException("随机数小于50,任务失败");
236
- }
237
-
98
+ SnailJobLog.REMOTE.info("广播任务执行");
99
+ // 每个节点都会执行此方法
238
100
  return ExecuteResult.success("广播任务执行成功");
239
101
  }
240
102
  }
241
103
  ```
242
104
 
243
- ### 3.4 静态分片任务
105
+ ### 静态分片任务
244
106
 
245
107
  > 源码:`ruoyi-job/.../snailjob/TestStaticShardingJob.java`
246
108
 
247
- 静态分片将任务按固定数量分成多个分片,每个节点执行不同分片。
109
+ 按固定规则分片,每个节点处理不同数据范围。
248
110
 
249
111
  ```java
250
- import cn.hutool.core.convert.Convert;
251
- import com.aizuda.snailjob.client.job.core.annotation.JobExecutor;
252
- import com.aizuda.snailjob.client.job.core.dto.JobArgs;
253
- import com.aizuda.snailjob.model.dto.ExecuteResult;
254
- import com.aizuda.snailjob.common.log.SnailJobLog;
255
-
256
112
  @Component
257
113
  @JobExecutor(name = "testStaticShardingJob")
258
114
  public class TestStaticShardingJob {
259
115
 
260
- /**
261
- * 静态分片任务
262
- * jobParams 格式:起始ID,结束ID(如:1,100000)
263
- */
116
+ // jobParams 格式:起始ID,结束ID(如:1,100000)
264
117
  public ExecuteResult jobExecute(JobArgs jobArgs) {
265
- String jobParams = Convert.toStr(jobArgs.getJobParams());
266
- SnailJobLog.LOCAL.info("开始执行分片任务,参数: {}", jobParams);
267
-
268
- // 解析分片参数
269
- String[] split = jobParams.split(",");
118
+ String[] split = jobArgs.getJobParams().split(",");
270
119
  Long fromId = Long.parseLong(split[0]);
271
120
  Long toId = Long.parseLong(split[1]);
272
-
273
121
  SnailJobLog.REMOTE.info("处理 ID 范围: {} - {}", fromId, toId);
274
-
275
- // 业务逻辑:处理该范围的数据
276
- // processDataRange(fromId, toId);
277
-
122
+ // 处理该范围的数据
278
123
  return ExecuteResult.success("分片任务完成");
279
124
  }
280
125
  }
281
126
  ```
282
127
 
283
- **控制台配置分片**:
284
- 1. 任务类型选择"静态分片"
285
- 2. 分片参数设置多组(每组对应一个分片):
286
- - 分片 0:`1,100000`
287
- - 分片 1:`100001,200000`
288
- - 分片 2:`200001,300000`
128
+ **控制台分片配置**:分片0=`1,100000` / 分片1=`100001,200000` / 分片2=`200001,300000`
289
129
 
290
- ### 3.5 Map 任务(动态分片)
130
+ ### Map 任务(动态分片)
291
131
 
292
132
  > 源码:`ruoyi-job/.../snailjob/TestMapJobAnnotation.java`
293
133
 
294
- Map 任务适用于需要动态拆分数据的场景,先 Map 分片,然后并行执行。
134
+ 运行时动态拆分数据,并行执行。
295
135
 
296
136
  ```java
297
- import com.aizuda.snailjob.client.job.core.annotation.JobExecutor;
298
137
  import com.aizuda.snailjob.client.job.core.annotation.MapExecutor;
299
138
  import com.aizuda.snailjob.client.job.core.dto.MapArgs;
300
139
  import com.aizuda.snailjob.client.job.core.MapHandler;
301
- import com.aizuda.snailjob.model.dto.ExecuteResult;
302
- import com.aizuda.snailjob.common.log.SnailJobLog;
303
-
304
- import java.util.List;
305
- import java.util.stream.Collectors;
306
- import java.util.stream.IntStream;
307
140
 
308
141
  @Component
309
142
  @JobExecutor(name = "testMapJobAnnotation")
310
143
  public class TestMapJobAnnotation {
311
144
 
312
- /**
313
- * Map 入口:拆分数据
314
- * 无 taskName 的 @MapExecutor 是入口方法
315
- */
316
- @MapExecutor
145
+ @MapExecutor // 无 taskName = 入口方法
317
146
  public ExecuteResult doJobMapExecute(MapArgs mapArgs, MapHandler mapHandler) {
318
- SnailJobLog.REMOTE.info("Map 入口执行");
319
-
320
- // 将 1-200 按每组 50 个分成 4 组
321
147
  List<List<Integer>> partition = IntStream.rangeClosed(1, 200)
322
148
  .boxed()
323
149
  .collect(Collectors.groupingBy(i -> (i - 1) / 50))
324
- .values()
325
- .stream()
326
- .toList();
327
-
328
- // 分发到子任务 doCalc
150
+ .values().stream().toList();
329
151
  return mapHandler.doMap(partition, "doCalc");
330
152
  }
331
153
 
332
- /**
333
- * Map 子任务:处理每个分片
334
- */
335
- @MapExecutor(taskName = "doCalc")
154
+ @MapExecutor(taskName = "doCalc") // 子任务
336
155
  public ExecuteResult doCalc(MapArgs mapArgs) {
337
- // 获取当前分片的数据
338
156
  List<Integer> sourceList = (List<Integer>) mapArgs.getMapResult();
339
-
340
- SnailJobLog.REMOTE.info("处理分片数据,数量: {}", sourceList.size());
341
-
342
- // 计算当前分片的总和
343
- int partitionTotal = sourceList.stream().mapToInt(i -> i).sum();
344
-
345
- return ExecuteResult.success(partitionTotal);
157
+ int total = sourceList.stream().mapToInt(i -> i).sum();
158
+ return ExecuteResult.success(total);
346
159
  }
347
160
  }
348
161
  ```
349
162
 
350
- ### 3.6 MapReduce 任务(分片 + 汇总)
163
+ ### MapReduce 任务(分片 + 汇总)
351
164
 
352
165
  > 源码:`ruoyi-job/.../snailjob/TestMapReduceAnnotation1.java`
353
166
 
354
- MapReduce 在 Map 基础上增加了 Reduce 汇总阶段。
167
+ 在 Map 基础上增加 Reduce 汇总。
355
168
 
356
169
  ```java
357
- import com.aizuda.snailjob.client.job.core.annotation.JobExecutor;
358
- import com.aizuda.snailjob.client.job.core.annotation.MapExecutor;
359
170
  import com.aizuda.snailjob.client.job.core.annotation.ReduceExecutor;
360
- import com.aizuda.snailjob.client.job.core.dto.MapArgs;
361
171
  import com.aizuda.snailjob.client.job.core.dto.ReduceArgs;
362
- import com.aizuda.snailjob.client.job.core.MapHandler;
363
- import com.aizuda.snailjob.model.dto.ExecuteResult;
364
- import com.aizuda.snailjob.common.log.SnailJobLog;
365
-
366
- import java.util.List;
367
- import java.util.stream.Collectors;
368
- import java.util.stream.IntStream;
369
172
 
370
173
  @Component
371
174
  @JobExecutor(name = "testMapReduceAnnotation1")
372
175
  public class TestMapReduceAnnotation1 {
373
176
 
374
- /**
375
- * Map 入口:拆分数据
376
- */
377
177
  @MapExecutor
378
178
  public ExecuteResult rootMapExecute(MapArgs mapArgs, MapHandler mapHandler) {
379
- SnailJobLog.REMOTE.info("MapReduce 入口执行");
380
-
381
- // 将 1-200 按每组 50 个分成 4 组
382
- List<List<Integer>> partition = IntStream.rangeClosed(1, 200)
383
- .boxed()
384
- .collect(Collectors.groupingBy(i -> (i - 1) / 50))
385
- .values()
386
- .stream()
387
- .toList();
388
-
179
+ // 拆分数据(同 Map 任务)
389
180
  return mapHandler.doMap(partition, "doCalc");
390
181
  }
391
182
 
392
- /**
393
- * Map 子任务:计算每个分片的总和
394
- */
395
183
  @MapExecutor(taskName = "doCalc")
396
184
  public ExecuteResult doCalc(MapArgs mapArgs) {
397
185
  List<Integer> sourceList = (List<Integer>) mapArgs.getMapResult();
398
-
399
- int partitionTotal = sourceList.stream().mapToInt(i -> i).sum();
400
-
401
- SnailJobLog.REMOTE.info("分片计算完成,总和: {}", partitionTotal);
402
-
403
- return ExecuteResult.success(partitionTotal);
186
+ return ExecuteResult.success(sourceList.stream().mapToInt(i -> i).sum());
404
187
  }
405
188
 
406
- /**
407
- * Reduce 汇总:合并所有分片结果
408
- */
409
189
  @ReduceExecutor
410
190
  public ExecuteResult reduceExecute(ReduceArgs reduceArgs) {
411
- // 获取所有 Map 子任务的结果
412
191
  List<?> mapResults = reduceArgs.getMapResult();
413
-
414
- int reduceTotal = mapResults.stream()
415
- .mapToInt(i -> Integer.parseInt((String) i))
416
- .sum();
417
-
418
- SnailJobLog.REMOTE.info("Reduce 汇总完成,最终总和: {}", reduceTotal);
419
-
420
- return ExecuteResult.success(reduceTotal);
421
- }
422
- }
423
- ```
424
-
425
- ---
426
-
427
- ## 四、SnailJob 日志工具
428
-
429
- ### 4.1 日志类型
430
-
431
- ```java
432
- import com.aizuda.snailjob.common.log.SnailJobLog;
433
-
434
- // 本地日志(输出到控制台/日志文件)
435
- SnailJobLog.LOCAL.info("本地日志: {}", message);
436
- SnailJobLog.LOCAL.warn("警告: {}", message);
437
- SnailJobLog.LOCAL.error("错误: {}", message, exception);
438
-
439
- // 远程日志(上报到 SnailJob 控制台,可在 Web 界面查看)
440
- SnailJobLog.REMOTE.info("远程日志: {}", message);
441
- SnailJobLog.REMOTE.warn("警告: {}", message);
442
- SnailJobLog.REMOTE.error("错误: {}", message, exception);
443
- ```
444
-
445
- ### 4.2 日志最佳实践
446
-
447
- ```java
448
- @Component
449
- @JobExecutor(name = "orderProcessJob")
450
- public class OrderProcessJob {
451
-
452
- public ExecuteResult jobExecute(JobArgs jobArgs) {
453
- String jobParams = jobArgs.getJobParams();
454
-
455
- // 1. 记录任务开始
456
- SnailJobLog.REMOTE.info("开始处理订单,参数: {}", jobParams);
457
-
458
- try {
459
- // 2. 业务逻辑
460
- int count = processOrders(jobParams);
461
-
462
- // 3. 记录成功
463
- SnailJobLog.REMOTE.info("订单处理完成,处理数量: {}", count);
464
- return ExecuteResult.success("处理 " + count + " 条订单");
465
-
466
- } catch (Exception e) {
467
- // 4. 记录失败(同时记录本地和远程)
468
- SnailJobLog.LOCAL.error("订单处理失败", e);
469
- SnailJobLog.REMOTE.error("订单处理失败: {}", e.getMessage());
470
-
471
- // 抛出异常触发重试
472
- throw e;
473
- }
192
+ int total = mapResults.stream()
193
+ .mapToInt(i -> Integer.parseInt((String) i)).sum();
194
+ SnailJobLog.REMOTE.info("Reduce 汇总,最终总和: {}", total);
195
+ return ExecuteResult.success(total);
474
196
  }
475
197
  }
476
198
  ```
477
199
 
478
200
  ---
479
201
 
480
- ## 五、执行模式对比
202
+ ## 执行模式对比
481
203
 
482
204
  | 模式 | 特点 | 适用场景 |
483
205
  |------|------|---------|
484
206
  | **集群** | 多节点竞争,只有一个执行 | 订单处理、数据汇总 |
485
207
  | **广播** | 所有节点都执行 | 清理缓存、刷新配置 |
486
208
  | **静态分片** | 按固定规则分片 | 已知数据范围的批处理 |
487
- | **Map** | 动态分片 | 需要运行时确定分片的场景 |
209
+ | **Map** | 动态分片 | 运行时确定分片 |
488
210
  | **MapReduce** | 动态分片 + 结果汇总 | 分布式计算(求和、统计) |
489
211
 
490
212
  ---
491
213
 
492
- ## 六、控制台配置
493
-
494
- ### 6.1 创建任务
214
+ ## 日志工具
495
215
 
496
- 1. 访问 SnailJob 控制台
497
- 2. **任务管理** → **新增任务**
498
- 3. 配置项:
499
- - 任务名称:`testJobExecutor`(与 `@JobExecutor(name)` 一致)
500
- - 任务类型:集群/广播/静态分片/Map/MapReduce
501
- - 触发类型:CRON / 固定频率
502
- - CRON 表达式:`0 0 2 * * ?`
503
-
504
- ### 6.2 重试策略
216
+ ```java
217
+ import com.aizuda.snailjob.common.log.SnailJobLog;
505
218
 
506
- | 策略 | 说明 | 使用场景 |
507
- |------|------|---------|
508
- | 固定间隔 | 每次间隔相同 | 网络抖动 |
509
- | 指数退避 | 间隔逐倍增加 | 服务恢复中 |
510
- | CRON | 按表达式重试 | 定点重试 |
219
+ SnailJobLog.LOCAL.info("本地日志: {}", msg); // 输出到控制台/日志文件
220
+ SnailJobLog.REMOTE.info("远程日志: {}", msg); // 上报到 SnailJob 控制台
221
+ ```
511
222
 
512
223
  ---
513
224
 
514
- ## 七、最佳实践
225
+ ## 最佳实践
515
226
 
516
- ### 7.1 任务实现规范
227
+ ### 标准任务模板
517
228
 
518
229
  ```java
519
230
  @Component
@@ -525,19 +236,12 @@ public class OrderCleanupJob {
525
236
 
526
237
  public ExecuteResult jobExecute(JobArgs jobArgs) {
527
238
  SnailJobLog.REMOTE.info("开始清理过期订单");
528
-
529
239
  try {
530
- // 1. 解析参数
531
240
  String params = jobArgs.getJobParams();
532
241
  int days = StringUtils.isBlank(params) ? 30 : Integer.parseInt(params);
533
-
534
- // 2. 执行业务
535
242
  int count = orderService.cleanupExpiredOrders(days);
536
-
537
- // 3. 返回成功
538
- SnailJobLog.REMOTE.info("清理完成,删除 {} 条订单", count);
243
+ SnailJobLog.REMOTE.info("清理完成,删除 {} 条", count);
539
244
  return ExecuteResult.success("清理 " + count + " 条");
540
-
541
245
  } catch (Exception e) {
542
246
  SnailJobLog.REMOTE.error("清理失败: {}", e.getMessage());
543
247
  throw e; // 抛出异常触发重试
@@ -546,88 +250,65 @@ public class OrderCleanupJob {
546
250
  }
547
251
  ```
548
252
 
549
- ### 7.2 幂等性保证
253
+ ### 幂等性保证
550
254
 
551
255
  ```java
552
- @Component
553
- @JobExecutor(name = "paymentSyncJob")
554
- public class PaymentSyncJob {
555
-
556
- public ExecuteResult jobExecute(JobArgs jobArgs) {
557
- String orderId = jobArgs.getJobParams();
558
-
559
- // 1. 幂等检查
560
- if (paymentService.isSynced(orderId)) {
561
- SnailJobLog.REMOTE.info("订单 {} 已同步,跳过", orderId);
562
- return ExecuteResult.success("已同步");
563
- }
564
-
565
- // 2. 执行同步
566
- paymentService.sync(orderId);
567
-
568
- return ExecuteResult.success("同步成功");
256
+ public ExecuteResult jobExecute(JobArgs jobArgs) {
257
+ String orderId = jobArgs.getJobParams();
258
+ if (paymentService.isSynced(orderId)) {
259
+ return ExecuteResult.success("已同步,跳过");
569
260
  }
261
+ paymentService.sync(orderId);
262
+ return ExecuteResult.success("同步成功");
570
263
  }
571
264
  ```
572
265
 
573
- ### 7.3 错误处理
266
+ ### 错误处理
574
267
 
575
268
  ```java
576
- // 正确:抛出异常触发重试
577
- public ExecuteResult jobExecute(JobArgs jobArgs) {
578
- try {
579
- // 业务逻辑
580
- } catch (Exception e) {
581
- SnailJobLog.REMOTE.error("执行失败", e);
582
- throw e; // ✅ 抛出异常,SnailJob 会自动重试
583
- }
584
- }
269
+ // 抛出异常 -> SnailJob 自动重试
270
+ throw e;
585
271
 
586
- // 错误:吞掉异常,不会触发重试
587
- public ExecuteResult jobExecute(JobArgs jobArgs) {
588
- try {
589
- // 业务逻辑
590
- } catch (Exception e) {
591
- SnailJobLog.REMOTE.error("执行失败", e);
592
- return ExecuteResult.failure("失败"); // ❌ 不会触发重试
593
- }
594
- }
272
+ // 返回 failure -> 不会触发重试(慎用)
273
+ return ExecuteResult.failure("失败");
595
274
  ```
596
275
 
597
276
  ---
598
277
 
599
- ## 八、常见问题
278
+ ## 控制台配置
600
279
 
601
- ### Q1:任务不执行?
280
+ 1. **任务管理** -> **新增任务**
281
+ 2. 任务名称与 `@JobExecutor(name)` 一致
282
+ 3. 任务类型:集群/广播/静态分片/Map/MapReduce
283
+ 4. 触发类型:CRON / 固定频率
602
284
 
603
- 1. 检查 `snail-job.enabled: true`
604
- 2. 检查 `@JobExecutor(name)` 与控制台配置一致
605
- 3. 检查 SnailJob 服务是否启动
606
- 4. 查看日志是否有连接错误
285
+ ### 重试策略
607
286
 
608
- ### Q2:@Scheduled vs SnailJob 怎么选?
287
+ | 策略 | 说明 | 场景 |
288
+ |------|------|------|
289
+ | 固定间隔 | 每次间隔相同 | 网络抖动 |
290
+ | 指数退避 | 间隔逐倍增加 | 服务恢复中 |
291
+ | CRON | 按表达式重试 | 定点重试 |
609
292
 
610
- | 条件 | 选择 |
611
- |------|------|
612
- | 任务 < 100,简单逻辑 | `@Scheduled` |
613
- | 需要重试、监控 | SnailJob |
614
- | 分布式部署 | SnailJob |
615
- | 需要 Web 管理 | SnailJob |
293
+ ---
616
294
 
617
- ### Q3:如何查看任务日志?
295
+ ## 常见问题
618
296
 
619
- - **本地日志**:查看应用日志文件
620
- - **远程日志**:SnailJob 控制台 → 任务实例 → 查看日志
297
+ | 问题 | 排查步骤 |
298
+ |------|---------|
299
+ | 任务不执行 | 1.检查 `snail-job.enabled: true` 2.`@JobExecutor(name)` 与控制台一致 3.SnailJob 服务是否启动 |
300
+ | @Scheduled vs SnailJob | 简单/<100个任务 -> @Scheduled;需重试/监控/分布式 -> SnailJob |
301
+ | 查看任务日志 | 本地 -> 应用日志;远程 -> SnailJob 控制台 -> 任务实例 -> 查看日志 |
621
302
 
622
303
  ---
623
304
 
624
- ## 九、核心文件位置
305
+ ## 核心文件位置
625
306
 
626
307
  | 文件 | 路径 |
627
308
  |------|------|
628
- | 注解方式示例 | `ruoyi-modules/ruoyi-job/.../snailjob/TestAnnoJobExecutor.java` |
629
- | 类方式示例 | `ruoyi-modules/ruoyi-job/.../snailjob/TestClassJobExecutor.java` |
630
- | 广播任务示例 | `ruoyi-modules/ruoyi-job/.../snailjob/TestBroadcastJob.java` |
631
- | 静态分片示例 | `ruoyi-modules/ruoyi-job/.../snailjob/TestStaticShardingJob.java` |
632
- | Map 任务示例 | `ruoyi-modules/ruoyi-job/.../snailjob/TestMapJobAnnotation.java` |
633
- | MapReduce 示例 | `ruoyi-modules/ruoyi-job/.../snailjob/TestMapReduceAnnotation1.java` |
309
+ | 注解方式 | `ruoyi-modules/ruoyi-job/.../snailjob/TestAnnoJobExecutor.java` |
310
+ | 类方式 | `ruoyi-modules/ruoyi-job/.../snailjob/TestClassJobExecutor.java` |
311
+ | 广播任务 | `ruoyi-modules/ruoyi-job/.../snailjob/TestBroadcastJob.java` |
312
+ | 静态分片 | `ruoyi-modules/ruoyi-job/.../snailjob/TestStaticShardingJob.java` |
313
+ | Map 任务 | `ruoyi-modules/ruoyi-job/.../snailjob/TestMapJobAnnotation.java` |
314
+ | MapReduce | `ruoyi-modules/ruoyi-job/.../snailjob/TestMapReduceAnnotation1.java` |