@cjwddz/service-manager
v0.0.1
Published
A service management framework for Node.js applications with daemon support
Maintainers
Readme
@cjwddz/service-manager
一个支持守护进程的 Node.js 服务管理框架。
特性
- 🚀 易于使用:只需实现
start()方法 - 🔄 生命周期钩子:
beforeStart、afterStart、beforeStop、beforeRestart、afterRestart、onUpdateAvailable - 📊 自动状态检查:框架自动提供状态和健康检查
- 🛠️ CLI 命令:
start、stop、restart、status - 🔒 进程管理:PID 文件管理、优雅关闭
- 🔁 自动重启:可配置的自动重启,支持重启限制和退避策略
- 🔄 自动更新检查:自动检查更新,支持自定义检查逻辑
- 📝 日志管理:自动日志文件管理
安装
npm install @cjwddz/service-manager快速开始
最小示例
// src/index.ts
import { createService } from '@cjwddz/service-manager';
import { Hono } from 'hono';
import { serve } from '@hono/node-server';
const app = new Hono();
app.get('/', (c) => c.json({ message: 'Hello' }));
// 只需调用 createService(),框架自动处理一切:
// - 守护进程模式检测和自动运行
// - CLI 命令注册
// - 所有管理逻辑
createService({
name: 'my-service',
start: async () => {
return serve({
fetch: app.fetch,
port: 3000,
});
},
});// bin/cli.ts
#!/usr/bin/env node
import '../src/index.js'; // 注册服务
import '@cjwddz/service-manager/cli'; // 注册 CLI 命令使用生命周期钩子
// src/index.ts
import { createService, IService, UpdateInfo } from '@cjwddz/service-manager';
import { Hono } from 'hono';
import { serve } from '@hono/node-server';
import { initDatabase, closeDatabase } from './db';
class MyService implements IService {
async start() {
const app = new Hono();
app.get('/', (c) => c.json({ message: 'Hello' }));
return serve({
fetch: app.fetch,
port: 3000,
});
}
hooks = {
beforeStart: async () => {
await initDatabase();
},
afterStart: async () => {
await registerToRegistry();
},
beforeStop: async () => {
await saveState();
await closeDatabase();
},
beforeRestart: async () => {
await backupData();
},
afterRestart: async () => {
await verifyService();
},
// 更新检查钩子
onUpdateAvailable: async (updateInfo: UpdateInfo) => {
console.log(`Update available: ${updateInfo.currentVersion} → ${updateInfo.latestVersion}`);
// 返回 true 表示执行自动更新,false 表示只通知
return false; // 默认只通知,不自动更新
},
};
}
createService(new MyService(), {
name: 'my-service',
version: '1.0.0',
// 自动重启配置
autoRestart: {
enabled: true,
maxRestarts: 5, // 1 分钟内最多重启 5 次
restartWindow: 60 * 1000, // 1 分钟时间窗口
backoff: 'exponential', // 指数退避:1s, 2s, 4s, 8s...
},
// 自动更新检查配置
updateCheck: {
enabled: true,
interval: 24 * 60 * 60 * 1000, // 每 24 小时检查一次
autoUpdate: false, // 默认不自动更新,只通知
// checkFunction: customUpdateCheck, // 可选:自定义检查函数
},
});CLI 使用
在 package.json 中配置 CLI
{
"name": "my-service",
"version": "1.0.0",
"bin": {
"my-service": "./bin/cli.js"
}
}创建 CLI 入口
// bin/cli.ts
#!/usr/bin/env node
// 1. 先导入服务代码(注册服务,框架会自动处理守护进程模式)
import '../src/index.js';
// 2. 然后导入 CLI(注册命令)
import '@cjwddz/service-manager/cli';就是这么简单! 框架会自动:
- ✅ 检测守护进程模式并自动运行服务
- ✅ 注册 CLI 命令
- ✅ 处理所有管理逻辑
用户无需手动处理守护进程模式检测和 CLI 注册!
使用 CLI 命令
# 启动服务
my-service start
# 停止服务
my-service stop
# 重启服务
my-service restart
# 查看状态
my-service statusAPI 参考
createService(service, config?)
创建服务管理器实例。
参数:
service: IService- 服务实现config?: Partial<ServiceConfig>- 可选配置
返回: ServiceManager
IService 接口
interface IService {
start(): Promise<void | Server>;
hooks?: {
beforeStart?: () => Promise<void> | void;
afterStart?: () => Promise<void> | void;
beforeStop?: () => Promise<void> | void;
beforeRestart?: () => Promise<void> | void;
afterRestart?: () => Promise<void> | void;
onUpdateAvailable?: (updateInfo: UpdateInfo) => Promise<boolean> | boolean;
};
}ServiceConfig 接口
interface ServiceConfig {
name: string;
version?: string;
cwd?: string;
dataDir?: string;
pidFile?: string;
logFile?: string;
startTimeout?: number;
stopTimeout?: number;
restartDelay?: number;
autoRestart?: {
enabled: boolean;
maxRestarts?: number; // 最大重启次数(默认:5)
restartWindow?: number; // 重启时间窗口(毫秒,默认:60000)
restartDelay?: number; // 重启延迟(毫秒,默认:1000)
backoff?: 'linear' | 'exponential'; // 退避策略(默认:exponential)
baseDelay?: number; // 基础延迟(毫秒,默认:1000)
};
updateCheck?: {
enabled: boolean; // 是否启用更新检查(默认:false)
interval?: number; // 检查间隔(毫秒,默认:24小时)
autoUpdate?: boolean; // 是否自动更新(默认:false)
checkFunction?: () => Promise<UpdateInfo | null>; // 自定义检查函数
};
env?: Record<string, string>;
stdout?: string | 'inherit' | 'ignore';
stderr?: string | 'inherit' | 'ignore';
}UpdateInfo 接口
interface UpdateInfo {
currentVersion: string;
latestVersion: string;
packageName: string;
updateAvailable: boolean;
changelog?: string;
[key: string]: any;
}工作原理
- 框架控制管理逻辑:所有 start/stop/restart 逻辑都由框架处理
- 业务代码提供钩子:您的代码实现
start()和可选的生命周期钩子 - 自动状态检查:框架自动检查进程状态、运行时间和健康状态
- 进程管理:框架管理 PID 文件、信号处理和优雅关闭
- 自动重启:如果启用,框架会自动重启失败的服务,支持重启限制和退避策略
- 更新检查:框架自动检查更新并通过钩子通知
自动重启保护机制
框架防止无限重启循环:
- 重启限制:时间窗口内的最大重启次数(默认:1 分钟内最多 5 次)
- 退避策略:重启之间的指数或线性延迟
- 时间窗口:时间窗口过期后重启计数器重置
退避策略示例
指数退避(exponential):
- 第 1 次重启:等待 1 秒
- 第 2 次重启:等待 2 秒
- 第 3 次重启:等待 4 秒
- 第 4 次重启:等待 8 秒
- 第 5 次重启:等待 16 秒
线性退避(linear):
- 第 1 次重启:等待 1 秒
- 第 2 次重启:等待 2 秒
- 第 3 次重启:等待 3 秒
- 第 4 次重启:等待 4 秒
- 第 5 次重启:等待 5 秒
更新检查
框架可以自动检查更新:
- 默认行为:检查 npm registry 中的包更新
- 可自定义:您可以提供自定义的
checkFunction来覆盖默认逻辑 - 基于钩子:当有更新可用时,会调用
onUpdateAvailable钩子 - 自动更新:可选的自动更新(默认禁用以确保安全)
默认更新检查逻辑
- 读取
package.json获取包名和当前版本 - 检查是否是 npm 包(排除本地包)
- 查询 npm registry 获取最新版本
- 比较版本号
- 如果有更新,调用
onUpdateAvailable钩子
自定义更新检查
import { defaultUpdateCheck, UpdateInfo } from '@cjwddz/service-manager';
async function customUpdateCheck(): Promise<UpdateInfo | null> {
// 使用默认检查
const result = await defaultUpdateCheck();
// 添加自定义逻辑
if (result && result.updateAvailable) {
// 从 GitHub API 获取 changelog
const changelog = await fetchChangelog(result.latestVersion);
return {
...result,
changelog,
};
}
return result;
}
createService(
{
start: async () => {
/* ... */
},
},
{
updateCheck: {
enabled: true,
checkFunction: customUpdateCheck, // 使用自定义检查函数
},
}
);许可证
MIT
