- Fix #49: Add column existence checks to migration 011_add_user_upload_settings.js to prevent "column already exists" errors during deployment - Fix #50: Create missing workerManager.js file that starts background services (file watcher and expiration checker) for native installations
This commit is contained in:
@@ -1,23 +1,56 @@
|
||||
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) {
|
||||
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');
|
||||
});
|
||||
} else {
|
||||
console.log('Column upload_category_id already exists in events table, skipping...');
|
||||
}
|
||||
|
||||
// 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) {
|
||||
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) {
|
||||
const hasAllowUserUploads = await knex.schema.hasColumn('events', 'allow_user_uploads');
|
||||
if (hasAllowUserUploads) {
|
||||
await knex.schema.alterTable('events', function(table) {
|
||||
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');
|
||||
});
|
||||
}
|
||||
|
||||
const hasUploadedBy = await knex.schema.hasColumn('photos', 'uploaded_by');
|
||||
if (hasUploadedBy) {
|
||||
await knex.schema.alterTable('photos', function(table) {
|
||||
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