Files
kener/migrations/20260109120000_add_maintenances_tables.ts
T
2026-01-22 11:19:13 +05:30

69 lines
3.8 KiB
TypeScript

import type { Knex } from "knex";
export async function up(knex: Knex): Promise<void> {
// Create maintenances table - defines maintenance schedules using iCalendar RRULE
// RRULE examples:
// - ONE_TIME: FREQ=MINUTELY;COUNT=1 (single occurrence)
// - RECURRING: FREQ=WEEKLY;BYDAY=SU;BYHOUR=2;BYMINUTE=0 (every Sunday at 2 AM)
// Reference: http://www.kanzaki.com/docs/ical/rrule.html
await knex.schema.createTable("maintenances", (table) => {
table.increments("id").primary();
table.string("title", 255).notNullable();
table.text("description").nullable(); // Maintenance details/description
table.integer("start_date_time").notNullable(); // Unix timestamp - when the first occurrence starts
table.string("rrule", 500).notNullable(); // iCalendar RRULE string (e.g., FREQ=WEEKLY;BYDAY=SU)
table.integer("duration_seconds").notNullable(); // Duration of each maintenance window in seconds
table.string("status", 50).notNullable().defaultTo("ACTIVE"); // ACTIVE or INACTIVE
table.timestamp("created_at").defaultTo(knex.fn.now());
table.timestamp("updated_at").defaultTo(knex.fn.now());
});
// Create maintenance_monitors junction table - links monitors to maintenance schedules
await knex.schema.createTable("maintenance_monitors", (table) => {
table.increments("id").primary();
table.integer("maintenance_id").unsigned().notNullable();
table.string("monitor_tag", 255).notNullable();
table.timestamp("created_at").defaultTo(knex.fn.now());
table.timestamp("updated_at").defaultTo(knex.fn.now());
// Foreign key constraints
table.foreign("maintenance_id").references("id").inTable("maintenances").onDelete("CASCADE");
table.foreign("monitor_tag").references("tag").inTable("monitors").onDelete("CASCADE");
// Unique constraint to prevent duplicate monitor assignments
table.unique(["maintenance_id", "monitor_tag"]);
});
// Create maintenances_events table - actual maintenance occurrences (generated by job)
await knex.schema.createTable("maintenances_events", (table) => {
table.increments("id").primary();
table.integer("maintenance_id").unsigned().notNullable();
table.integer("start_date_time").notNullable(); // Unix timestamp
table.integer("end_date_time").notNullable(); // Unix timestamp
table.string("status", 50).notNullable().defaultTo("SCHEDULED"); // SCHEDULED, IN_PROGRESS, COMPLETED, CANCELLED
table.timestamp("created_at").defaultTo(knex.fn.now());
table.timestamp("updated_at").defaultTo(knex.fn.now());
// Foreign key constraint
table.foreign("maintenance_id").references("id").inTable("maintenances").onDelete("CASCADE");
});
// Add indexes for faster lookups
await knex.schema.raw("CREATE INDEX idx_maintenances_status ON maintenances (status)");
await knex.schema.raw("CREATE INDEX idx_maintenances_start_time ON maintenances (start_date_time)");
await knex.schema.raw(
"CREATE INDEX idx_maintenance_monitors_maintenance_id ON maintenance_monitors (maintenance_id)",
);
await knex.schema.raw("CREATE INDEX idx_maintenance_monitors_monitor_tag ON maintenance_monitors (monitor_tag)");
await knex.schema.raw("CREATE INDEX idx_maintenances_events_maintenance_id ON maintenances_events (maintenance_id)");
await knex.schema.raw("CREATE INDEX idx_maintenances_events_status ON maintenances_events (status)");
await knex.schema.raw("CREATE INDEX idx_maintenances_events_start_time ON maintenances_events (start_date_time)");
await knex.schema.raw("CREATE INDEX idx_maintenances_events_end_time ON maintenances_events (end_date_time)");
}
export async function down(knex: Knex): Promise<void> {
await knex.schema.dropTableIfExists("maintenances_events");
await knex.schema.dropTableIfExists("maintenance_monitors");
await knex.schema.dropTableIfExists("maintenances");
}