This commit is contained in:
odzugkoev
2026-03-01 17:10:03 -05:00
parent 7e0887c62d
commit 85cf732a61
19 changed files with 2284 additions and 32 deletions

View File

@@ -9,12 +9,13 @@ const config = require('./config');
const apiClient = require('./api-client');
const printer = require('./printer');
const PrintQueueWorker = require('./print-worker');
const AbandonedCallPoller = require('./abandoned-call-poller');
const fastify = Fastify({
logger: true
});
const isDev = false;
const isDev = true;
// Order Poller Class
class OrderPoller {
@@ -68,11 +69,16 @@ class OrderPoller {
return;
}
// Check if token is expired
if (apiClient.isTokenExpired(appConfig.tokenExpiry)) {
console.log('Token expired, please re-login');
this.isPolling = false;
return;
// Attempt token refresh if expired or near expiry
if (apiClient.isTokenNearExpiry(appConfig.tokenExpiry, 7)) {
const refreshed = await apiClient.ensureValidToken();
if (!refreshed) {
console.log('Token expired and refresh failed, please re-login');
this.isPolling = false;
return;
}
// Re-read config after refresh so the poll uses the new token
Object.assign(appConfig, config.getAll());
}
// Get last synced order ID
@@ -365,6 +371,7 @@ async function main() {
await fastify.register(require('./routes/dashboard'));
await fastify.register(require('./routes/settings'));
await fastify.register(require('./routes/orders'));
await fastify.register(require('./routes/abandoned-calls'));
// Initialize printer with config
const appConfig = config.getAll();
@@ -383,10 +390,12 @@ async function main() {
// Start order poller
const poller = new OrderPoller(apiClient, database, printer);
const printWorker = new PrintQueueWorker(database, config, printer);
const abandonedCallPoller = new AbandonedCallPoller(database, printer);
// Make poller available globally for restart after settings change
// Make pollers available globally for restart after settings change
fastify.decorate('orderPoller', poller);
fastify.decorate('printWorker', printWorker);
fastify.decorate('abandonedCallPoller', abandonedCallPoller);
// Start server
const port = parseInt(process.env.PORT, 10) || 3000;
@@ -412,15 +421,44 @@ async function main() {
setInterval(() => { try { checkAndUpdate(); } catch (e) { fastify.log.error(e); } }, updateIntervalMs);
}
// Attempt token refresh on startup in case it expired while offline
try {
const refreshedToken = await apiClient.ensureValidToken();
if (refreshedToken) {
console.log('Startup token check passed');
} else if (config.get('authToken')) {
console.log('Startup token refresh failed — user may need to re-login');
}
} catch (err) {
console.error('Startup token refresh error:', err.message);
}
// Start polling after server is up
poller.start();
// Start print queue worker
printWorker.start();
// Start abandoned call poller
abandonedCallPoller.start();
// Periodic token refresh (every 6 hours)
const TOKEN_REFRESH_INTERVAL_MS = 6 * 60 * 60 * 1000;
const tokenRefreshTimer = setInterval(async () => {
try {
const result = await apiClient.ensureValidToken();
if (result) {
console.log('Periodic token refresh: OK');
}
} catch (err) {
console.error('Periodic token refresh error:', err.message);
}
}, TOKEN_REFRESH_INTERVAL_MS);
// Handle shutdown gracefully (PM2 reload-friendly)
const gracefulShutdown = async () => {
console.log('\nShutting down gracefully...');
poller.stop();
try { abandonedCallPoller.stop(); } catch (_) {}
clearInterval(tokenRefreshTimer);
try { printWorker.stop(); } catch (_) {}
try { database.close(); } catch (_) {}
try { await fastify.close(); } catch (_) {}