/** * Look for any workers which should be running on this server and if * they're not, remove them from Redis. * * This is a form of garbage collection to handle cases where the * server may have been killed and the workers did not die gracefully * and therefore leave state information in Redis. */ public function cleanup() { $workers = self::allWorkers(); $hosts = $this->redis->smembers(Host::redisKey()); $cleaned = array(); foreach ($workers as $worker) { list($host, $pid) = explode(':', (string) $worker, 2); if ($host != (string) $this->host and in_array($host, $hosts) or $host == (string) $this->host and posix_kill((int) $pid, 0)) { continue; } $this->log('Pruning dead worker: ' . $worker, Logger::DEBUG); $worker->unregister(); $cleaned[] = (string) $worker; } $workerIds = array_map(function ($w) { return (string) $w; }, $workers); $keys = (array) $this->redis->keys('worker:' . $this->host . ':*'); foreach ($keys as $key) { $key = $this->redis->removeNamespace($key); $id = substr($key, strlen('worker:')); if (!in_array($id, $workerIds)) { if ($this->redis->ttl($key) < 0) { $this->log('Expiring worker data: ' . $key, Logger::DEBUG); $this->redis->expire($key, \Resque::getConfig('default.expiry_time', \Resque::DEFAULT_EXPIRY_TIME)); } } } Event::fire(Event::WORKER_CLEANUP, array($this, $cleaned)); return $cleaned; }