<?php
namespace taskman;
use Exception;
use Throwable;

task('config_worker', function(array $args)
{
  if(sizeof($args) != 3)
    throw new Exception("Config worker args not set");

  $in_file = $args[0];
  $out_file = $args[1];
  $err_file = $args[2];

  try
  {
    list($params, $job) = unserialize(ensure_read($in_file));
    $result = _config_worker_func($params, $job);
    ensure_write($out_file, serialize($result));
  }
  catch(Throwable $e)
  {
    //NOTE: explicitely catching all exceptions and writing to the error file 
    //      since under Windows error file stream redirect may work unreliably 
    file_put_contents($err_file, $e->getMessage() . "\n" . $e->getTraceAsString(), FILE_APPEND);
    throw $e;
  }
});

function _config_worker_run_procs(ConfigFetchParams $params, array $jobs, bool $serial) : array
{
  if($serial)
  {
    $results_by_job = array();
    foreach($jobs as $job)
      $results_by_job[] = _config_worker_func($params, $job, $serial);
    return $results_by_job;
  }
  else
  {
    //initializing worker for master process anyway
    $params->globals->initWorker(true);

    $workers_args = array();
    foreach($jobs as $job)
      $workers_args[] = array($params, $job);

    return run_background_gamectl_workers('config_worker', $workers_args);
  }
}

//returns [[base_dir, file, cache_file, was_stale, parser_type, error], ...]
function _config_worker_func(ConfigFetchParams $params, array $job, bool $is_master_proc = false) : array
{
  $start_time = microtime(true);

  $params->globals->initWorker($is_master_proc);

  list($idx, $start_time, $chunk) = $job;
  if($params->verbose)
    config_log("Worker $idx (" . sizeof($chunk) . ") started (".round(microtime(true)-$start_time, 2)." sec)");

  $fast_parser_num = 0;
  $results = array();
  foreach($chunk as $file_idx => $chunk_data)
  {
    list($base_dir, $file) = $chunk_data;

    try
    {
      if($params->verbose && $file_idx > 0 && ($file_idx % 500) == 0)
        config_log("Worker $idx progress: " . round($file_idx / sizeof($chunk) * 100) . "% ...");

      $cache_file = config_get_cache_path($params->globals, $file);

      $parser_type = null;

      $is_stale = true;
      if(!$params->force_stale)
        $is_stale = need_to_regen($cache_file, array($file));

      if($is_stale)
        _config_invalidate_cache($params, $base_dir, $file, $cache_file, $parser_type);

      $results[] = array($base_dir, $file, $cache_file, $is_stale, $parser_type, null);
    }
    catch(Throwable $e)
    {
      $results[] = array($base_dir, $file, null, null, null, $e->getMessage());
    }
  }

  if($params->verbose)
    config_log("Worker $idx done (".round(microtime(true)-$start_time, 2)." sec)");

  return $results;
}