@hile/core 1.0.8 → 1.0.9
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.md +30 -0
- package/SKILL.md +35 -2
- package/dist/index.d.ts +9 -1
- package/dist/index.js +12 -3
- package/package.json +4 -3
- package/skill.json +16 -0
package/README.md
CHANGED
|
@@ -122,6 +122,34 @@ export const connectionService = defineService(async (shutdown) => {
|
|
|
122
122
|
|
|
123
123
|
> **注意:** 请使用 `async` 函数定义服务。同步函数中直接 `throw` 的错误无法触发销毁机制。
|
|
124
124
|
|
|
125
|
+
### 手动销毁(Graceful Shutdown)
|
|
126
|
+
|
|
127
|
+
调用 `container.shutdown()` 可手动触发所有已注册服务的销毁回调,适用于进程退出时优雅关闭资源:
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
import container from '@hile/core'
|
|
131
|
+
|
|
132
|
+
process.on('SIGTERM', async () => {
|
|
133
|
+
await container.shutdown()
|
|
134
|
+
process.exit(0)
|
|
135
|
+
})
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
销毁按 **服务注册逆序** 执行:后注册的服务先销毁。调用后销毁队列清空,重复调用不会再次执行。
|
|
139
|
+
|
|
140
|
+
### 服务校验(isService)
|
|
141
|
+
|
|
142
|
+
使用 `isService` 判断一个对象是否为合法的服务注册信息。内部通过不可伪造的 Symbol 标识校验,确保只有通过 `defineService` / `container.register` 创建的对象才会返回 `true`:
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
import { defineService, isService } from '@hile/core'
|
|
146
|
+
|
|
147
|
+
const myService = defineService(async (shutdown) => 'hello')
|
|
148
|
+
|
|
149
|
+
isService(myService) // true
|
|
150
|
+
isService({ id: 1, fn: () => {} } as any) // false
|
|
151
|
+
```
|
|
152
|
+
|
|
125
153
|
## 隔离容器
|
|
126
154
|
|
|
127
155
|
除默认容器外,可以创建独立的 `Container` 实例,实现服务作用域隔离:
|
|
@@ -146,6 +174,7 @@ const result = await container.resolve(service)
|
|
|
146
174
|
|------|------|
|
|
147
175
|
| `defineService(fn)` | 注册服务到默认容器,返回 `ServiceRegisterProps` |
|
|
148
176
|
| `loadService(props)` | 从默认容器加载服务,返回 `Promise<R>` |
|
|
177
|
+
| `isService(props)` | 判断对象是否为合法的服务注册信息(通过内部 Symbol 校验) |
|
|
149
178
|
|
|
150
179
|
### Container
|
|
151
180
|
|
|
@@ -157,6 +186,7 @@ const result = await container.resolve(service)
|
|
|
157
186
|
| `hasMeta(id)` | 检查服务是否已运行(存在运行时元数据) |
|
|
158
187
|
| `getIdByService(fn)` | 根据函数引用获取服务 ID |
|
|
159
188
|
| `getMetaById(id)` | 根据服务 ID 获取运行时元数据 |
|
|
189
|
+
| `shutdown()` | 手动销毁所有服务,返回 `Promise<void>`。按服务注册逆序执行所有销毁回调 |
|
|
160
190
|
|
|
161
191
|
### 服务状态
|
|
162
192
|
|
package/SKILL.md
CHANGED
|
@@ -30,10 +30,14 @@ type ServiceCutDownHandler = (fn: ServiceCutDownFunction) => void;
|
|
|
30
30
|
// 服务函数:第一个参数固定为销毁注册器,返回值为同步值或 Promise
|
|
31
31
|
type ServiceFunction<R> = (shutdown: ServiceCutDownHandler) => R | Promise<R>;
|
|
32
32
|
|
|
33
|
+
// 内部服务标识(Symbol,不可外部构造)
|
|
34
|
+
const sericeFlag: unique symbol;
|
|
35
|
+
|
|
33
36
|
// 服务注册信息:由 defineService/register 返回,作为 loadService/resolve 的入参
|
|
34
37
|
interface ServiceRegisterProps<R> {
|
|
35
38
|
id: number;
|
|
36
39
|
fn: ServiceFunction<R>;
|
|
40
|
+
flag: typeof sericeFlag;
|
|
37
41
|
}
|
|
38
42
|
```
|
|
39
43
|
|
|
@@ -135,6 +139,27 @@ export const connectionService = defineService(async (shutdown) => {
|
|
|
135
139
|
- 销毁函数可以是 `async`,容器会依次 `await`
|
|
136
140
|
- 同一个函数引用多次传给 `shutdown()` 只会注册一次
|
|
137
141
|
|
|
142
|
+
### 3.5 手动销毁所有服务
|
|
143
|
+
|
|
144
|
+
在应用退出或需要优雅关闭时,调用 `container.shutdown()` 手动触发所有已注册的销毁回调:
|
|
145
|
+
|
|
146
|
+
**模板:**
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
import container from '@hile/core'
|
|
150
|
+
|
|
151
|
+
process.on('SIGTERM', async () => {
|
|
152
|
+
await container.shutdown()
|
|
153
|
+
process.exit(0)
|
|
154
|
+
})
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
**规则:**
|
|
158
|
+
- `shutdown()` 返回 `Promise`,**必须** `await`
|
|
159
|
+
- 销毁按 **服务注册逆序** 执行:后注册的服务先销毁
|
|
160
|
+
- 每个服务内部的销毁回调同样按 **逆序(LIFO)** 执行
|
|
161
|
+
- `shutdown()` 执行完毕后,再次调用不会重复执行(销毁队列已被清空)
|
|
162
|
+
|
|
138
163
|
---
|
|
139
164
|
|
|
140
165
|
## 4. 强制规则(生成代码时必须遵守)
|
|
@@ -145,7 +170,7 @@ export const connectionService = defineService(async (shutdown) => {
|
|
|
145
170
|
| 2 | 服务函数第一个参数**必须**是 `shutdown` | 这是容器注入的销毁注册器,即使不使用也要声明 |
|
|
146
171
|
| 3 | `defineService` 的结果**必须**赋给模块级 `export const` | 服务基于函数引用去重,引用必须稳定 |
|
|
147
172
|
| 4 | **不要**在 `defineService` 内直接写匿名函数再传给另一个函数 | 每次调用会创建新引用,导致重复注册 |
|
|
148
|
-
| 5 | **不要**手动构造 `ServiceRegisterProps` 对象 | 必须通过 `defineService` 或 `container.register`
|
|
173
|
+
| 5 | **不要**手动构造 `ServiceRegisterProps` 对象 | 必须通过 `defineService` 或 `container.register` 获取,内部 `flag` 为不可伪造的 Symbol |
|
|
149
174
|
| 6 | **不要**缓存 `loadService` 的结果到模块顶层变量 | 服务可能尚未初始化,应在需要时 `await loadService()` |
|
|
150
175
|
| 7 | 每个外部资源初始化后**立即**注册 `shutdown` | 确保初始化中途失败时已创建的资源能被正确清理 |
|
|
151
176
|
| 8 | 一个文件只定义一个服务 | 保持服务职责单一、依赖清晰 |
|
|
@@ -338,6 +363,7 @@ export const goodService = defineService(async (shutdown) => {
|
|
|
338
363
|
|------|------|------|
|
|
339
364
|
| `defineService` | `<R>(fn: ServiceFunction<R>) => ServiceRegisterProps<R>` | 注册服务,返回注册信息 |
|
|
340
365
|
| `loadService` | `<R>(props: ServiceRegisterProps<R>) => Promise<R>` | 加载服务,返回服务实例 |
|
|
366
|
+
| `isService` | `<R>(props: ServiceRegisterProps<R>) => boolean` | 判断对象是否为合法的服务注册信息(通过内部 Symbol 校验) |
|
|
341
367
|
|
|
342
368
|
### Container 类(用于创建隔离容器)
|
|
343
369
|
|
|
@@ -349,6 +375,7 @@ export const goodService = defineService(async (shutdown) => {
|
|
|
349
375
|
| `hasMeta` | `(id: number) => boolean` | 检查服务是否已运行过 |
|
|
350
376
|
| `getIdByService` | `<R>(fn: ServiceFunction<R>) => number \| undefined` | 根据函数引用查 ID |
|
|
351
377
|
| `getMetaById` | `(id: number) => Paddings \| undefined` | 根据 ID 查运行时元数据 |
|
|
378
|
+
| `shutdown` | `() => Promise<void>` | 手动销毁所有服务,按服务注册逆序执行所有销毁回调 |
|
|
352
379
|
|
|
353
380
|
### resolve 状态机
|
|
354
381
|
|
|
@@ -394,7 +421,13 @@ resolve(props)
|
|
|
394
421
|
|
|
395
422
|
- **单个服务内**:销毁回调按注册的逆序(LIFO)依次 `await` 执行
|
|
396
423
|
- **全局销毁**:按服务注册顺序的逆序依次销毁
|
|
397
|
-
-
|
|
424
|
+
- **触发时机**:
|
|
425
|
+
- 服务函数异步失败(reject)时自动触发该服务的销毁回调
|
|
426
|
+
- 手动调用 `container.shutdown()` 时触发所有已注册服务的销毁回调(按服务注册逆序)
|
|
427
|
+
|
|
428
|
+
### 服务标识机制(sericeFlag)
|
|
429
|
+
|
|
430
|
+
容器内部使用 `const sericeFlag = Symbol('service')` 作为服务注册信息的标识。`register` 返回的对象会携带 `flag: sericeFlag` 字段。`isService()` 通过检查 `flag === sericeFlag` 以及 `id` 和 `fn` 的类型来判断一个对象是否为合法的服务注册信息。由于 Symbol 不可伪造,外部无法手动构造通过 `isService` 校验的对象。
|
|
398
431
|
|
|
399
432
|
### 函数去重机制
|
|
400
433
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
export type ServiceCutDownFunction = () => unknown | Promise<unknown>;
|
|
2
2
|
export type ServiceCutDownHandler = (fn: ServiceCutDownFunction) => void;
|
|
3
3
|
export type ServiceFunction<R> = (fn: ServiceCutDownHandler) => R | Promise<R>;
|
|
4
|
+
declare const sericeFlag: unique symbol;
|
|
4
5
|
export interface ServiceRegisterProps<R> {
|
|
5
6
|
id: number;
|
|
6
7
|
fn: ServiceFunction<R>;
|
|
8
|
+
flag: typeof sericeFlag;
|
|
7
9
|
}
|
|
8
10
|
interface Paddings<R = any> {
|
|
9
11
|
status: -1 | 0 | 1;
|
|
@@ -63,7 +65,7 @@ export declare class Container {
|
|
|
63
65
|
* 先注册的后销毁,后注册的先销毁
|
|
64
66
|
* @returns - 销毁结果
|
|
65
67
|
*/
|
|
66
|
-
|
|
68
|
+
shutdown(): Promise<void>;
|
|
67
69
|
/**
|
|
68
70
|
* 检查服务是否已注册
|
|
69
71
|
* @param fn - 服务函数
|
|
@@ -92,4 +94,10 @@ export declare class Container {
|
|
|
92
94
|
export declare const container: Container;
|
|
93
95
|
export declare function defineService<R>(fn: ServiceFunction<R>): ServiceRegisterProps<R>;
|
|
94
96
|
export declare function loadService<R>(props: ServiceRegisterProps<R>): Promise<R>;
|
|
97
|
+
/**
|
|
98
|
+
* 判断是否为服务
|
|
99
|
+
* @param props - 服务注册信息
|
|
100
|
+
* @returns - 是否为服务
|
|
101
|
+
*/
|
|
102
|
+
export declare function isService<R>(props: ServiceRegisterProps<R>): boolean;
|
|
95
103
|
export default container;
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const sericeFlag = Symbol('service');
|
|
1
2
|
export class Container {
|
|
2
3
|
id = 1;
|
|
3
4
|
packages = new Map();
|
|
@@ -18,11 +19,11 @@ export class Container {
|
|
|
18
19
|
*/
|
|
19
20
|
register(fn) {
|
|
20
21
|
if (this.packages.has(fn)) {
|
|
21
|
-
return { id: this.packages.get(fn), fn };
|
|
22
|
+
return { id: this.packages.get(fn), fn, flag: sericeFlag };
|
|
22
23
|
}
|
|
23
24
|
const id = this.getId();
|
|
24
25
|
this.packages.set(fn, id);
|
|
25
|
-
return { id, fn };
|
|
26
|
+
return { id, fn, flag: sericeFlag };
|
|
26
27
|
}
|
|
27
28
|
/**
|
|
28
29
|
* 从容器中解决服务
|
|
@@ -126,7 +127,7 @@ export class Container {
|
|
|
126
127
|
while (i--) {
|
|
127
128
|
await Promise.resolve(pools[i]());
|
|
128
129
|
}
|
|
129
|
-
this.shutdownFunctions.
|
|
130
|
+
this.shutdownFunctions.delete(id);
|
|
130
131
|
this.shutdownQueues.splice(this.shutdownQueues.indexOf(id), 1);
|
|
131
132
|
}
|
|
132
133
|
}
|
|
@@ -184,4 +185,12 @@ export function defineService(fn) {
|
|
|
184
185
|
export function loadService(props) {
|
|
185
186
|
return container.resolve(props);
|
|
186
187
|
}
|
|
188
|
+
/**
|
|
189
|
+
* 判断是否为服务
|
|
190
|
+
* @param props - 服务注册信息
|
|
191
|
+
* @returns - 是否为服务
|
|
192
|
+
*/
|
|
193
|
+
export function isService(props) {
|
|
194
|
+
return props.flag === sericeFlag && typeof props.id === 'number' && typeof props.fn === 'function';
|
|
195
|
+
}
|
|
187
196
|
export default container;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hile/core",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.9",
|
|
4
4
|
"description": "Hile core - lightweight async service container",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
"files": [
|
|
14
14
|
"dist",
|
|
15
15
|
"README.md",
|
|
16
|
-
"SKILL.md"
|
|
16
|
+
"SKILL.md",
|
|
17
|
+
"skill.json"
|
|
17
18
|
],
|
|
18
19
|
"author": "",
|
|
19
20
|
"license": "MIT",
|
|
@@ -24,5 +25,5 @@
|
|
|
24
25
|
"@types/node": "^25.3.1",
|
|
25
26
|
"vitest": "^4.0.18"
|
|
26
27
|
},
|
|
27
|
-
"gitHead": "
|
|
28
|
+
"gitHead": "315d22b9f3c2a21f40938bbefe422d100fca2cee"
|
|
28
29
|
}
|
package/skill.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hile/core",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Hile core - lightweight async service container",
|
|
5
|
+
"repository": "https://github.com/cevio/hile/tree/main/packages/core",
|
|
6
|
+
"skills": [
|
|
7
|
+
{
|
|
8
|
+
"id": "core",
|
|
9
|
+
"name": "Hile应用核心优化指南",
|
|
10
|
+
"description": "提供 Hile 开发者使用核心包开发 Hile 应用的指南",
|
|
11
|
+
"path": "SKILL.md"
|
|
12
|
+
}
|
|
13
|
+
],
|
|
14
|
+
"authors": ["evio"],
|
|
15
|
+
"license": "MIT"
|
|
16
|
+
}
|