import { setTimeout as setTimeoutAsync } from 'timers/promises';
import { getRedisClient } from './external-services/redis.js';

function handleSignal(signal) {
  console.log('got signal', signal, '- exiting now');
  process.exit();
}

function handleUncaughtException(e) {
  console.error(e);
  console.log('uncaught exception or unhandled rejection - exiting now');
  process.exitCode = 1;
  process.exit();
}

process.on('SIGTERM', handleSignal);
process.on('SIGINT', handleSignal);
process.on('uncaughtException', handleUncaughtException);
process.on('unhandledRejection', handleUncaughtException);

const removePrefix = (key) => key.split(':').slice(1).join(':');

const redisClient = getRedisClient();

while (true) {
  const [workInProgress, workersAlive] = (await redisClient.multi().keys('work:*').keys('worker:*').exec()).map((x) =>
    (x[1] as Array<string>).map(removePrefix)
  );
  const suspectedDroppedWork = workInProgress.filter((w) => !workersAlive.includes(w));
  for (const work of suspectedDroppedWork) {
    const queueName = work.split(':')[0];
    const [requeueResult, _] = await redisClient
      .multi()
      .rpoplpush(`work:${work}`, queueName)
      .del(`work:${work}`)
      .exec();
    if (requeueResult !== null) {
      console.log(`requeued ${work} to ${queueName}`);
    }
  }
  await setTimeoutAsync(2000);
}
