Fix up reset scripts again

This commit is contained in:
2025-01-12 00:44:53 -05:00
parent e48911ae24
commit 03ad15c731
4 changed files with 472 additions and 103 deletions

View File

@@ -24,6 +24,13 @@ const METRICS_TABLES = [
'vendor_metrics'
];
// Core tables that must exist
const REQUIRED_CORE_TABLES = [
'products',
'orders',
'purchase_orders'
];
async function resetMetrics() {
outputProgress({
status: 'running',
@@ -34,91 +41,107 @@ async function resetMetrics() {
const connection = await mysql.createConnection(dbConfig);
try {
// First verify that core tables exist
outputProgress({
status: 'running',
operation: 'Verifying core tables exist',
percentage: '10'
});
// Use SHOW TABLES to verify core tables exist
const [showTables] = await connection.query('SHOW TABLES');
const existingTables = showTables.map(t => Object.values(t)[0]);
outputProgress({
operation: 'Core tables verification',
message: {
found: existingTables,
required: REQUIRED_CORE_TABLES
}
});
// Check if any core tables are missing
const missingCoreTables = REQUIRED_CORE_TABLES.filter(
t => !existingTables.includes(t)
);
if (missingCoreTables.length > 0) {
throw new Error(
`Core tables missing: ${missingCoreTables.join(', ')}. Please run reset-db.js first.`
);
}
// Verify all core tables use InnoDB
const [engineStatus] = await connection.query('SHOW TABLE STATUS WHERE Name IN (?)', [REQUIRED_CORE_TABLES]);
const nonInnoDBTables = engineStatus.filter(t => t.Engine !== 'InnoDB');
if (nonInnoDBTables.length > 0) {
throw new Error(
`Tables using non-InnoDB engine: ${nonInnoDBTables.map(t => t.Name).join(', ')}`
);
}
// Disable foreign key checks first
await connection.query('SET FOREIGN_KEY_CHECKS = 0');
// Get list of existing metrics tables
const [tables] = await connection.query(`
// Drop only the metrics tables if they exist
const [existing] = await connection.query(`
SELECT GROUP_CONCAT(table_name) as tables
FROM information_schema.tables
WHERE table_schema = DATABASE()
AND table_name IN (${METRICS_TABLES.map(table => `'${table}'`).join(',')})`
);
AND table_name IN (${METRICS_TABLES.map(table => `'${table}'`).join(',')})
`);
if (tables[0].tables) {
if (existing[0].tables) {
outputProgress({
status: 'running',
operation: 'Dropping existing metrics tables',
percentage: '20'
});
// Drop all existing metrics tables in one query
const dropQuery = `DROP TABLE IF EXISTS ${tables[0].tables.split(',').map(table => '`' + table + '`').join(', ')}`;
const dropQuery = `
DROP TABLE IF EXISTS
${existing[0].tables
.split(',')
.map(table => '`' + table + '`')
.join(', ')}
`;
await connection.query(dropQuery);
}
// Read metrics schema
// Read metrics schema in its entirety
outputProgress({
status: 'running',
operation: 'Creating metrics tables',
percentage: '40'
});
const schemaPath = path.join(__dirname, '../db/metrics-schema.sql');
const schemaSQL = fs.readFileSync(schemaPath, 'utf8');
// Split schema into parts
const parts = schemaSQL.split('-- Create optimized indexes');
const tableSchema = parts[0];
// Execute table creation first
await connection.query(tableSchema);
// Verify all tables were created
// Run the entire metrics-schema so it creates
// the metrics tables and indexes in one shot
await connection.query(schemaSQL);
// Verify all tables were actually created using SHOW TABLES
const [verifyTables] = await connection.query('SHOW TABLES');
const tablesAfterCreation = verifyTables.map(t => Object.values(t)[0]);
outputProgress({
status: 'running',
operation: 'Verifying tables',
percentage: '60'
operation: 'Verifying metrics tables',
message: {
found: tablesAfterCreation,
required: METRICS_TABLES
}
});
const [verifyTables] = await connection.query(`
SELECT table_name
FROM information_schema.tables
WHERE table_schema = DATABASE()
AND table_name IN (${METRICS_TABLES.map(table => `'${table}'`).join(',')})`
);
const missingTables = METRICS_TABLES.filter(table =>
!verifyTables.find(t => t.table_name === table)
const missingTables = METRICS_TABLES.filter(
t => !tablesAfterCreation.includes(t)
);
if (missingTables.length > 0) {
throw new Error(`Failed to create tables: ${missingTables.join(', ')}`);
}
// Create indexes
outputProgress({
status: 'running',
operation: 'Creating indexes',
percentage: '80'
});
// Drop existing indexes if they exist
try {
await connection.query('DROP INDEX IF EXISTS idx_orders_metrics ON orders');
await connection.query('DROP INDEX IF EXISTS idx_purchase_orders_metrics ON purchase_orders');
} catch (err) {
// Ignore any errors dropping indexes
console.warn('Warning dropping indexes:', err.message);
}
// Create new indexes
try {
await connection.query('CREATE INDEX idx_orders_metrics ON orders (product_id, date, canceled, quantity, price)');
await connection.query('CREATE INDEX idx_purchase_orders_metrics ON purchase_orders (product_id, date, status, ordered, received)');
} catch (err) {
// Log index creation errors but don't fail
console.warn('Warning creating indexes:', err.message);
throw new Error(
`Failed to create tables: ${missingTables.join(', ')}`
);
}
// Re-enable foreign key checks
@@ -144,12 +167,12 @@ async function resetMetrics() {
}
}
// Export the function if being required as a module
// Export if required as a module
if (typeof module !== 'undefined' && module.exports) {
module.exports = resetMetrics;
}
// Run directly if called from command line
// Run if called from command line
if (require.main === module) {
resetMetrics().catch(error => {
console.error('Error:', error);