feat(center-nodes): add node heartbeat endpoint
Some checks failed
backend-ci / verify (Fabric.Backend.Center) (push) Has been cancelled
backend-ci / verify (Fabric.Backend.Guild) (push) Has been cancelled

This commit is contained in:
nav
2026-05-12 08:54:17 +00:00
parent 7887a8d3be
commit 7f68a09486
3 changed files with 35 additions and 2 deletions

View File

@@ -1,4 +1,10 @@
import { Column, CreateDateColumn, Entity, PrimaryGeneratedColumn } from 'typeorm'; import {
Column,
CreateDateColumn,
Entity,
PrimaryGeneratedColumn,
UpdateDateColumn,
} from 'typeorm';
@Entity('guild_nodes') @Entity('guild_nodes')
export class GuildNode { export class GuildNode {
@@ -21,6 +27,12 @@ export class GuildNode {
}) })
status!: 'active' | 'offline' | 'revoked'; status!: 'active' | 'offline' | 'revoked';
@Column({ type: 'datetime', nullable: true })
lastHeartbeatAt!: Date | null;
@CreateDateColumn() @CreateDateColumn()
createdAt!: Date; createdAt!: Date;
@UpdateDateColumn()
updatedAt!: Date;
} }

View File

@@ -65,6 +65,27 @@ export class NodesController {
}; };
} }
@Post(':nodeId/heartbeat')
async heartbeat(@Param('nodeId') nodeId: string) {
const node = await this.nodeRepo.findOne({ where: { nodeId } });
if (!node) {
throw new NotFoundException('node not found');
}
node.lastHeartbeatAt = new Date();
if (node.status !== 'revoked') {
node.status = 'active';
}
const saved = await this.nodeRepo.save(node);
return {
status: 'ok',
nodeId: saved.nodeId,
nodeStatus: saved.status,
lastHeartbeatAt: saved.lastHeartbeatAt,
};
}
@Patch(':nodeId/status') @Patch(':nodeId/status')
async updateStatus( async updateStatus(
@Param('nodeId') nodeId: string, @Param('nodeId') nodeId: string,

View File

@@ -27,7 +27,7 @@
- [x] node 唯一性校验nodeId/endpoint - [x] node 唯一性校验nodeId/endpoint
- [x] node 状态模型active/offline/revoked - [x] node 状态模型active/offline/revoked
- [x] `GET /nodes` 列表 + 分页 - [x] `GET /nodes` 列表 + 分页
- [ ] node 心跳接口(可选) - [x] node 心跳接口(可选)
### 1.3 Center 运维能力 ### 1.3 Center 运维能力
- [ ] 审计日志auth/node 关键操作) - [ ] 审计日志auth/node 关键操作)