/** * Adds a Job to the queue only if one does not * already exist. * * @param $job * @param $args * * @return mixed */ public function addUniqueJob($job, JobPayloadContainer $args) { // Refuse to pop a job onto the queue if the admin // has not yet configured an administrative contact. // See: https://github.com/eveseat/seat/issues/77 (Request by CCP) if ($this->hasDefaultAdminContact()) { logger()->error('Default admin contact still set. Not queuing job for: ' . $args->api); return 'Failed to queue due to default config'; } // Look for an existing job $job_id = JobTracking::where('owner_id', $args->owner_id)->where('api', $args->api)->whereIn('status', ['Queued', 'Working'])->value('job_id'); // Just return if the job already exists if ($job_id) { logger()->warning('A job for Api ' . $args->api . ' and owner ' . $args->owner_id . ' already exists.'); return $job_id; } // Add a new job onto the queue... $new_job = (new $job($args))->onQueue($args->queue); $job_id = dispatch($new_job); // Check that the id we got back is a random // string and not 0. In fact, normal job_ids // are like a 32char string, so just check that // its more than 2. If its not, we can assume // the job itself was not sucesfully added. // If it actually is queued, it will get discarded // when trackOrDismiss() is called. if (strlen($job_id) < 2) { return; } // ...and add tracking information JobTracking::create(['job_id' => $job_id, 'owner_id' => $args->owner_id, 'api' => $args->api, 'scope' => $args->scope, 'status' => 'Queued']); return $job_id; }
/** * Adds a Job to the queue only if one does not * already exist. * * @param $job * @param $args * * @return mixed */ public function addUniqueJob($job, JobContainer $args) { // Look for an existing job $job_id = JobTracking::where('owner_id', $args->owner_id)->where('api', $args->api)->whereIn('status', ['Queued', 'Working'])->value('job_id'); // Just return if the job already exists if ($job_id) { return $job_id; } // Add a new job onto the queue... $new_job = (new $job($args))->onQueue($args->queue); $job_id = $this->dispatch($new_job); // Check that the id we got back is a random // string and not 0. In fact, normal job_ids // are like a 32char string, so just check that // its more than 2. If its not, we can assume // the job itself was not sucesfully added. // If it actually is queued, it will get discarded // when trackOrDismiss() is called. if (strlen($job_id) < 2) { return; } // ...and add tracking information JobTracking::create(['job_id' => $job_id, 'owner_id' => $args->owner_id, 'api' => $args->api, 'scope' => $args->scope, 'status' => 'Queued']); return $job_id; }
/** * Checks the Job Tracking table if the current job * has a tracking entry. If not, the job is just * deleted * * @return mixed */ public function trackOrDismiss() { // Match the current job_id with the tracking // record we added when queuing the job $job_tracker = JobTracking::where('job_id', $this->job->getJobId())->first(); // If no tracking record is found, just put // the job back in the queue after a few // seconds. It could be that the job // to add it has not finished yet. if (!$job_tracker) { // Check that we have not come by this logic // for like the 10th time now. if ($this->attempts() < 10) { // Add the job back into the queue and wait // for 2 seconds before releasing it. $this->release(2); return null; } // Remove yourself from the queue Log::error('Error finding a JobTracker for job ' . $this->job->getJobID()); $this->delete(); return null; } // Return the Job Tracking handle return $job_tracker; }
/** * Return a count summary of the jobs in * the queue * * @return array */ public function count_summary() { $response = ['total_jobs' => JobTracking::count('job_id'), 'working_jobs' => JobTracking::where('status', 'Working')->count('job_id'), 'queued_jobs' => JobTracking::where('status', 'Queued')->count('job_id'), 'done_jobs' => JobTracking::where('status', 'Done')->count('job_id'), 'error_jobs' => JobTracking::where('status', 'Error')->count('job_id')]; return $response; }
/** * @param $api_key * * @return \Illuminate\View\View */ public function getDetail($api_key) { $key = ApiKeyModel::with('info', 'characters', 'status')->where('key_id', $api_key)->firstOrFail(); $access_map = null; if ($key->info) { $access_map = $key->info->type == 'Corporation' ? config('eveapi.access_bits.corp') : config('eveapi.access_bits.char'); } $jobs = JobTracking::where('owner_id', $api_key)->orderBy('created_at', 'desc')->take(50)->get(); // Get worker information. $key_type = $key->info->type == 'Corporation' ? 'corporation' : 'character'; $available_workers = config('eveapi.worker_groups'); $current_workers = $key->api_call_constraints; return view('web::api.detail', compact('key', 'access_map', 'jobs', 'key_type', 'available_workers', 'current_workers')); }
/** * @return mixed */ public function clearErroredJobHistory() { return JobTracking::where('status', 'Error')->delete(); }
/** * @param $api_key * * @return \Illuminate\View\View */ public function getDetail($api_key) { $key = ApiKeyModel::with('info', 'characters')->where('key_id', $api_key)->firstOrFail(); $access_map = null; if ($key->info) { $access_map = $key->info->type == 'Corporation' ? config('eveapi.access_bits.corp') : config('eveapi.access_bits.char'); } $jobs = JobTracking::where('owner_id', $api_key)->orderBy('created_at', 'desc')->get(); return view('web::api.detail', compact('key', 'access_map', 'jobs')); }
/** * Handle an exception that can be thrown by a job. * * This is the failed method that Laravel itself will call * when a jobs `handle` method throws any uncaught exception. * * @param \Exception $exception */ public function failed(Exception $exception) { logger()->error('An error occured in ' . __CLASS__ . '. The exception thrown was ' . $exception->getMessage() . ' in file ' . $exception->getFile() . ' on line ' . $exception->getLine()); // Try and find the jobtracking entry. Sadly, because the context // seems logs in the `failed()` methods, we cant just lookup by job_id :( $job_tracker = JobTracking::where('owner_id', $this->job_payload->owner_id)->where('api', $this->job_payload->api)->where('scope', $this->job_payload->scope)->where('status', '<>', 'Error')->first(); if ($job_tracker) { // Prepare some useful information about the error. $output = 'Last Updater: ' . $job_tracker->output . PHP_EOL; $output .= PHP_EOL; $output .= 'Exception : ' . get_class($exception) . PHP_EOL; $output .= 'Error Code : ' . $exception->getCode() . PHP_EOL; $output .= 'Error Message : ' . $exception->getMessage() . PHP_EOL; $output .= 'File : ' . $exception->getFile() . PHP_EOL; $output .= 'Line : ' . $exception->getLine() . PHP_EOL; $output .= PHP_EOL; $output .= 'Traceback: ' . PHP_EOL; $output .= $exception->getTraceAsString() . PHP_EOL; $job_tracker->fill(['status' => 'Error', 'output' => $output])->save(); } // Analytics. Report only the Exception class and message. dispatch((new Analytics((new AnalyticsContainer())->set('type', 'exception')->set('exd', get_class($exception) . ':' . $exception->getMessage())->set('exf', 1)))->onQueue('medium')); return; }