Merge pull request #5 from josedario87/feat/daily-employee-sync
feat: Add daily employee data synchronization
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
import cron from 'node-cron';
|
||||
import { syncEmpleadosToExternalDB } from './sync-empleados.js';
|
||||
|
||||
// Example cron job, runs every 5 seconds for demonstration/testing.
|
||||
cron.schedule('*/5 * * * * *', () => {
|
||||
const now = new Date();
|
||||
if (!isNaN(now)) {
|
||||
@@ -9,3 +11,12 @@ cron.schedule('*/5 * * * * *', () => {
|
||||
console.log('[cron] Fecha inválida');
|
||||
}
|
||||
});
|
||||
|
||||
// Schedules the daily employee data synchronization to run at midnight.
|
||||
cron.schedule('0 0 * * *', () => {
|
||||
console.log('[CronWorker] Running daily employee synchronization task...');
|
||||
syncEmpleadosToExternalDB().catch(err => {
|
||||
console.error('[CronWorker] Error during scheduled employee synchronization:', err);
|
||||
});
|
||||
});
|
||||
console.log('[CronWorker] Daily employee synchronization task scheduled for 00:00.');
|
||||
|
||||
169
worker/sync-empleados.js
Normal file
169
worker/sync-empleados.js
Normal file
@@ -0,0 +1,169 @@
|
||||
// This script is responsible for synchronizing employee data from the local
|
||||
// Prisma database to an external database. It is designed to be run as a scheduled task.
|
||||
|
||||
// --- External Database Configuration (PLACEHOLDERS - User MUST Configure via environment variables) ---
|
||||
// IMPORTANT: These variables define the connection to your external database.
|
||||
// You MUST configure these, ideally through environment variables, for the script to work.
|
||||
// The script provides a template for different database types, but you'll need to:
|
||||
// 1. Install the appropriate database client library (e.g., `npm install pg` or `npm install mysql2`).
|
||||
// 2. Implement the actual database connection and query logic in the designated section.
|
||||
|
||||
const EXTERNAL_DB_TYPE = process.env.EXTERNAL_DB_TYPE || 'your_db_type_here'; // e.g., 'postgres', 'mysql'. User must set this.
|
||||
const EXTERNAL_DB_HOST = process.env.EXTERNAL_DB_HOST || 'YOUR_EXTERNAL_DB_HOST'; // User must set this.
|
||||
const EXTERNAL_DB_PORT = process.env.EXTERNAL_DB_PORT || 5432; // Adjust default port if needed. User must set this.
|
||||
const EXTERNAL_DB_USER = process.env.EXTERNAL_DB_USER || 'YOUR_EXTERNAL_DB_USER'; // User must set this.
|
||||
const EXTERNAL_DB_PASSWORD = process.env.EXTERNAL_DB_PASSWORD || 'YOUR_EXTERNAL_DB_PASSWORD'; // User must set this.
|
||||
const EXTERNAL_DB_NAME = process.env.EXTERNAL_DB_NAME || 'YOUR_EXTERNAL_DB_NAME'; // User must set this.
|
||||
const EXTERNAL_DB_EMPLEADOS_TABLE = process.env.EXTERNAL_DB_EMPLEADOS_TABLE || 'empleados_externos'; // User must set this.
|
||||
// --- End of External Database Configuration ---
|
||||
|
||||
import { PrismaClient } from '../api/prisma/generated/client';
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
async function syncEmpleadosToExternalDB() {
|
||||
console.log('[SyncEmpleados] Starting synchronization process...');
|
||||
// Core logic for synchronization, wrapped in try/catch/finally to ensure
|
||||
// resources like the Prisma client are properly managed (e.g., disconnected).
|
||||
try {
|
||||
// Fetch all 'Cliente' records from the local Prisma database that are marked as 'empleado'.
|
||||
const localEmpleados = await prisma.cliente.findMany({
|
||||
where: { empleado: true }, // Filters for clients who are also employees
|
||||
select: {
|
||||
id: true, // Local ID, might be useful for logging/tracing
|
||||
name: true,
|
||||
cedula: true,
|
||||
ubicacion: true,
|
||||
telefono: true,
|
||||
// avatar_url: true, // Add other relevant fields
|
||||
// idciat: true, // Add other relevant fields
|
||||
},
|
||||
});
|
||||
|
||||
if (!localEmpleados.length) {
|
||||
console.log('[SyncEmpleados] No employees found in local database. Nothing to sync.');
|
||||
return;
|
||||
}
|
||||
console.log(`[SyncEmpleados] Found ${localEmpleados.length} employees to sync.`);
|
||||
|
||||
// --- External DB Connection Logic (User to implement based on EXTERNAL_DB_TYPE) ---
|
||||
// User must implement the actual database connection logic here based on EXTERNAL_DB_TYPE
|
||||
// and install the required database client library (e.g., 'pg' for PostgreSQL, 'mysql2' for MySQL).
|
||||
// The following are conceptual examples.
|
||||
|
||||
// Example for PostgreSQL using 'pg' library (user would need to install it: npm install pg)
|
||||
/*
|
||||
if (EXTERNAL_DB_TYPE === 'postgres') {
|
||||
// const { Client } = require('pg'); // User would uncomment and install
|
||||
// const externalDbClient = new Client({
|
||||
// host: EXTERNAL_DB_HOST,
|
||||
// port: EXTERNAL_DB_PORT,
|
||||
// user: EXTERNAL_DB_USER,
|
||||
// password: EXTERNAL_DB_PASSWORD,
|
||||
// database: EXTERNAL_DB_NAME,
|
||||
// });
|
||||
// await externalDbClient.connect();
|
||||
// console.log('[SyncEmpleados] Connected to external PostgreSQL database.');
|
||||
|
||||
// ... (sync logic using externalDbClient) ...
|
||||
|
||||
// await externalDbClient.end();
|
||||
// console.log('[SyncEmpleados] Disconnected from external PostgreSQL database.');
|
||||
} else if (EXTERNAL_DB_TYPE === 'mysql') {
|
||||
// const mysql = require('mysql2/promise'); // User would uncomment and install
|
||||
// const connection = await mysql.createConnection({
|
||||
// host: EXTERNAL_DB_HOST,
|
||||
// user: EXTERNAL_DB_USER,
|
||||
// password: EXTERNAL_DB_PASSWORD,
|
||||
// database: EXTERNAL_DB_NAME,
|
||||
// port: EXTERNAL_DB_PORT,
|
||||
// });
|
||||
// console.log('[SyncEmpleados] Connected to external MySQL database.');
|
||||
|
||||
// ... (sync logic using connection) ...
|
||||
|
||||
// await connection.end();
|
||||
// console.log('[SyncEmpleados] Disconnected from external MySQL database.');
|
||||
} else {
|
||||
console.error(`[SyncEmpleados] Unsupported EXTERNAL_DB_TYPE: ${EXTERNAL_DB_TYPE}. User needs to implement connection logic.`);
|
||||
// For now, we will just log the data that would be synced
|
||||
}
|
||||
*/
|
||||
// --- End of External DB Connection Logic ---
|
||||
|
||||
console.log('[SyncEmpleados] --- Data to be Synced (Conceptual) ---');
|
||||
for (const emp of localEmpleados) {
|
||||
console.log(`[SyncEmpleados] Processing employee: ID=${emp.id}, Cedula=${emp.cedula}, Name=${emp.name}`);
|
||||
|
||||
// Conceptual Upsert Logic: The following section outlines where you would implement the upsert (update or insert) operation.
|
||||
// You'll need to use your chosen external database client to first check if an employee
|
||||
// with a matching unique identifier (e.g., emp.cedula) exists in the ${EXTERNAL_DB_EMPLEADOS_TABLE}.
|
||||
// If it exists, execute an UPDATE statement. If not, execute an INSERT statement.
|
||||
// Ensure you map fields from 'emp' (local employee) to the corresponding columns in your external table.
|
||||
|
||||
// Example of data to be inserted/updated:
|
||||
const externalData = {
|
||||
// Assuming external table has these columns. User must map accordingly.
|
||||
// Ensure data types are compatible between local and external databases.
|
||||
cedula: emp.cedula, // Primary key for matching in the external table (assumed)
|
||||
nombre: emp.name,
|
||||
telefono: emp.telefono,
|
||||
ubicacion: emp.ubicacion,
|
||||
// local_id: emp.id, // Optional: store local ID for reference
|
||||
// ... map other fields ...
|
||||
};
|
||||
console.log(`[SyncEmpleados] Data for external table: ${JSON.stringify(externalData)}`);
|
||||
}
|
||||
console.log('[SyncEmpleados] --- End of Data to be Synced ---');
|
||||
|
||||
} catch (error) {
|
||||
// Catch any errors that occur during the synchronization process.
|
||||
console.error('[SyncEmpleados] Error during synchronization:', error);
|
||||
} finally {
|
||||
// Ensure the Prisma client is always disconnected, even if an error occurs.
|
||||
await prisma.$disconnect();
|
||||
console.log('[SyncEmpleados] Prisma client disconnected.');
|
||||
}
|
||||
console.log('[SyncEmpleados] Synchronization process finished.');
|
||||
}
|
||||
|
||||
export { syncEmpleadosToExternalDB };
|
||||
|
||||
// --- Testing Considerations ---
|
||||
// 1. **Configuration is Key:** This script requires the `EXTERNAL_DB_...` variables to be correctly
|
||||
// configured with your actual external database credentials and details before any meaningful
|
||||
// end-to-end testing can be performed.
|
||||
//
|
||||
// 2. **Manual Testing:**
|
||||
// * Once configured, you can test the script by running it directly: `node worker/sync-empleados.js`
|
||||
// * Observe the console logs for any errors or successful completion messages.
|
||||
// * Verify that data from your local 'Cliente' table (where empleado=true) appears correctly
|
||||
// in your designated external database table (`EXTERNAL_DB_EMPLEADOS_TABLE`).
|
||||
// * Check that subsequent runs correctly update existing records and insert new ones.
|
||||
// * The cron job in `worker/cron-worker.js` is scheduled to run this script daily at midnight.
|
||||
// You can monitor logs after this time to see its execution.
|
||||
//
|
||||
// 3. **Automated Testing (Recommendations for future development):**
|
||||
// * **Unit Tests:**
|
||||
// - Mock the Prisma client (`../api/prisma/generated/client`) to return predefined employee data
|
||||
// and spy on its methods.
|
||||
// - Mock the external database client (e.g., `pg`, `mysql2`) to simulate connection,
|
||||
// query execution (select, insert, update), and disconnections. This allows testing
|
||||
// the sync logic without actual database dependencies.
|
||||
// * **Integration Tests:**
|
||||
// - If possible, set up a dedicated test instance of your external database.
|
||||
// - Write tests that populate the local Prisma test database with sample employee data,
|
||||
// run the sync script, and then query the external test database to assert that
|
||||
// the data was synchronized correctly. This provides more comprehensive testing
|
||||
// but requires more setup.
|
||||
//
|
||||
// 4. **Logging:** Pay close attention to the console output. The script includes logging for various
|
||||
// stages, which will be crucial for diagnosing issues during testing and operation.
|
||||
// --- End of Testing Considerations ---
|
||||
|
||||
// Optional: For direct execution of this script, e.g., `node worker/sync-empleados.js`
|
||||
if (require.main === module) {
|
||||
console.log('[SyncEmpleados] Running synchronization script directly.');
|
||||
syncEmpleadosToExternalDB()
|
||||
.then(() => console.log('[SyncEmpleados] Direct execution completed.'))
|
||||
.catch(err => console.error('[SyncEmpleados] Direct execution failed:', err));
|
||||
}
|
||||
Reference in New Issue
Block a user