feat(db): add graylog schema and processed_tickets multi-source migration
This commit is contained in:
parent
a243064992
commit
941bde4f7c
2 changed files with 136 additions and 1 deletions
127
src-tauri/migrations/009_graylog_auto_resolve.sql
Normal file
127
src-tauri/migrations/009_graylog_auto_resolve.sql
Normal file
|
|
@ -0,0 +1,127 @@
|
||||||
|
BEGIN;
|
||||||
|
|
||||||
|
PRAGMA foreign_keys = OFF;
|
||||||
|
|
||||||
|
DROP INDEX IF EXISTS idx_processed_tickets_tracker_artifact_unique;
|
||||||
|
|
||||||
|
CREATE TABLE processed_tickets_new (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
tracker_id TEXT REFERENCES watched_trackers(id) ON DELETE CASCADE,
|
||||||
|
project_id TEXT REFERENCES projects(id) ON DELETE CASCADE,
|
||||||
|
source TEXT NOT NULL DEFAULT 'tuleap',
|
||||||
|
source_ref TEXT,
|
||||||
|
artifact_id INTEGER NOT NULL,
|
||||||
|
artifact_title TEXT NOT NULL,
|
||||||
|
artifact_data TEXT NOT NULL,
|
||||||
|
status TEXT NOT NULL DEFAULT 'Pending',
|
||||||
|
analyst_report TEXT,
|
||||||
|
developer_report TEXT,
|
||||||
|
worktree_path TEXT,
|
||||||
|
branch_name TEXT,
|
||||||
|
detected_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
||||||
|
processed_at TEXT
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO processed_tickets_new (
|
||||||
|
id,
|
||||||
|
tracker_id,
|
||||||
|
project_id,
|
||||||
|
source,
|
||||||
|
source_ref,
|
||||||
|
artifact_id,
|
||||||
|
artifact_title,
|
||||||
|
artifact_data,
|
||||||
|
status,
|
||||||
|
analyst_report,
|
||||||
|
developer_report,
|
||||||
|
worktree_path,
|
||||||
|
branch_name,
|
||||||
|
detected_at,
|
||||||
|
processed_at
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
pt.id,
|
||||||
|
pt.tracker_id,
|
||||||
|
wt.project_id,
|
||||||
|
'tuleap',
|
||||||
|
NULL,
|
||||||
|
pt.artifact_id,
|
||||||
|
pt.artifact_title,
|
||||||
|
pt.artifact_data,
|
||||||
|
pt.status,
|
||||||
|
pt.analyst_report,
|
||||||
|
pt.developer_report,
|
||||||
|
pt.worktree_path,
|
||||||
|
pt.branch_name,
|
||||||
|
pt.detected_at,
|
||||||
|
pt.processed_at
|
||||||
|
FROM processed_tickets pt
|
||||||
|
LEFT JOIN watched_trackers wt ON wt.id = pt.tracker_id;
|
||||||
|
|
||||||
|
DROP TABLE processed_tickets;
|
||||||
|
ALTER TABLE processed_tickets_new RENAME TO processed_tickets;
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX idx_processed_tickets_tracker_artifact_unique
|
||||||
|
ON processed_tickets(tracker_id, artifact_id)
|
||||||
|
WHERE tracker_id IS NOT NULL;
|
||||||
|
|
||||||
|
CREATE INDEX idx_processed_tickets_project_detected
|
||||||
|
ON processed_tickets(project_id, detected_at DESC);
|
||||||
|
|
||||||
|
CREATE INDEX idx_processed_tickets_source_ref
|
||||||
|
ON processed_tickets(source, source_ref);
|
||||||
|
|
||||||
|
CREATE TABLE graylog_credentials (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
project_id TEXT NOT NULL UNIQUE REFERENCES projects(id) ON DELETE CASCADE,
|
||||||
|
base_url TEXT NOT NULL,
|
||||||
|
api_token_encrypted TEXT NOT NULL,
|
||||||
|
analyst_agent_id TEXT NOT NULL REFERENCES agents(id),
|
||||||
|
developer_agent_id TEXT NOT NULL REFERENCES agents(id),
|
||||||
|
stream_id TEXT,
|
||||||
|
query_filter TEXT NOT NULL DEFAULT '',
|
||||||
|
polling_interval_minutes INTEGER NOT NULL DEFAULT 10,
|
||||||
|
lookback_minutes INTEGER NOT NULL DEFAULT 30,
|
||||||
|
score_threshold INTEGER NOT NULL DEFAULT 70,
|
||||||
|
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE graylog_subjects (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
||||||
|
subject_key TEXT NOT NULL,
|
||||||
|
source TEXT NOT NULL,
|
||||||
|
normalized_message TEXT NOT NULL,
|
||||||
|
first_seen_at TEXT NOT NULL,
|
||||||
|
last_seen_at TEXT NOT NULL,
|
||||||
|
last_score INTEGER NOT NULL DEFAULT 0,
|
||||||
|
active_ticket_id TEXT REFERENCES processed_tickets(id),
|
||||||
|
status TEXT NOT NULL DEFAULT 'idle',
|
||||||
|
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
||||||
|
UNIQUE(project_id, subject_key)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE graylog_detections (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
subject_id TEXT NOT NULL REFERENCES graylog_subjects(id) ON DELETE CASCADE,
|
||||||
|
window_start TEXT NOT NULL,
|
||||||
|
window_end TEXT NOT NULL,
|
||||||
|
critical_count INTEGER NOT NULL DEFAULT 0,
|
||||||
|
error_count INTEGER NOT NULL DEFAULT 0,
|
||||||
|
warning_count INTEGER NOT NULL DEFAULT 0,
|
||||||
|
total_count INTEGER NOT NULL DEFAULT 0,
|
||||||
|
last_seen_at TEXT NOT NULL,
|
||||||
|
score INTEGER NOT NULL,
|
||||||
|
triggered INTEGER NOT NULL DEFAULT 0,
|
||||||
|
triggered_ticket_id TEXT REFERENCES processed_tickets(id),
|
||||||
|
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX idx_graylog_detections_subject_created
|
||||||
|
ON graylog_detections(subject_id, created_at DESC);
|
||||||
|
|
||||||
|
PRAGMA foreign_keys = ON;
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
|
@ -9,6 +9,7 @@ const MIGRATION_005: &str = include_str!("../migrations/005_orchestration_module
|
||||||
const MIGRATION_006: &str = include_str!("../migrations/006_processed_tickets_unique_index.sql");
|
const MIGRATION_006: &str = include_str!("../migrations/006_processed_tickets_unique_index.sql");
|
||||||
const MIGRATION_007: &str = include_str!("../migrations/007_normalize_timestamps_rfc3339.sql");
|
const MIGRATION_007: &str = include_str!("../migrations/007_normalize_timestamps_rfc3339.sql");
|
||||||
const MIGRATION_008: &str = include_str!("../migrations/008_project_scoped_tuleap_credentials.sql");
|
const MIGRATION_008: &str = include_str!("../migrations/008_project_scoped_tuleap_credentials.sql");
|
||||||
|
const MIGRATION_009: &str = include_str!("../migrations/009_graylog_auto_resolve.sql");
|
||||||
|
|
||||||
pub fn init(db_path: &Path) -> Result<Connection> {
|
pub fn init(db_path: &Path) -> Result<Connection> {
|
||||||
let conn = Connection::open(db_path)?;
|
let conn = Connection::open(db_path)?;
|
||||||
|
|
@ -66,6 +67,10 @@ fn migrate(conn: &Connection) -> Result<()> {
|
||||||
conn.execute_batch(MIGRATION_008)?;
|
conn.execute_batch(MIGRATION_008)?;
|
||||||
conn.pragma_update(None, "user_version", 8)?;
|
conn.pragma_update(None, "user_version", 8)?;
|
||||||
}
|
}
|
||||||
|
if version < 9 {
|
||||||
|
conn.execute_batch(MIGRATION_009)?;
|
||||||
|
conn.pragma_update(None, "user_version", 9)?;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -91,6 +96,9 @@ mod tests {
|
||||||
tables,
|
tables,
|
||||||
vec![
|
vec![
|
||||||
"agents",
|
"agents",
|
||||||
|
"graylog_credentials",
|
||||||
|
"graylog_detections",
|
||||||
|
"graylog_subjects",
|
||||||
"notifications",
|
"notifications",
|
||||||
"processed_tickets",
|
"processed_tickets",
|
||||||
"project_agent_tasks",
|
"project_agent_tasks",
|
||||||
|
|
@ -121,7 +129,7 @@ mod tests {
|
||||||
let version: i32 = conn
|
let version: i32 = conn
|
||||||
.pragma_query_value(None, "user_version", |row| row.get(0))
|
.pragma_query_value(None, "user_version", |row| row.get(0))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(version, 8);
|
assert_eq!(version, 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue