title: how to finish all tasks at once in php
body: <p>i am running a webgame based on php .
  each player will create up to 100 attacks tasks that will be stored in db with details of it and end_time , every page load of any player on the website will call a function to check everything in db that supposed to end_time to be now or less .
  if found any , then it will start processing them ( make the actual attack and get its results  ).</p>
  <p>it is like travian if you know it .
  my issue happens when there are 20 task or more at the same moment then it will stuck and only process one task per page load ( which kills the game. )</p>
  <p>i use foreach loop in order to process the array of queues that gotten by querying the db .</p>
  <p>code is :</p>
  <p>every page load will call :</p>
  <pre><code> public function processQueue($type = 3, $playerId = 0)
      {
          global $gameConfig;
          $this-&gt;load_model('Mutex', 'mutex');
          $this-&gt;mutex-&gt;releaseOnTimeout();
          if ($this-&gt;mutex-&gt;lock()) { // locker to forbid 2 players from working on same rows and cause double values. 
              $this-&gt;processTaskQueue($type, $playerId);
              }
              $this-&gt;mutex-&gt;release();
          }
      }
  </code></pre>
  <p>Processing function :</p>
  <pre><code>public function processTaskQueue($type, $playerId)
      {
          $p_type = QS_ACCOUNT_DELETE . ',' . QS_MERCHANT_GO . ',' . QS_MERCHANT_BACK . ',' . QS_WAR_REINFORCE . ',' . QS_WAR_ATTACK . ',' . QS_WAR_ATTACK_PLUNDER . ',' . QS_WAR_ATTACK_SPY . ',' . QS_CREATEVILLAGE . ',' . QS_TATAR_RAISE . ',' . QS_SITE_RESET . ',' . QS_CROP_DELETE . ',' . QS_ARTEFACTS_RAISE;
          if ($type == 1) {
              $expr = &quot;((q.player_id=&quot; . $playerId . &quot; AND q.proc_type!=&quot; . QS_TROOP_TRAINING . &quot;) OR q.proc_type IN (&quot; . $p_type . &quot;))&quot;;
          } elseif ($type == 2) {
              $expr = &quot;(q.player_id=&quot; . $playerId . &quot; OR q.proc_type IN (&quot; . $p_type . &quot;))&quot;;
          } else {
              $expr = &quot;q.proc_type!=&quot; . QS_TROOP_TRAINING;
          }
          $result = db::get_all(&quot;SELECT  q.id, q.player_id, q.village_id, q.to_player_id, q.to_village_id, q.proc_type, q.building_id, q.proc_params, q.threads, q.execution_time, TIMESTAMPDIFF(SECOND, NOW(),q.end_date) remainingTimeInSeconds FROM p_queue q WHERE TIMESTAMPDIFF(SECOND, NOW(),(q.end_date - INTERVAL (q.execution_time*(q.threads-1)) SECOND)) &lt;= 0 AND $expr ORDER BY TIMESTAMPDIFF(SECOND, NOW(),(q.end_date - INTERVAL (q.execution_time*(q.threads-1)) SECOND)) ASC&quot;);
          foreach ($result as $resultRow) {
              $remain = $resultRow['remainingTimeInSeconds'];
              if ($remain &lt; 0) {
                  $remain = 0;
              }
              $resultRow['threads_completed_num'] = $resultRow['execution_time'] &lt;= 0 ? $resultRow['threads'] : floor(($resultRow['threads'] * $resultRow['execution_time'] - $remain) / $resultRow['execution_time']);
              if ($this-&gt;processTask($resultRow)) {
                  unset($result);
                  $this-&gt;processQueue($type, $playerId);
                  break;
              }
          }
          unset($result);
  
      }
  </code></pre>
  <p>locker function :</p>
  <pre><code>define(&quot;__QS_LOCK_FS_&quot;, MODELS_DIR . &quot;lock&quot;);
  
  class Mutex_Model extends Model
  {
  
      public function lock()
      {
          if (0 &lt; db::count(&quot;UPDATE g_settings gs SET gs.qlocked=1, qlocked_date=NOW() WHERE gs.qlocked=0&quot;) &amp;&amp; ($fp = fopen(__QS_LOCK_FS_, &quot;r&quot;)) != FALSE) {
              if (flock($fp, LOCK_EX)) {
                  fclose($fp);
                  return TRUE;
              }
              fclose($fp);
          }
          return FALSE;
      }
  
      public function release()
      {
          $this-&gt;_releaseInternal();
          db::query(&quot;UPDATE g_settings gs SET gs.qlocked=0&quot;);
      }
  
      public function releaseOnTimeout()
      {
          if (0 &lt; db::count(&quot;UPDATE g_settings gs SET gs.qlocked=0 WHERE gs.qlocked=1 AND TIME_TO_SEC(TIMEDIFF(NOW(), gs.qlocked_date)) &gt; 120&quot;)) {
              $this-&gt;_releaseInternal();
          }
      }
  
      public function _releaseInternal()
      {
          if (($fp = fopen(__QS_LOCK_FS_, &quot;r&quot;)) != FALSE) {
              flock($fp, LOCK_UN);
              fclose($fp);
          }
      }
  
  }
  </code></pre>
  <p>what i need is to process all of the results in the array quickly ( could be 200 arrays in it or more ) and make it work all of the time without causing an issue ( tried ajax code to run every second but that cause missing stuff when a player logs out while it is running -- the row the script was handling while he is leaving will be miss )
  and i need to process everything at once in it instead of the foreach loop ( it is very slow and will be stuck at every refresh )</p>
  <p>i tried the following :</p>
  <p>1- delete the break and make it continue running till it finished , but that gives players 500 http msg and make loading very very very slow for the one who got the locker opens ( mutex )</p>
  <p>2- make cron job with php file that loops for 59s on processQueue function , but still it will only process like 10 - 20 tasks at one second maximum which is very slow</p>
  <p>3- remove the locker which cause double values (meaning a. player send 50 solider they will return 100 )</p>
  <p>my server infos are :
  12 CPUs ( only 2 of them consumed )
  131,744,852 memory
  Configurations :</p>
  <p>Start Servers [?]
  5 default</p>
  <p>10
  Minimum Spare Servers [?]
  5 default</p>
  <p>10
  Maximum Spare Servers [?]
  10 default</p>
  <p>20
  Server Limit (Maximum: 20,000) [?]
  256 default</p>
  <p>8042
  Max Request Workers [?]
  150 default</p>
  <p>8042
  Max Connections Per Child [?]
  10000 default</p>
  <p>10000
  Keep-Alive [?]
  On</p>
  <p>PHP-FPM Pool options
  Max Requests<br />
  95000
  cPanel Default: 20
  Max Children<br />
  10000
  cPanel Default: 5
  Process Idle Timeout  :30
  i am really confused and hoping you can help me out here ..</p>