wok-server 0.4.13 → 0.6.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.
- package/README.en.md +61 -0
- package/README.md +44 -29
- package/dist/cache/cache.js +98 -98
- package/dist/cache/config.js +19 -19
- package/dist/cache/index.js +27 -27
- package/dist/cache/purge-task.js +46 -46
- package/dist/cache/stat.js +47 -47
- package/dist/config/convert.js +36 -36
- package/dist/config/exception.js +14 -14
- package/dist/config/index.js +81 -81
- package/dist/http-client/index.js +136 -136
- package/dist/i18n/ar.js +17 -17
- package/dist/i18n/de.js +17 -17
- package/dist/i18n/en-us.js +17 -17
- package/dist/i18n/es.js +17 -17
- package/dist/i18n/fr.js +17 -17
- package/dist/i18n/i18n.js +231 -231
- package/dist/i18n/index.js +52 -52
- package/dist/i18n/ja.js +17 -17
- package/dist/i18n/ko.js +17 -17
- package/dist/i18n/msg.js +2 -2
- package/dist/i18n/pt.js +17 -17
- package/dist/i18n/ru.js +17 -17
- package/dist/i18n/tag.js +18 -18
- package/dist/i18n/zh-HK.js +17 -17
- package/dist/i18n/zh-TW.js +17 -17
- package/dist/i18n/zh-cn.js +17 -17
- package/dist/index.js +14 -14
- package/dist/lock/index.js +114 -114
- package/dist/log/config.js +35 -29
- package/dist/log/date.js +21 -21
- package/dist/log/file.js +198 -72
- package/dist/log/index.js +135 -105
- package/dist/log/level.js +33 -33
- package/dist/log/log.js +56 -0
- package/dist/log/store.js +19 -16
- package/dist/mongodb/collection.js +2 -2
- package/dist/mongodb/config.js +34 -34
- package/dist/mongodb/doc.js +2 -2
- package/dist/mongodb/exception.js +14 -14
- package/dist/mongodb/index.js +58 -58
- package/dist/mongodb/manager/base.js +563 -563
- package/dist/mongodb/manager/index.js +63 -63
- package/dist/mongodb/manager/tx-strict.js +84 -84
- package/dist/mongodb/manager/tx.js +30 -30
- package/dist/mongodb/migration.js +52 -52
- package/dist/mvc/access-log.js +33 -33
- package/dist/mvc/config.js +27 -27
- package/dist/mvc/exchange.js +113 -113
- package/dist/mvc/handler/index.js +7 -6
- package/dist/mvc/handler/json.js +65 -65
- package/dist/mvc/handler/restful.js +35 -35
- package/dist/mvc/handler/sse.js +65 -0
- package/dist/mvc/handler/upload.js +31 -31
- package/dist/mvc/index.js +50 -50
- package/dist/mvc/interceptor.js +2 -2
- package/dist/mvc/query.js +43 -43
- package/dist/mvc/render/file.js +132 -132
- package/dist/mvc/render/html/html.js +90 -90
- package/dist/mvc/render/html/index.js +18 -18
- package/dist/mvc/render/html/style.js +2 -2
- package/dist/mvc/render/index.js +7 -7
- package/dist/mvc/render/json.js +26 -26
- package/dist/mvc/render/text.js +16 -16
- package/dist/mvc/router.js +2 -2
- package/dist/mvc/server.js +272 -272
- package/dist/mvc/static/header.js +67 -67
- package/dist/mvc/static/index.js +6 -6
- package/dist/mvc/static/mime-type.js +84 -84
- package/dist/mvc/static/server-cache-config.js +66 -66
- package/dist/mvc/static/server-cache.js +133 -133
- package/dist/mvc/static/static-handler.js +372 -372
- package/dist/mysql/config.js +51 -51
- package/dist/mysql/exception.js +14 -14
- package/dist/mysql/index.js +87 -87
- package/dist/mysql/manager/base.js +239 -231
- package/dist/mysql/manager/index.js +107 -107
- package/dist/mysql/manager/ops/count.js +20 -20
- package/dist/mysql/manager/ops/criteria.js +356 -356
- package/dist/mysql/manager/ops/delete.js +65 -65
- package/dist/mysql/manager/ops/exist.js +26 -26
- package/dist/mysql/manager/ops/find.js +169 -130
- package/dist/mysql/manager/ops/index.js +14 -14
- package/dist/mysql/manager/ops/insert.js +106 -106
- package/dist/mysql/manager/ops/modify.js +10 -10
- package/dist/mysql/manager/ops/paginate.js +23 -23
- package/dist/mysql/manager/ops/query.js +9 -9
- package/dist/mysql/manager/ops/update.js +216 -216
- package/dist/mysql/manager/ops/utils.js +24 -24
- package/dist/mysql/manager/tx-strict.js +103 -100
- package/dist/mysql/manager/tx.js +30 -30
- package/dist/mysql/manager/utils.js +56 -56
- package/dist/mysql/migration.js +136 -136
- package/dist/mysql/table-info.js +8 -8
- package/dist/task/daily.js +59 -59
- package/dist/task/fixed-delay.js +38 -38
- package/dist/task/fixed-rate.js +42 -42
- package/dist/task/index.js +9 -9
- package/dist/task/task.js +56 -56
- package/dist/validation/exception.js +36 -36
- package/dist/validation/index.js +40 -40
- package/dist/validation/validator/array.js +34 -34
- package/dist/validation/validator/enum.js +28 -28
- package/dist/validation/validator/index.js +14 -14
- package/dist/validation/validator/length.js +40 -40
- package/dist/validation/validator/max-length.js +35 -35
- package/dist/validation/validator/max.js +29 -29
- package/dist/validation/validator/min-length.js +33 -33
- package/dist/validation/validator/min.js +29 -29
- package/dist/validation/validator/not-blank.js +33 -33
- package/dist/validation/validator/not-null.js +21 -21
- package/dist/validation/validator/plain-obj.js +32 -32
- package/dist/validation/validator/regexp.js +34 -34
- package/documentation/en/cache.md +56 -0
- package/documentation/en/config.md +96 -0
- package/documentation/en/engineering.md +256 -0
- package/documentation/en/http-client.md +32 -0
- package/documentation/en/i18n.md +143 -0
- package/documentation/en/index.md +24 -0
- package/documentation/en/lock.md +51 -0
- package/documentation/en/log.md +109 -0
- package/documentation/en/mongodb.md +256 -0
- package/documentation/en/mvc.md +688 -0
- package/documentation/en/mysql.md +552 -0
- package/documentation/en/task.md +45 -0
- package/documentation/en/test.md +56 -0
- package/documentation/en/validate.md +130 -0
- package/documentation/zh-cn/engineering.md +1 -1
- package/documentation/zh-cn/log.md +81 -8
- package/documentation/zh-cn/mvc.md +66 -24
- package/documentation/zh-cn/mysql.md +24 -23
- package/documentation/zh-cn/validate.md +2 -2
- package/package.json +3 -1
- package/skills/wok-server-api-rules/SKILL.md +350 -0
- package/skills/wok-server-cache/SKILL.md +216 -0
- package/skills/wok-server-config/SKILL.md +200 -0
- package/skills/wok-server-getting-started/SKILL.md +123 -0
- package/skills/wok-server-getting-started/references/engineering.md +169 -0
- package/skills/wok-server-http-client/SKILL.md +164 -0
- package/skills/wok-server-i18n/SKILL.md +214 -0
- package/skills/wok-server-lock/SKILL.md +144 -0
- package/skills/wok-server-log/SKILL.md +218 -0
- package/skills/wok-server-mongodb/SKILL.md +235 -0
- package/skills/wok-server-mvc/SKILL.md +251 -0
- package/skills/wok-server-mvc/references/respond-html.md +157 -0
- package/skills/wok-server-mvc/references/sse.md +121 -0
- package/skills/wok-server-mvc/references/static-files.md +47 -0
- package/skills/wok-server-mvc/references/upload.md +62 -0
- package/skills/wok-server-mvc/references/websocket.md +30 -0
- package/skills/wok-server-mysql/SKILL.md +315 -0
- package/skills/wok-server-mysql/references/multi-datasource.md +76 -0
- package/skills/wok-server-mysql/references/version-control.md +22 -0
- package/skills/wok-server-task/SKILL.md +158 -0
- package/skills/wok-server-validate/SKILL.md +167 -0
- package/src/cache/cache.ts +118 -0
- package/src/cache/config.ts +53 -0
- package/src/cache/index.ts +27 -0
- package/src/cache/purge-task.ts +53 -0
- package/src/cache/stat.ts +47 -0
- package/src/config/convert.ts +27 -0
- package/src/config/exception.ts +8 -0
- package/src/config/index.ts +92 -0
- package/src/http-client/index.ts +202 -0
- package/src/i18n/ar.ts +16 -0
- package/src/i18n/de.ts +16 -0
- package/src/i18n/en-us.ts +16 -0
- package/src/i18n/es.ts +16 -0
- package/src/i18n/fr.ts +16 -0
- package/src/i18n/i18n.ts +230 -0
- package/src/i18n/index.ts +50 -0
- package/src/i18n/ja.ts +16 -0
- package/src/i18n/ko.ts +16 -0
- package/src/i18n/msg.ts +50 -0
- package/src/i18n/pt.ts +16 -0
- package/src/i18n/ru.ts +16 -0
- package/src/i18n/tag.ts +18 -0
- package/src/i18n/zh-HK.ts +16 -0
- package/src/i18n/zh-TW.ts +16 -0
- package/src/i18n/zh-cn.ts +16 -0
- package/src/index.ts +11 -0
- package/src/lock/index.ts +164 -0
- package/src/log/config.ts +71 -0
- package/src/log/date.ts +19 -0
- package/src/log/file.ts +215 -0
- package/src/log/index.ts +136 -0
- package/src/log/level.ts +29 -0
- package/src/log/log.ts +77 -0
- package/src/log/store.ts +31 -0
- package/src/mongodb/collection.ts +25 -0
- package/src/mongodb/config.ts +69 -0
- package/src/mongodb/doc.ts +12 -0
- package/src/mongodb/exception.ts +8 -0
- package/src/mongodb/index.ts +71 -0
- package/src/mongodb/manager/base.ts +674 -0
- package/src/mongodb/manager/index.ts +80 -0
- package/src/mongodb/manager/tx-strict.ts +153 -0
- package/src/mongodb/manager/tx.ts +34 -0
- package/src/mongodb/migration.ts +66 -0
- package/src/mvc/access-log.ts +33 -0
- package/src/mvc/config.ts +70 -0
- package/src/mvc/exchange.ts +126 -0
- package/src/mvc/handler/index.ts +4 -0
- package/src/mvc/handler/json.ts +96 -0
- package/src/mvc/handler/restful.ts +39 -0
- package/src/mvc/handler/sse.ts +90 -0
- package/src/mvc/handler/upload.ts +54 -0
- package/src/mvc/index.ts +48 -0
- package/src/mvc/interceptor.ts +12 -0
- package/src/mvc/query.ts +36 -0
- package/src/mvc/render/file.ts +148 -0
- package/src/mvc/render/html/html.ts +187 -0
- package/src/mvc/render/html/index.ts +16 -0
- package/src/mvc/render/html/style.ts +1201 -0
- package/src/mvc/render/index.ts +4 -0
- package/src/mvc/render/json.ts +24 -0
- package/src/mvc/render/text.ts +14 -0
- package/src/mvc/router.ts +13 -0
- package/src/mvc/server.ts +315 -0
- package/src/mvc/static/header.ts +86 -0
- package/src/mvc/static/index.ts +3 -0
- package/src/mvc/static/mime-type.ts +81 -0
- package/src/mvc/static/server-cache-config.ts +92 -0
- package/src/mvc/static/server-cache.ts +171 -0
- package/src/mvc/static/static-handler.ts +445 -0
- package/src/mysql/config.ts +130 -0
- package/src/mysql/exception.ts +8 -0
- package/src/mysql/index.ts +88 -0
- package/src/mysql/manager/base.ts +285 -0
- package/src/mysql/manager/index.ts +112 -0
- package/src/mysql/manager/ops/count.ts +30 -0
- package/src/mysql/manager/ops/criteria.ts +412 -0
- package/src/mysql/manager/ops/delete.ts +96 -0
- package/src/mysql/manager/ops/exist.ts +41 -0
- package/src/mysql/manager/ops/find.ts +226 -0
- package/src/mysql/manager/ops/index.ts +11 -0
- package/src/mysql/manager/ops/insert.ts +120 -0
- package/src/mysql/manager/ops/modify.ts +14 -0
- package/src/mysql/manager/ops/paginate.ts +60 -0
- package/src/mysql/manager/ops/query.ts +13 -0
- package/src/mysql/manager/ops/update.ts +294 -0
- package/src/mysql/manager/ops/utils.ts +20 -0
- package/src/mysql/manager/tx-strict.ts +138 -0
- package/src/mysql/manager/tx.ts +31 -0
- package/src/mysql/manager/utils.ts +75 -0
- package/src/mysql/migration.ts +149 -0
- package/src/mysql/table-info.ts +41 -0
- package/src/task/daily.ts +70 -0
- package/src/task/fixed-delay.ts +45 -0
- package/src/task/fixed-rate.ts +49 -0
- package/src/task/index.ts +4 -0
- package/src/task/task.ts +70 -0
- package/src/validation/exception.ts +27 -0
- package/src/validation/index.ts +61 -0
- package/src/validation/validator/array.ts +32 -0
- package/src/validation/validator/enum.ts +25 -0
- package/src/validation/validator/index.ts +11 -0
- package/src/validation/validator/length.ts +42 -0
- package/src/validation/validator/max-length.ts +33 -0
- package/src/validation/validator/max.ts +26 -0
- package/src/validation/validator/min-length.ts +31 -0
- package/src/validation/validator/min.ts +26 -0
- package/src/validation/validator/not-blank.ts +31 -0
- package/src/validation/validator/not-null.ts +19 -0
- package/src/validation/validator/plain-obj.ts +30 -0
- package/src/validation/validator/regexp.ts +32 -0
- package/types/cache/cache.d.ts +52 -52
- package/types/cache/config.d.ts +32 -32
- package/types/cache/index.d.ts +2 -2
- package/types/cache/purge-task.d.ts +11 -11
- package/types/cache/stat.d.ts +26 -26
- package/types/config/convert.d.ts +6 -6
- package/types/config/exception.d.ts +7 -7
- package/types/config/index.d.ts +25 -25
- package/types/http-client/index.d.ts +71 -71
- package/types/i18n/ar.d.ts +2 -2
- package/types/i18n/de.d.ts +2 -2
- package/types/i18n/en-us.d.ts +2 -2
- package/types/i18n/es.d.ts +2 -2
- package/types/i18n/fr.d.ts +2 -2
- package/types/i18n/i18n.d.ts +102 -102
- package/types/i18n/index.d.ts +9 -9
- package/types/i18n/ja.d.ts +2 -2
- package/types/i18n/ko.d.ts +2 -2
- package/types/i18n/msg.d.ts +50 -50
- package/types/i18n/pt.d.ts +2 -2
- package/types/i18n/ru.d.ts +2 -2
- package/types/i18n/tag.d.ts +11 -11
- package/types/i18n/zh-HK.d.ts +2 -2
- package/types/i18n/zh-TW.d.ts +2 -2
- package/types/i18n/zh-cn.d.ts +2 -2
- package/types/index.d.ts +11 -11
- package/types/lock/index.d.ts +64 -64
- package/types/log/config.d.ts +35 -27
- package/types/log/date.d.ts +2 -2
- package/types/log/file.d.ts +13 -5
- package/types/log/index.d.ts +53 -34
- package/types/log/level.d.ts +14 -14
- package/types/log/log.d.ts +40 -0
- package/types/log/store.d.ts +19 -12
- package/types/mongodb/collection.d.ts +25 -25
- package/types/mongodb/config.d.ts +45 -45
- package/types/mongodb/doc.d.ts +11 -11
- package/types/mongodb/exception.d.ts +7 -7
- package/types/mongodb/index.d.ts +29 -29
- package/types/mongodb/manager/base.d.ts +188 -188
- package/types/mongodb/manager/index.d.ts +38 -38
- package/types/mongodb/manager/tx-strict.d.ts +41 -41
- package/types/mongodb/manager/tx.d.ts +21 -21
- package/types/mongodb/migration.d.ts +12 -12
- package/types/mvc/access-log.d.ts +7 -7
- package/types/mvc/config.d.ts +42 -42
- package/types/mvc/exchange.d.ts +72 -72
- package/types/mvc/handler/index.d.ts +4 -3
- package/types/mvc/handler/json.d.ts +44 -44
- package/types/mvc/handler/restful.d.ts +11 -11
- package/types/mvc/handler/sse.d.ts +34 -0
- package/types/mvc/handler/upload.d.ts +36 -36
- package/types/mvc/index.d.ts +22 -22
- package/types/mvc/interceptor.d.ts +11 -11
- package/types/mvc/query.d.ts +13 -13
- package/types/mvc/render/file.d.ts +10 -10
- package/types/mvc/render/html/html.d.ts +98 -98
- package/types/mvc/render/html/index.d.ts +11 -11
- package/types/mvc/render/html/style.d.ts +1201 -1201
- package/types/mvc/render/index.d.ts +4 -4
- package/types/mvc/render/json.d.ts +17 -17
- package/types/mvc/render/text.d.ts +10 -10
- package/types/mvc/router.d.ts +11 -11
- package/types/mvc/server.d.ts +90 -90
- package/types/mvc/static/header.d.ts +27 -27
- package/types/mvc/static/index.d.ts +3 -3
- package/types/mvc/static/mime-type.d.ts +2 -2
- package/types/mvc/static/server-cache-config.d.ts +30 -30
- package/types/mvc/static/server-cache.d.ts +76 -76
- package/types/mvc/static/static-handler.d.ts +77 -77
- package/types/mysql/config.d.ts +90 -90
- package/types/mysql/exception.d.ts +7 -7
- package/types/mysql/index.d.ts +16 -16
- package/types/mysql/manager/base.d.ts +165 -159
- package/types/mysql/manager/index.d.ts +36 -36
- package/types/mysql/manager/ops/count.d.ts +13 -13
- package/types/mysql/manager/ops/criteria.d.ts +134 -134
- package/types/mysql/manager/ops/delete.d.ts +46 -46
- package/types/mysql/manager/ops/exist.d.ts +6 -6
- package/types/mysql/manager/ops/find.d.ts +86 -70
- package/types/mysql/manager/ops/index.d.ts +10 -10
- package/types/mysql/manager/ops/insert.d.ts +18 -18
- package/types/mysql/manager/ops/modify.d.ts +3 -3
- package/types/mysql/manager/ops/paginate.d.ts +36 -36
- package/types/mysql/manager/ops/query.d.ts +3 -3
- package/types/mysql/manager/ops/update.d.ts +76 -76
- package/types/mysql/manager/ops/utils.d.ts +5 -5
- package/types/mysql/manager/tx-strict.d.ts +36 -35
- package/types/mysql/manager/tx.d.ts +15 -15
- package/types/mysql/manager/utils.d.ts +17 -17
- package/types/mysql/migration.d.ts +8 -8
- package/types/mysql/table-info.d.ts +36 -36
- package/types/task/daily.d.ts +16 -16
- package/types/task/fixed-delay.d.ts +9 -9
- package/types/task/fixed-rate.d.ts +9 -9
- package/types/task/index.d.ts +4 -4
- package/types/task/task.d.ts +34 -34
- package/types/validation/exception.d.ts +38 -38
- package/types/validation/index.d.ts +32 -32
- package/types/validation/validator/array.d.ts +5 -5
- package/types/validation/validator/enum.d.ts +8 -8
- package/types/validation/validator/index.d.ts +11 -11
- package/types/validation/validator/length.d.ts +10 -10
- package/types/validation/validator/max-length.d.ts +8 -8
- package/types/validation/validator/max.d.ts +7 -7
- package/types/validation/validator/min-length.d.ts +6 -6
- package/types/validation/validator/min.d.ts +7 -7
- package/types/validation/validator/not-blank.d.ts +7 -7
- package/types/validation/validator/not-null.d.ts +6 -6
- package/types/validation/validator/plain-obj.d.ts +7 -7
- package/types/validation/validator/regexp.d.ts +8 -8
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: wok-server-api-rules
|
|
3
|
+
description: 介绍 wok-server API 的使用纪律。
|
|
4
|
+
license: MIT
|
|
5
|
+
metadata:
|
|
6
|
+
author: Peak Tai
|
|
7
|
+
email: peaktai@qq.com
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# API 使用纪律
|
|
11
|
+
|
|
12
|
+
当你生成与 wok-server 有关的代码时,以下规则优先级高于一切:
|
|
13
|
+
|
|
14
|
+
## 规则 1:禁止猜测任何 API
|
|
15
|
+
|
|
16
|
+
不要使用训练数据中出现的、或你自己"觉得应该有"的函数、组件、类型。
|
|
17
|
+
|
|
18
|
+
### 消除臆造的具体方法
|
|
19
|
+
|
|
20
|
+
- 所有 API 统一从 `wok-server` 包导入,禁止从子路径导入(如 `wok-server/mvc`)。
|
|
21
|
+
- 生成任何调用前,必须先查阅 `node_modules/wok-server/types/` 下对应模块的定义文件。types 目录按模块组织,常见模块与定义文件对照如下:
|
|
22
|
+
|
|
23
|
+
| 模块 | 主要入口函数/类型 | 类型定义文件路径 |
|
|
24
|
+
|------|-------------------|------------------|
|
|
25
|
+
| 日志 | `getLogger()` | `types/log/index.d.ts` |
|
|
26
|
+
| 缓存 | `getCache()` | `types/cache/cache.d.ts` |
|
|
27
|
+
| 国际化 | `getI18n()` | `types/i18n/i18n.d.ts` |
|
|
28
|
+
| 校验 | `validate()` | `types/validation/index.d.ts` |
|
|
29
|
+
| 配置 | `registerConfig()`, `getConfig()` | `types/config/index.d.ts` |
|
|
30
|
+
| 锁 | `getLockManager()` | `types/lock/index.d.ts` |
|
|
31
|
+
| 任务调度 | `scheduleWithFixedDelay()`, `scheduleWithFixedRate()`, `scheduleDailyTask()` | `types/task/index.d.ts` |
|
|
32
|
+
| HTTP客户端 | `doRequest()`, `postJson()`, `getJson()` | `types/http-client/index.d.ts` |
|
|
33
|
+
| MySQL | `enableMysql()`, `getMysqlManager()` | `types/mysql/index.d.ts` |
|
|
34
|
+
| MongoDB | `enableMongoDB()`, `getMongoDBManager()` | `types/mongodb/index.d.ts` |
|
|
35
|
+
| MVC | `startWebServer()`, `stopWebServer()`, `createJsonHandler()`, `createUploadHandler()`, `createSseHandler()`, `restful()`, `removeServerStaticCache()` | `types/mvc/index.d.ts` |
|
|
36
|
+
|
|
37
|
+
- 代码必须严格匹配签名——函数参数名称、顺序、类型完全一致,返回值类型正确处理(如 `Promise` 需 `await`)。
|
|
38
|
+
|
|
39
|
+
### 示例
|
|
40
|
+
|
|
41
|
+
❌ 错误:`getCache().add('key', data)` —— cache 没有 `add` 方法,属于臆造。
|
|
42
|
+
|
|
43
|
+
✅ 正确:查阅 `node_modules/wok-server/types/cache/cache.d.ts` 后,使用 `getCache().put('key', data)` 并严格按签名调用。
|
|
44
|
+
|
|
45
|
+
❌ 错误:`exchange.send(data)` 或 `exchange.json(data)` —— `ServerExchange` 没有这些方法。
|
|
46
|
+
|
|
47
|
+
✅ 正确:使用 `exchange.respondJson(data)` 或 `exchange.respondText(text)` 等,详见下方 ServerExchange 速查表。
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## 规则 2:每个拦截器和每个路由 handler 都应该有单独的文件
|
|
52
|
+
|
|
53
|
+
禁止多个拦截器写在一个文件里,禁止多个接口的处理逻辑在一个文件里。
|
|
54
|
+
即使内容再少,也不允许写在一起。
|
|
55
|
+
|
|
56
|
+
路由的配置(`routers` 对象)必须在入口文件(如 `main.ts`)或独立的 router 目录中**集中管理**,不允许在业务目录中分散配置路由映射。集中配置是为了方便查找所有路由。
|
|
57
|
+
|
|
58
|
+
### 拦截器标准签名
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
import { ServerExchange } from 'wok-server'
|
|
62
|
+
|
|
63
|
+
// 每个拦截器单独一个文件,export 一个函数
|
|
64
|
+
export async function authInterceptor(
|
|
65
|
+
exchange: ServerExchange,
|
|
66
|
+
next: () => Promise<void>
|
|
67
|
+
): Promise<void> {
|
|
68
|
+
// 前置处理...
|
|
69
|
+
await next()
|
|
70
|
+
// 后置处理...
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
类型定义为:
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
interface Interceptor {
|
|
78
|
+
(exchange: ServerExchange, next: () => Promise<void>): Promise<void>
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## 规则 3:每个路由 handler 文件的参数和响应定义都应该保持在内部
|
|
85
|
+
|
|
86
|
+
每个路由的处理逻辑是独立的,不向外导出除 handler 以外的函数、组件、类型,不和别的路由共享数据。
|
|
87
|
+
|
|
88
|
+
### 可用的 Handler 工厂函数
|
|
89
|
+
|
|
90
|
+
wok-server 提供了以下 4 种 handler 工厂函数,禁止使用除此之外任何臆造的工厂函数:
|
|
91
|
+
|
|
92
|
+
| 工厂函数 | 用途 | 请求格式 | 响应格式 |
|
|
93
|
+
|----------|------|----------|----------|
|
|
94
|
+
| `createJsonHandler` | JSON 请求/响应 | POST,JSON body | JSON |
|
|
95
|
+
| `createUploadHandler` | 二进制文件上传 | POST,binary body | JSON |
|
|
96
|
+
| `createSseHandler` | Server-Sent Events 推送 | GET | SSE 事件流 |
|
|
97
|
+
| `restful` | 按 HTTP 方法分发 | 任意 | 由内层 handler 决定 |
|
|
98
|
+
|
|
99
|
+
#### createJsonHandler 示例
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
// create-user.ts
|
|
103
|
+
import { createJsonHandler, notBlank, length, min, max, notNull } from 'wok-server'
|
|
104
|
+
|
|
105
|
+
interface Form {
|
|
106
|
+
name: string
|
|
107
|
+
age: number
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
interface Resp {
|
|
111
|
+
id: string
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export const createUserHandler = createJsonHandler<Form, Resp>({
|
|
115
|
+
validation: {
|
|
116
|
+
name: [notBlank(), length({ min: 2, max: 16 })],
|
|
117
|
+
age: [notNull(), min(1), max(150)]
|
|
118
|
+
},
|
|
119
|
+
// 可选:缓存支持
|
|
120
|
+
async cache(body) {
|
|
121
|
+
return { key: `user-${body.name}`, expiresInSeconds: 60 }
|
|
122
|
+
},
|
|
123
|
+
async handle(body) {
|
|
124
|
+
const newUser = await createUser(body)
|
|
125
|
+
return { id: newUser.id }
|
|
126
|
+
}
|
|
127
|
+
})
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
命名约定:请求数据类型推荐命名为 `Form`,响应数据类型推荐命名为 `Resp`。
|
|
131
|
+
由于这两个数据类型是保持在文件内部的,所以不同的 handler 文件可以使用这两个名称,不会冲突,
|
|
132
|
+
这也是推荐的方式。如果每个具体的业务,根据场景命名也是可以的,如 CreateUserForm、CreateUserResp,
|
|
133
|
+
这样更严谨,查询可能更方便,但是开发效率会稍低。
|
|
134
|
+
|
|
135
|
+
#### createUploadHandler 示例
|
|
136
|
+
|
|
137
|
+
上传请求正文是文件二进制内容,额外参数通过 QueryString 传递。请求体类型是 `Buffer`,不需要定义 Form。
|
|
138
|
+
|
|
139
|
+
```ts
|
|
140
|
+
// upload-avatar.ts
|
|
141
|
+
import { createUploadHandler, validate, notBlank } from 'wok-server'
|
|
142
|
+
|
|
143
|
+
interface Resp {
|
|
144
|
+
url: string
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export const uploadAvatarHandler = createUploadHandler<Resp>({
|
|
148
|
+
async handle(body, exchange) {
|
|
149
|
+
const userId = exchange.query.getStr('userId')
|
|
150
|
+
validate({ userId }, { userId: [notBlank()] })
|
|
151
|
+
// body 就是文件的 Buffer,可直接使用
|
|
152
|
+
const key = `avatars/${userId}`
|
|
153
|
+
await oss.putObject(key, body)
|
|
154
|
+
return { url: oss.getUrl(key) }
|
|
155
|
+
}
|
|
156
|
+
})
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
#### createSseHandler 示例
|
|
160
|
+
|
|
161
|
+
SSE handler 没有请求/响应数据类型,只有 `SseContext`。
|
|
162
|
+
|
|
163
|
+
```ts
|
|
164
|
+
// sse-notify.ts
|
|
165
|
+
import { createSseHandler } from 'wok-server'
|
|
166
|
+
|
|
167
|
+
export const notifyHandler = createSseHandler({
|
|
168
|
+
async handle(ctx) {
|
|
169
|
+
// ctx.send(data, event?, id?) 发送事件
|
|
170
|
+
// ctx.close() 关闭连接
|
|
171
|
+
ctx.send({ message: '连接成功' }, 'connected')
|
|
172
|
+
// ... 业务逻辑
|
|
173
|
+
ctx.close()
|
|
174
|
+
}
|
|
175
|
+
})
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
#### restful 示例
|
|
179
|
+
|
|
180
|
+
```ts
|
|
181
|
+
// user-router.ts
|
|
182
|
+
import { restful } from 'wok-server'
|
|
183
|
+
import { createUserHandler } from './create-user'
|
|
184
|
+
import { getUserHandler } from './get-user'
|
|
185
|
+
|
|
186
|
+
export const userRouter = restful({
|
|
187
|
+
get: getUserHandler,
|
|
188
|
+
post: createUserHandler
|
|
189
|
+
})
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## 规则 4:业务错误应抛出异常,由全局异常拦截器统一处理
|
|
195
|
+
|
|
196
|
+
推荐的处理模式:
|
|
197
|
+
1. 定义 `BusinessException` 自定义业务异常类
|
|
198
|
+
2. 创建 `globalErrorInterceptor` 放在拦截器链**第一位**
|
|
199
|
+
3. Handler 中遇到业务错误,抛出异常来中止处理流程
|
|
200
|
+
|
|
201
|
+
```ts
|
|
202
|
+
// exception.ts —— 全局异常定义文件
|
|
203
|
+
import { ServerExchange, ValidationException } from 'wok-server'
|
|
204
|
+
|
|
205
|
+
export class BusinessException {
|
|
206
|
+
constructor(
|
|
207
|
+
readonly message: string,
|
|
208
|
+
readonly status?: number
|
|
209
|
+
) {}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export async function globalErrorInterceptor(
|
|
213
|
+
exchange: ServerExchange,
|
|
214
|
+
next: () => Promise<void>
|
|
215
|
+
): Promise<void> {
|
|
216
|
+
try {
|
|
217
|
+
await next()
|
|
218
|
+
} catch (e) {
|
|
219
|
+
if (e instanceof BusinessException) {
|
|
220
|
+
exchange.respondErrMsg(e.message, e.status ?? 400)
|
|
221
|
+
return
|
|
222
|
+
}
|
|
223
|
+
if (e instanceof ValidationException) {
|
|
224
|
+
exchange.respondErrMsg(`${e.propertyPath}:${e.errMsg}`, 400)
|
|
225
|
+
return
|
|
226
|
+
}
|
|
227
|
+
throw e
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
```ts
|
|
233
|
+
// main.ts 入口文件,将错误拦截器放在第一位
|
|
234
|
+
import { startWebServer } from 'wok-server'
|
|
235
|
+
import { globalErrorInterceptor } from './exception'
|
|
236
|
+
|
|
237
|
+
await startWebServer({
|
|
238
|
+
interceptors: [globalErrorInterceptor /* , 其他拦截器 */],
|
|
239
|
+
routers: { /* ... */ }
|
|
240
|
+
})
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## 附录 A:ServerExchange 速查表
|
|
246
|
+
|
|
247
|
+
所有路由 handler 和拦截器都通过 `ServerExchange` 与请求/响应交互。以下是其完整方法列表,禁止使用表中未列出的方法。
|
|
248
|
+
|
|
249
|
+
### 读取请求
|
|
250
|
+
|
|
251
|
+
| 方法/属性 | 返回类型 | 说明 |
|
|
252
|
+
|-----------|----------|------|
|
|
253
|
+
| `exchange.request` | `IncomingMessage` | Node.js 原生请求对象 |
|
|
254
|
+
| `exchange.response` | `ServerResponse` | Node.js 原生响应对象 |
|
|
255
|
+
| `await exchange.bodyJson<T>()` | `Promise<T>` | 读取 JSON 请求体(空体返回 `{}`) |
|
|
256
|
+
| `await exchange.bodyBuffer()` | `Promise<Buffer>` | 读取二进制请求体 |
|
|
257
|
+
| `await exchange.bodyText()` | `Promise<string>` | 读取文本请求体 |
|
|
258
|
+
| `exchange.parseQueryString()` | `QueryString` | 解析 URL 查询字符串 |
|
|
259
|
+
|
|
260
|
+
> **注意**:如果使用了第三方库读取 request 内容,则不能再调用 `bodyXxx` 系列方法,反之亦然。但 `bodyXxx` 系列方法之间可以重复调用。
|
|
261
|
+
|
|
262
|
+
### 响应
|
|
263
|
+
|
|
264
|
+
| 方法 | 说明 |
|
|
265
|
+
|------|------|
|
|
266
|
+
| `exchange.respondJson(json, status?)` | 响应 JSON,默认 status 200 |
|
|
267
|
+
| `exchange.respondErrMsg(message, status?)` | 响应统一错误格式 `{ message: "..." }`,默认 status 400 |
|
|
268
|
+
| `exchange.respondText(text, status?)` | 响应纯文本,默认 status 200 |
|
|
269
|
+
| `exchange.respondFile(filePath, download?)` | 响应文件,`download=true` 触发下载 |
|
|
270
|
+
| `exchange.respondHtml(html, status?)` | 响应 HTML |
|
|
271
|
+
| `exchange.respond({ statusCode, body?, headers? })` | 底层通用响应 |
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## 附录 B:startWebServer 完整配置
|
|
276
|
+
|
|
277
|
+
```ts
|
|
278
|
+
import { startWebServer } from 'wok-server'
|
|
279
|
+
|
|
280
|
+
await startWebServer({
|
|
281
|
+
// 必填:路由配置,键为路径,值为 RouterHandler
|
|
282
|
+
// 路径仅支持明确地址,不支持动态参数(如 /users/:id)和通配符
|
|
283
|
+
// '*' 为特殊路径,用于兜底处理 404
|
|
284
|
+
routers: {
|
|
285
|
+
'/user/create': createUserHandler,
|
|
286
|
+
'/user/delete': deleteUserHandler,
|
|
287
|
+
'/sse/notify': notifyHandler,
|
|
288
|
+
'*': notFoundHandler
|
|
289
|
+
},
|
|
290
|
+
// 可选:拦截器链,按数组顺序执行
|
|
291
|
+
interceptors: [globalErrorInterceptor, authInterceptor],
|
|
292
|
+
// 可选:前置处理,可整合 socket.io 等原生 http 组件
|
|
293
|
+
preHandler: async (server) => {
|
|
294
|
+
// const io = new Server(server)
|
|
295
|
+
},
|
|
296
|
+
// 可选:静态文件服务配置
|
|
297
|
+
static: {
|
|
298
|
+
'/': { dir: 'fe', cacheAge: 600 }
|
|
299
|
+
}
|
|
300
|
+
})
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
## 附录 C:内置校验器列表
|
|
306
|
+
|
|
307
|
+
以下校验器从 `wok-server` 导入,禁止臆造不存在的校验器:
|
|
308
|
+
|
|
309
|
+
| 函数 | 作用 |
|
|
310
|
+
|------|------|
|
|
311
|
+
| `notNull()` | 非空校验(不能是 null/undefined) |
|
|
312
|
+
| `notBlank()` | 字符串非空校验(不能是 null/undefined/空白字符串) |
|
|
313
|
+
| `min(n)` | 数字最小值 |
|
|
314
|
+
| `max(n)` | 数字最大值 |
|
|
315
|
+
| `length({ min?, max? })` | 字符串/数组长度范围 |
|
|
316
|
+
| `maxLength(n)` | 字符串/数组最大长度 |
|
|
317
|
+
| `minLength(n)` | 字符串/数组最小长度 |
|
|
318
|
+
| `regexp(re)` | 正则校验 |
|
|
319
|
+
| `enumerate(list)` | 枚举校验,值必须在指定列表中 |
|
|
320
|
+
| `array(validators)` | 数组元素校验 |
|
|
321
|
+
| `plainObject(opts)` | 嵌套对象校验 |
|
|
322
|
+
|
|
323
|
+
所有内置校验器已支持国际化,自动根据请求头 `accept-language` 切换提示语言。
|
|
324
|
+
|
|
325
|
+
---
|
|
326
|
+
|
|
327
|
+
## 附录 D:目录结构参考
|
|
328
|
+
|
|
329
|
+
```
|
|
330
|
+
src/
|
|
331
|
+
├── exception.ts # 全局异常定义 + 错误拦截器
|
|
332
|
+
├── main.ts # 入口:启动服务、集中配置路由
|
|
333
|
+
├── auth/ # 授权模块
|
|
334
|
+
│ ├── auth-interceptor.ts
|
|
335
|
+
│ ├── create-auth.ts
|
|
336
|
+
│ └── index.ts
|
|
337
|
+
├── user/ # 用户模块
|
|
338
|
+
│ ├── user.ts # 实体配置(mysql/mongo 等)
|
|
339
|
+
│ ├── create-user.ts # POST /user/create
|
|
340
|
+
│ ├── update-user.ts # POST /user/update
|
|
341
|
+
│ └── index.ts
|
|
342
|
+
└── tag/ # 标签模块
|
|
343
|
+
├── tag.ts
|
|
344
|
+
├── create-tag.ts
|
|
345
|
+
└── index.ts
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
- 目录按业务功能划分,而非按技术层(service/controller)划分。
|
|
349
|
+
- 路由配置集中在 `main.ts` 或独立 `router/` 目录中。
|
|
350
|
+
- 每个 handler 和 interceptor 都是单独文件。
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: wok-server-cache
|
|
3
|
+
description: wok-server 缓存组件使用指南,提供内存缓存功能,支持过期时间、随机淘汰策略和统计信息。
|
|
4
|
+
license: MIT
|
|
5
|
+
metadata:
|
|
6
|
+
author: Peak Tai
|
|
7
|
+
email: peaktai@qq.com
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# wok-server 缓存组件
|
|
11
|
+
|
|
12
|
+
## 概述
|
|
13
|
+
|
|
14
|
+
缓存组件提供基于内存的简单缓存,采用**随机淘汰**驱逐策略,支持过期时间。适合缓存少量短期数据。
|
|
15
|
+
|
|
16
|
+
如需大量数据缓存或避免影响 GC,应考虑外部方案(Redis 等)或堆外内存(Buffer)。
|
|
17
|
+
|
|
18
|
+
## 源码与类型定义
|
|
19
|
+
|
|
20
|
+
安装 `wok-server` 后,可通过以下路径查看源码与类型定义:
|
|
21
|
+
|
|
22
|
+
- 源码目录:`node_modules/wok-server/src/cache/`
|
|
23
|
+
- 类型定义:`node_modules/wok-server/types/` (引用 cache 组件的 `.d.ts` 文件)
|
|
24
|
+
|
|
25
|
+
核心源码文件:
|
|
26
|
+
|
|
27
|
+
| 文件 | 说明 |
|
|
28
|
+
| :---------------- | :----------------------------- |
|
|
29
|
+
| `cache.ts` | Cache 类,核心缓存逻辑 |
|
|
30
|
+
| `config.ts` | 缓存配置,环境变量映射 |
|
|
31
|
+
| `purge-task.ts` | 清理任务,删除过期和多余数据 |
|
|
32
|
+
| `stat.ts` | 命中率统计 |
|
|
33
|
+
| `index.ts` | 模块入口,导出 `getCache` 函数 |
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## 获取缓存实例
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
import { getCache } from 'wok-server'
|
|
41
|
+
const cache = getCache()
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
`getCache()` 返回全局单例的 `Cache` 实例,模块加载时即完成初始化并启动后台清理任务。
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## 环境变量
|
|
49
|
+
|
|
50
|
+
| 环境变量 | 说明 | 默认值 |
|
|
51
|
+
| :------------------------------ | :--------------------------- | :----- |
|
|
52
|
+
| `CACHE_DEFAULT_EXPIRE_IN_SECONDS` | 默认过期时间(秒),1-3600 | 60 |
|
|
53
|
+
| `CACHE_STAT_TASK_ENABLED` | 是否启用统计任务 | false |
|
|
54
|
+
| `CACHE_STAT_INTERVAL` | 统计周期(秒),1-86400 | 300 |
|
|
55
|
+
| `CACHE_CLEANING_INTERVAL` | 清理间隔(秒),1-3600 | 60 |
|
|
56
|
+
| `CACHE_MAX_ELEMENTS` | 最大元素数,1-Number.MAX_VALUE | 1024 |
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## 基本操作
|
|
61
|
+
|
|
62
|
+
### put — 写入缓存
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
cache.put(key: string, val: any, expiresInSeconds?: number): void
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
- `key`:缓存键
|
|
69
|
+
- `val`:缓存值,任意类型
|
|
70
|
+
- `expiresInSeconds`:过期时间(秒),可选,不传则使用 `CACHE_DEFAULT_EXPIRE_IN_SECONDS` 的默认值(默认 60 秒)
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
cache.put('abc', 123) // 默认 60 秒过期
|
|
74
|
+
cache.put('d', 2233, 1) // 1 秒后过期
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### get — 读取缓存
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
cache.get<T>(key: string): T | undefined
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
- 命中返回缓存值,过期或不存在返回 `undefined`
|
|
84
|
+
- 读取时会检查过期时间,已过期则自动删除并返回 `undefined`
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
const value = cache.get<number>('abc') // 123 或 undefined
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### remove — 删除缓存
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
cache.remove(key: string): void
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
cache.remove('abc')
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### clear — 清空全部缓存
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
cache.clear(): void
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
清空所有缓存数据,同时重置统计信息。
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## computeIfAbsent — 不存在则计算
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
cache.computeIfAbsent<T>(
|
|
114
|
+
key: string,
|
|
115
|
+
provider: () => Promise<T> | T,
|
|
116
|
+
expiresInSeconds?: number
|
|
117
|
+
): Promise<T>
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
如果 `key` 对应的缓存存在且未过期,直接返回缓存值;否则调用 `provider` 计算值,写入缓存并返回。
|
|
121
|
+
|
|
122
|
+
**并发安全**:相同 `key` 的并发调用只会触发一次 `provider` 执行,其他调用复用同一个 Promise 结果。
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
const user = await cache.computeIfAbsent(
|
|
126
|
+
`get-user-${userId}`,
|
|
127
|
+
() => findUserById(userId),
|
|
128
|
+
120 // 可选,过期时间秒
|
|
129
|
+
)
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## 驱逐与清理
|
|
135
|
+
|
|
136
|
+
### 清理任务
|
|
137
|
+
|
|
138
|
+
模块加载时自动启动清理任务,按 `CACHE_CLEANING_INTERVAL` 的周期执行,完成两件事:
|
|
139
|
+
|
|
140
|
+
1. **删除过期数据**:遍历并删除 `expireAt < now` 的记录
|
|
141
|
+
2. **驱逐多余记录**:如果清理后元素数仍超过 `CACHE_MAX_ELEMENTS`,从头开始删除多余条目
|
|
142
|
+
|
|
143
|
+
驱逐策略为**随机淘汰**(因 Map 的 key 顺序不保证,等同于随机),不支持设置其他驱逐策略。
|
|
144
|
+
|
|
145
|
+
### 统计任务
|
|
146
|
+
|
|
147
|
+
当 `CACHE_STAT_TASK_ENABLED=true` 时,按 `CACHE_STAT_INTERVAL` 周期输出统计日志:
|
|
148
|
+
|
|
149
|
+
```
|
|
150
|
+
[2023/09/27 11:31:35.690][INFO]Cache statistics,time window :2023/09/27 11:31:35.442 - now, hit :4/4,capacity:120/100
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
统计包含:
|
|
154
|
+
- **time window**:统计周期时间窗口
|
|
155
|
+
- **hit**:命中次数 / 总 get 次数
|
|
156
|
+
- **capacity**:当前元素数 / 最大容量
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## 内部实现要点
|
|
161
|
+
|
|
162
|
+
### Cache 类 (`cache.ts`)
|
|
163
|
+
|
|
164
|
+
```ts
|
|
165
|
+
export class Cache {
|
|
166
|
+
private promiseMap = new Map<string, Promise<any>>()
|
|
167
|
+
|
|
168
|
+
constructor(
|
|
169
|
+
private readonly valueMap: Map<string, CacheContent>,
|
|
170
|
+
private readonly stat?: CacheStat
|
|
171
|
+
) {}
|
|
172
|
+
// put / get / remove / clear / computeIfAbsent ...
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
- 底层是 `Map<string, CacheContent>`,`CacheContent` 包含 `val`(值)和 `expireAt`(过期时间戳)
|
|
177
|
+
- `promiseMap` 用于 `computeIfAbsent` 的并发去重
|
|
178
|
+
|
|
179
|
+
### PurgeTask (`purge-task.ts`)
|
|
180
|
+
|
|
181
|
+
实现 `Task` 接口,`run()` 方法中遍历 Map 删除过期条目,超出容量限制则从 Map 头部开始驱逐。
|
|
182
|
+
|
|
183
|
+
### CacheStat (`stat.ts`)
|
|
184
|
+
|
|
185
|
+
记录 `totalGet` 和 `totalHit`,`log()` 输出统计信息到日志,`clear()` 重置统计窗口。
|
|
186
|
+
|
|
187
|
+
### 模块初始化 (`index.ts`)
|
|
188
|
+
|
|
189
|
+
```ts
|
|
190
|
+
const valueMap = new Map<string, any>()
|
|
191
|
+
const stat = config.statTaskEnabled ? new CacheStat(valueMap) : undefined
|
|
192
|
+
const cache = new Cache(valueMap, stat)
|
|
193
|
+
|
|
194
|
+
scheduleWithFixedDelay(config.cleaningInterval, config.cleaningInterval, new PurgeTask(valueMap))
|
|
195
|
+
|
|
196
|
+
if (config.statTaskEnabled) {
|
|
197
|
+
scheduleWithFixedDelay(config.statInterval, config.statInterval, {
|
|
198
|
+
name: 'Cache statistics',
|
|
199
|
+
async run() { stat?.log(); stat?.clear() }
|
|
200
|
+
})
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export function getCache() { return cache }
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
模块加载即完成:创建 Map → 创建 Cache 实例 → 启动清理定时任务 → 可选启动统计任务。`getCache()` 返回的始终是同一个实例。
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## 性能注意事项
|
|
211
|
+
|
|
212
|
+
- 缓存数据过多会影响 GC:回收器无法回收被缓存的对象,但标记和整理工作仍有大量消耗
|
|
213
|
+
- 建议将 `CACHE_CLEANING_INTERVAL` 设置得小一些,及时清理无效数据
|
|
214
|
+
- 缓存记录时尽可能将过期时间设置得短一些
|
|
215
|
+
- 谨慎评估 `CACHE_MAX_ELEMENTS`,根据服务器内存合理设置
|
|
216
|
+
- 大量数据缓存场景应使用外部缓存服务(Redis 等)
|