mirror of
https://github.com/fosrl/pangolin.git
synced 2026-05-28 11:43:03 +00:00
Support the all types in the schema and engine
This commit is contained in:
@@ -11,7 +11,7 @@
|
||||
* This file is not licensed under the AGPLv3.
|
||||
*/
|
||||
|
||||
import { and, eq, isNull, or } from "drizzle-orm";
|
||||
import { and, eq, or } from "drizzle-orm";
|
||||
import { db } from "@server/db";
|
||||
import {
|
||||
alertRules,
|
||||
@@ -49,11 +49,9 @@ export async function processAlerts(context: AlertContext): Promise<void> {
|
||||
// ------------------------------------------------------------------
|
||||
// 1. Find matching alert rules
|
||||
// ------------------------------------------------------------------
|
||||
// Rules with no junction-table entries match ALL sites / health checks.
|
||||
// Rules with junction entries match only those specific IDs.
|
||||
// We implement this with a LEFT JOIN: a NULL join result means the rule
|
||||
// has no scope restrictions (match all); a non-NULL result that satisfies
|
||||
// the id equality filter means an explicit match.
|
||||
// Rules with allSites / allHealthChecks / allResources set to true match
|
||||
// ANY event of that type. Rules without these flags set match only the
|
||||
// specific IDs listed in the junction tables.
|
||||
const baseConditions = and(
|
||||
eq(alertRules.orgId, context.orgId),
|
||||
eq(alertRules.eventType, context.eventType),
|
||||
@@ -74,12 +72,20 @@ export async function processAlerts(context: AlertContext): Promise<void> {
|
||||
and(
|
||||
baseConditions,
|
||||
or(
|
||||
eq(alertSites.siteId, context.siteId),
|
||||
isNull(alertSites.alertRuleId)
|
||||
eq(alertRules.allSites, true),
|
||||
eq(alertSites.siteId, context.siteId)
|
||||
)
|
||||
)
|
||||
);
|
||||
rules = rows.map((r) => r.alertRules);
|
||||
// Deduplicate in case a rule matched on multiple junction rows
|
||||
const seen = new Set<number>();
|
||||
rules = rows
|
||||
.map((r) => r.alertRules)
|
||||
.filter((r) => {
|
||||
if (seen.has(r.alertRuleId)) return false;
|
||||
seen.add(r.alertRuleId);
|
||||
return true;
|
||||
});
|
||||
} else if (context.healthCheckId != null) {
|
||||
const rows = await db
|
||||
.select()
|
||||
@@ -92,12 +98,19 @@ export async function processAlerts(context: AlertContext): Promise<void> {
|
||||
and(
|
||||
baseConditions,
|
||||
or(
|
||||
eq(alertHealthChecks.healthCheckId, context.healthCheckId),
|
||||
isNull(alertHealthChecks.alertRuleId)
|
||||
eq(alertRules.allHealthChecks, true),
|
||||
eq(alertHealthChecks.healthCheckId, context.healthCheckId)
|
||||
)
|
||||
)
|
||||
);
|
||||
rules = rows.map((r) => r.alertRules);
|
||||
const seen = new Set<number>();
|
||||
rules = rows
|
||||
.map((r) => r.alertRules)
|
||||
.filter((r) => {
|
||||
if (seen.has(r.alertRuleId)) return false;
|
||||
seen.add(r.alertRuleId);
|
||||
return true;
|
||||
});
|
||||
} else if (context.resourceId != null) {
|
||||
const rows = await db
|
||||
.select()
|
||||
@@ -110,12 +123,19 @@ export async function processAlerts(context: AlertContext): Promise<void> {
|
||||
and(
|
||||
baseConditions,
|
||||
or(
|
||||
eq(alertResources.resourceId, context.resourceId),
|
||||
isNull(alertResources.alertRuleId)
|
||||
eq(alertRules.allResources, true),
|
||||
eq(alertResources.resourceId, context.resourceId)
|
||||
)
|
||||
)
|
||||
);
|
||||
rules = rows.map((r) => r.alertRules);
|
||||
const seen = new Set<number>();
|
||||
rules = rows
|
||||
.map((r) => r.alertRules)
|
||||
.filter((r) => {
|
||||
if (seen.has(r.alertRuleId)) return false;
|
||||
seen.add(r.alertRuleId);
|
||||
return true;
|
||||
});
|
||||
} else {
|
||||
rules = [];
|
||||
}
|
||||
|
||||
@@ -246,6 +246,9 @@ export async function createAlertRule(
|
||||
eventType,
|
||||
enabled,
|
||||
cooldownSeconds,
|
||||
allSites,
|
||||
allHealthChecks,
|
||||
allResources,
|
||||
createdAt: now,
|
||||
updatedAt: now
|
||||
})
|
||||
|
||||
@@ -217,8 +217,11 @@ export async function updateAlertRule(
|
||||
enabled,
|
||||
cooldownSeconds,
|
||||
siteIds,
|
||||
allSites,
|
||||
healthCheckIds,
|
||||
allHealthChecks,
|
||||
resourceIds,
|
||||
allResources,
|
||||
userIds,
|
||||
roleIds,
|
||||
emails,
|
||||
@@ -233,8 +236,10 @@ export async function updateAlertRule(
|
||||
if (name !== undefined) updateData.name = name;
|
||||
if (eventType !== undefined) updateData.eventType = eventType;
|
||||
if (enabled !== undefined) updateData.enabled = enabled;
|
||||
if (cooldownSeconds !== undefined)
|
||||
updateData.cooldownSeconds = cooldownSeconds;
|
||||
if (cooldownSeconds !== undefined) updateData.cooldownSeconds = cooldownSeconds;
|
||||
if (allSites !== undefined) updateData.allSites = allSites;
|
||||
if (allHealthChecks !== undefined) updateData.allHealthChecks = allHealthChecks;
|
||||
if (allResources !== undefined) updateData.allResources = allResources;
|
||||
|
||||
await db
|
||||
.update(alertRules)
|
||||
@@ -247,12 +252,14 @@ export async function updateAlertRule(
|
||||
);
|
||||
|
||||
// --- Full-replace site associations if siteIds was provided ---
|
||||
if (siteIds !== undefined) {
|
||||
if (siteIds !== undefined || allSites !== undefined) {
|
||||
await db
|
||||
.delete(alertSites)
|
||||
.where(eq(alertSites.alertRuleId, alertRuleId));
|
||||
|
||||
if (siteIds.length > 0) {
|
||||
// Only insert junction rows when allSites is not true
|
||||
const effectiveAllSites = allSites ?? false;
|
||||
if (!effectiveAllSites && siteIds !== undefined && siteIds.length > 0) {
|
||||
await db.insert(alertSites).values(
|
||||
siteIds.map((siteId) => ({
|
||||
alertRuleId,
|
||||
@@ -263,12 +270,13 @@ export async function updateAlertRule(
|
||||
}
|
||||
|
||||
// --- Full-replace health check associations if healthCheckIds was provided ---
|
||||
if (healthCheckIds !== undefined) {
|
||||
if (healthCheckIds !== undefined || allHealthChecks !== undefined) {
|
||||
await db
|
||||
.delete(alertHealthChecks)
|
||||
.where(eq(alertHealthChecks.alertRuleId, alertRuleId));
|
||||
|
||||
if (healthCheckIds.length > 0) {
|
||||
const effectiveAllHealthChecks = allHealthChecks ?? false;
|
||||
if (!effectiveAllHealthChecks && healthCheckIds !== undefined && healthCheckIds.length > 0) {
|
||||
await db.insert(alertHealthChecks).values(
|
||||
healthCheckIds.map((healthCheckId) => ({
|
||||
alertRuleId,
|
||||
@@ -279,12 +287,13 @@ export async function updateAlertRule(
|
||||
}
|
||||
|
||||
// --- Full-replace resource associations if resourceIds was provided ---
|
||||
if (resourceIds !== undefined) {
|
||||
if (resourceIds !== undefined || allResources !== undefined) {
|
||||
await db
|
||||
.delete(alertResources)
|
||||
.where(eq(alertResources.alertRuleId, alertRuleId));
|
||||
|
||||
if (resourceIds.length > 0) {
|
||||
const effectiveAllResources = allResources ?? false;
|
||||
if (!effectiveAllResources && resourceIds !== undefined && resourceIds.length > 0) {
|
||||
await db.insert(alertResources).values(
|
||||
resourceIds.map((resourceId) => ({
|
||||
alertRuleId,
|
||||
|
||||
Reference in New Issue
Block a user