Merge pull request #51 from the-luap/claude/fix-issues-49-50-01Rqwe1uhvLpbZ64tA5eiB2H
Fix issues #49 and #50: Migration errors and missing worker manager
This commit is contained in:
@@ -1,23 +1,56 @@
|
|||||||
exports.up = async function(knex) {
|
exports.up = async function(knex) {
|
||||||
// Add user upload settings to events table
|
// Add user upload settings to events table (check if columns exist first)
|
||||||
|
const hasAllowUserUploads = await knex.schema.hasColumn('events', 'allow_user_uploads');
|
||||||
|
if (!hasAllowUserUploads) {
|
||||||
|
console.log('Adding allow_user_uploads column to events table...');
|
||||||
await knex.schema.alterTable('events', function(table) {
|
await knex.schema.alterTable('events', function(table) {
|
||||||
table.boolean('allow_user_uploads').defaultTo(false);
|
table.boolean('allow_user_uploads').defaultTo(false);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.log('Column allow_user_uploads already exists in events table, skipping...');
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasUploadCategoryId = await knex.schema.hasColumn('events', 'upload_category_id');
|
||||||
|
if (!hasUploadCategoryId) {
|
||||||
|
console.log('Adding upload_category_id column to events table...');
|
||||||
|
await knex.schema.alterTable('events', function(table) {
|
||||||
table.integer('upload_category_id').references('id').inTable('photo_categories').onDelete('SET NULL');
|
table.integer('upload_category_id').references('id').inTable('photo_categories').onDelete('SET NULL');
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
console.log('Column upload_category_id already exists in events table, skipping...');
|
||||||
|
}
|
||||||
|
|
||||||
// Add uploaded_by field to photos table to track who uploaded
|
// Add uploaded_by field to photos table to track who uploaded
|
||||||
|
const hasUploadedBy = await knex.schema.hasColumn('photos', 'uploaded_by');
|
||||||
|
if (!hasUploadedBy) {
|
||||||
|
console.log('Adding uploaded_by column to photos table...');
|
||||||
await knex.schema.alterTable('photos', function(table) {
|
await knex.schema.alterTable('photos', function(table) {
|
||||||
table.string('uploaded_by').defaultTo('admin'); // 'admin' or guest identifier
|
table.string('uploaded_by').defaultTo('admin'); // 'admin' or guest identifier
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
console.log('Column uploaded_by already exists in photos table, skipping...');
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.down = async function(knex) {
|
exports.down = async function(knex) {
|
||||||
|
const hasAllowUserUploads = await knex.schema.hasColumn('events', 'allow_user_uploads');
|
||||||
|
if (hasAllowUserUploads) {
|
||||||
await knex.schema.alterTable('events', function(table) {
|
await knex.schema.alterTable('events', function(table) {
|
||||||
table.dropColumn('allow_user_uploads');
|
table.dropColumn('allow_user_uploads');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasUploadCategoryId = await knex.schema.hasColumn('events', 'upload_category_id');
|
||||||
|
if (hasUploadCategoryId) {
|
||||||
|
await knex.schema.alterTable('events', function(table) {
|
||||||
table.dropColumn('upload_category_id');
|
table.dropColumn('upload_category_id');
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasUploadedBy = await knex.schema.hasColumn('photos', 'uploaded_by');
|
||||||
|
if (hasUploadedBy) {
|
||||||
await knex.schema.alterTable('photos', function(table) {
|
await knex.schema.alterTable('photos', function(table) {
|
||||||
table.dropColumn('uploaded_by');
|
table.dropColumn('uploaded_by');
|
||||||
});
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
/**
|
||||||
|
* Worker Manager - Background service for PicPeak
|
||||||
|
*
|
||||||
|
* This service runs as a separate process to handle:
|
||||||
|
* - File watching for new photos
|
||||||
|
* - Expiration checking for events
|
||||||
|
* - Other background tasks
|
||||||
|
*/
|
||||||
|
|
||||||
|
const path = require('path');
|
||||||
|
const logger = require('../utils/logger');
|
||||||
|
|
||||||
|
// Load environment variables
|
||||||
|
require('dotenv').config({ path: path.join(__dirname, '../../.env') });
|
||||||
|
|
||||||
|
// Import services
|
||||||
|
const { startFileWatcher } = require('./fileWatcher');
|
||||||
|
const { startExpirationChecker } = require('./expirationChecker');
|
||||||
|
|
||||||
|
let isShuttingDown = false;
|
||||||
|
|
||||||
|
async function startWorkers() {
|
||||||
|
logger.info('Starting PicPeak background workers...');
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Start file watcher for automatic photo processing
|
||||||
|
startFileWatcher();
|
||||||
|
logger.info('File watcher started successfully');
|
||||||
|
|
||||||
|
// Start expiration checker for event lifecycle management
|
||||||
|
startExpirationChecker();
|
||||||
|
logger.info('Expiration checker started successfully');
|
||||||
|
|
||||||
|
logger.info('All background workers started successfully');
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Failed to start background workers:', error);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleShutdown(signal) {
|
||||||
|
if (isShuttingDown) {
|
||||||
|
logger.info('Shutdown already in progress...');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
isShuttingDown = true;
|
||||||
|
logger.info(`Received ${signal}. Shutting down gracefully...`);
|
||||||
|
|
||||||
|
// Give time for cleanup
|
||||||
|
setTimeout(() => {
|
||||||
|
logger.info('Worker manager shutdown complete');
|
||||||
|
process.exit(0);
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle shutdown signals
|
||||||
|
process.on('SIGTERM', () => handleShutdown('SIGTERM'));
|
||||||
|
process.on('SIGINT', () => handleShutdown('SIGINT'));
|
||||||
|
|
||||||
|
// Handle uncaught errors
|
||||||
|
process.on('uncaughtException', (error) => {
|
||||||
|
logger.error('Uncaught exception in worker manager:', error);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
process.on('unhandledRejection', (reason, promise) => {
|
||||||
|
logger.error('Unhandled rejection in worker manager:', reason);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Start workers
|
||||||
|
startWorkers();
|
||||||
Reference in New Issue
Block a user