Merge pull request #59 from zaunist/fix/delete_failed

fix: delete agent or monitor failed
This commit is contained in:
zaunist authored and GitHub committed 2025-06-13 13:07:36 +08:00
commit 4e354cd277
9 files changed
+1425 -60

No files matched your search

@@ -0,0 +1,7 @@
ALTER TABLE `agents` DROP COLUMN `cpu_usage`;--> statement-breakpoint
ALTER TABLE `agents` DROP COLUMN `memory_total`;--> statement-breakpoint
ALTER TABLE `agents` DROP COLUMN `memory_used`;--> statement-breakpoint
ALTER TABLE `agents` DROP COLUMN `disk_total`;--> statement-breakpoint
ALTER TABLE `agents` DROP COLUMN `disk_used`;--> statement-breakpoint
ALTER TABLE `agents` DROP COLUMN `network_rx`;--> statement-breakpoint
ALTER TABLE `agents` DROP COLUMN `network_tx`;
File diff suppressed because it is too large. Load diff
+7
View File
@@ -8,6 +8,13 @@
"when": 1748308256007,
"tag": "0000_romantic_next_avengers",
"breakpoints": true
},
{
"idx": 1,
"version": "6",
"when": 1749736889133,
"tag": "0001_fluffy_pestilence",
"breakpoints": true
}
]
}
+41 -29
View File
@@ -32,7 +32,11 @@ export async function getAgentMetricsByIds(agentIds: number[]) {
// 获取单个客户端详情
export async function getAgentById(id: number) {
const agent = await db.select().from(agents).where(eq(agents.id, id)).limit(1);
const agent = await db
.select()
.from(agents)
.where(eq(agents.id, id))
.limit(1);
return agent[0];
}
@@ -53,19 +57,22 @@ export async function createAgent(
// 将 ipAddresses 数组转换为 JSON 字符串
const ipAddressesJson = ipAddresses ? JSON.stringify(ipAddresses) : null;
const result = await db.insert(agents).values({
name,
token,
created_by: createdBy,
status,
created_at: now,
updated_at: now,
hostname,
ip_addresses: ipAddressesJson,
os,
version,
keepalive,
}).returning();
const result = await db
.insert(agents)
.values({
name,
token,
created_by: createdBy,
status,
created_at: now,
updated_at: now,
hostname,
ip_addresses: ipAddressesJson,
os,
version,
keepalive,
})
.returning();
if (!result) {
throw new Error("创建客户端失败");
@@ -74,17 +81,19 @@ export async function createAgent(
}
// 更新客户端信息
export async function updateAgent(
agent: Agent
) {
export async function updateAgent(agent: Agent) {
agent.updated_at = new Date().toISOString();
// 从 agent 对象中排除 id 等索引相关属性,避免更新主键
const { id, token, created_by, ...updateData } = agent;
try {
// 确保 updateData 中不包含 id
const updatedAgent = await db.update(agents).set(updateData).where(eq(agents.id, id)).returning();
const updatedAgent = await db
.update(agents)
.set(updateData)
.where(eq(agents.id, id))
.returning();
return updatedAgent[0];
} catch (error) {
console.error("更新客户端失败:", error);
@@ -94,12 +103,13 @@ export async function updateAgent(
// 删除客户端
export async function deleteAgent(id: number) {
// 先删除关联的指标数据
await db.delete(agentMetrics24h).where(eq(agentMetrics24h.agent_id, id));
const result = await db.delete(agents).where(eq(agents.id, id));
if (!result.success) {
try {
// 先删除关联的指标数据
await db.delete(agentMetrics24h).where(eq(agentMetrics24h.agent_id, id));
// 再删除客户端
await db.delete(agents).where(eq(agents.id, id));
} catch (error) {
console.error("删除客户端失败:", error);
throw new Error("删除客户端失败");
}
@@ -115,9 +125,9 @@ export async function getAgentByToken(token: string) {
// 获取活跃状态的客户端
export async function getActiveAgents() {
const activeAgents = await db
.select()
.from(agents)
.where(eq(agents.status, "active"));
.select()
.from(agents)
.where(eq(agents.status, "active"));
return activeAgents;
}
@@ -133,7 +143,9 @@ export async function setAgentInactive(id: number) {
// 插入客户端资源指标
export async function insertAgentMetrics(metrics: Metrics[]) {
return await db.batch(metrics.map(metric => db.insert(agentMetrics24h).values(metric)));
return await db.batch(
metrics.map((metric) => db.insert(agentMetrics24h).values(metric))
);
}
// 获取指定客户端资源指标
+5 -9
View File
@@ -14,22 +14,18 @@ import { eq, desc, asc, lt } from "drizzle-orm";
// 获取需要检查的监控列表
export async function getMonitorsToCheck() {
// 使用SQL表达式或自定义函数来处理日期计算
const allmonitors = await db
.select()
.from(monitors)
.execute();
const allmonitors = await db.select().from(monitors).execute();
// 在JavaScript中进行日期计算筛选
const now = new Date().getTime();
const monitorsToCheck = allmonitors.filter((monitor: Monitor) => {
if (!monitor.last_checked) return true; // 如果没有检查过,需要检查
const lastCheckedTime = new Date(monitor.last_checked).getTime();
const intervalMs = (monitor.interval || 60) * 1000; // 转换为毫秒
return now > (lastCheckedTime + intervalMs);
return now > lastCheckedTime + intervalMs;
});
// 解析所有监控的 headers 字段
+36 -19
View File
@@ -61,7 +61,6 @@ export const updateNotificationChannel = async (
Omit<NotificationChannel, "id" | "created_at" | "updated_at">
>
): Promise<boolean> => {
const result = await db
.update(notificationChannels)
.set({
@@ -245,7 +244,7 @@ export const getGlobalSettings = async (): Promise<{
.select()
.from(notificationSettings)
.where(eq(notificationSettings.target_type, "global-agent"));
return {
monitorSettings: monitorSettings[0],
agentSettings: agentSettings[0],
@@ -279,19 +278,19 @@ export const createOrUpdateSettings = async (
settings: Omit<NotificationSettings, "id" | "created_at" | "updated_at">
): Promise<number> => {
// 确保target_id为0时使用isNull,否则使用eq
const condition = settings.target_id === 0 ? isNull(notificationSettings.target_id) : eq(notificationSettings.target_id, settings.target_id);
const condition =
settings.target_id === 0
? isNull(notificationSettings.target_id)
: eq(notificationSettings.target_id, settings.target_id);
// 先检查是否已存在相同的设置
const existingSettings = await db
.select()
.from(notificationSettings)
.where(
and(
eq(notificationSettings.target_type, settings.target_type),
condition
)
and(eq(notificationSettings.target_type, settings.target_type), condition)
);
if (existingSettings.length === 1) {
if (existingSettings.length > 0) {
const existingSetting = existingSettings[0];
// 如果已存在则更新
await db
@@ -418,29 +417,19 @@ export const getNotificationConfig = async (): Promise<NotificationConfig> => {
// 获取所有渠道
const channels = await getNotificationChannels();
console.log("channels", channels);
// 获取所有模板
const templates = await getNotificationTemplates();
console.log("templates", templates);
// 获取全局设置
const globalSettings = await getGlobalSettings();
console.log("globalSettings", globalSettings);
// 获取特定监控项设置
const monitorSettings = await getSpecificSettings("monitor");
console.log("monitorSettings", monitorSettings);
// 获取特定客户端设置
const agentSettings = await getSpecificSettings("agent");
console.log("agentSettings", agentSettings);
// 构建通知配置
// 构建通知配置
const config: NotificationConfig = {
channels: channels,
templates: templates,
@@ -525,3 +514,31 @@ export const getNotificationConfig = async (): Promise<NotificationConfig> => {
return config;
};
/**
* 删除通知设置
* @param type 通知类型,"monitor" 或 "agent"
* @param id 目标ID,监控或客户端的ID
* @return {Promise<boolean>} 删除是否成功
*/
export const deleteNotificationSettings = async (
type: "monitor" | "agent",
id: number
): Promise<boolean> => {
// 执行删除操作
try {
await db
.delete(notificationSettings)
.where(
and(
eq(notificationSettings.target_type, type),
eq(notificationSettings.target_id, id)
)
);
} catch (error) {
console.error("[删除通知设置] 删除通知设置失败:", error);
throw new Error("删除通知设置失败");
}
return true;
};
+3
View File
@@ -128,6 +128,9 @@ export async function deleteAgentService(agentId: number) {
throw new Error("客户端不存在");
}
// 删除客户端通知设置
await AgentRepository.deleteNotificationSettings("agent", agent.id);
// 执行删除客户端
await AgentRepository.deleteAgent(agent.id);
+11 -1
View File
@@ -265,7 +265,17 @@ export async function deleteMonitor(id: number) {
return { success: false, message: "监控不存在", status: 404 };
}
// 执行删除
// 执行通知设置删除
const notificationResult = await NotificationService.deleteNotificationSettings(
"monitor",
id
);
if (!notificationResult.success) {
console.error("删除监控通知设置失败:", notificationResult.message);
// 继续执行监控删除,不影响主流程
}
// 执行monitor删除
const result = await repositories.deleteMonitor(id);
if (!result.success) {
+28 -2
View File
@@ -511,7 +511,7 @@ export async function sendNotification(
// 过滤掉不存在的渠道
const validChannels = channels.filter(
(ch): ch is models.NotificationChannel => ch !== null
)
);
console.log(
`[发送通知] 有效渠道数量: ${validChannels.length},类型分布:`,
@@ -651,7 +651,7 @@ export async function shouldSendNotification(
// 获取此对象的特定设置
const specificSettings = await repositories.getSpecificSettings(type, id);
console.log(
`[通知触发检查] 获取到特定设置数量: ${
specificSettings ? specificSettings.length : 0
@@ -777,3 +777,29 @@ export async function shouldSendNotification(
return { shouldSend, channels };
}
/**
* 删除通知设置
* @param type 通知类型
* @param id 通知设置ID
*/
export async function deleteNotificationSettings(
type: "monitor" | "agent",
id: number
): Promise<{ success: boolean; message?: string }> {
try {
console.log(`[删除通知设置] 开始删除${type}通知设置,ID=${id}`);
// 执行删除操作
await repositories.deleteNotificationSettings(type, id);
} catch (error) {
console.error("[删除通知设置] 删除通知设置失败:", error);
return {
success: false,
message: error instanceof Error ? error.message : "删除通知设置失败",
};
}
return {
success: true,
message: `${type}通知设置删除成功`,
};
}