क्या मुझे एक कतार के प्रसंस्करण के लिए क्रोन कार्य की आवश्यकता है?


32

मुझे एक ऐसा काम मिला है जिसे पूरा करने में लगभग 45 मिनट लगते हैं और हर दिन होने की जरूरत है (उपयोगकर्ताओं को कई बाहरी डेटाबेस आदि से सिंक करना)।

काम को संभालने के लिए, मैंने एक क्रोन कतार hook_cron_queue_info()इस प्रकार स्थापित की है:

function mymodule_cron_queue_info() {
  $queues = array();
  $queues['update_users_queue'] = array(
    'worker callback' => '_mymodule_process_user_queue_item',
    'time' => 120,
  );
  return $queues;
}

मैं इस फ़ंक्शन का उपयोग करके कतार को भरता हूं:

function mymodule_queue_all_users_for_synching() {
  //...query for users...

  $queue = DrupalQueue::get('update_users_queue');
  foreach($users as $user) {
    $queue->createItem($user);
  }
}

कतार-भरण क्रिया को क्रोन कार्य कहा जाता है। मैं एलिसिया क्रोन का उपयोग करता हूं , इसलिए मेरा कार्यान्वयन इस प्रकार hook_cronapi()है:

function mymodule_cronapi($op, $job = NULL) {
  $items = array();
  $items['queue_users_for_synch'] = array(
    'description' => 'Queue all user accounts for synching.',
    'rule' => '0 3 * * *', // Run this job every day at 3am.
    'callback' => 'mymodule_queue_all_users_for_synching',
  );
  return $items;
}

परिभाषित प्रत्येक कतार आइटम के लिए कार्यकर्ता कार्य इस mymodule_cron_queue_infoप्रकार है:

function _mymodule_process_user_queue_item($item) {
  //...synchronize user ($item)...
}

मेरा सवाल है, जब क्रोन वास्तव में कतार का प्रसंस्करण शुरू करने जा रहा है?

मान लें कि मैं प्रतिदिन प्रातः 3 बजे कतार को भरता हूँ, और इसे हर 30 मिनट में 120 सेकंड में संसाधित करना चाहता हूँ जब तक कि यह पूरा न हो जाए - क्या मुझे एक और क्रोन कार्य बनाने की आवश्यकता है?


मुझे उल्लेख करना चाहिए कि मैं Drupal 7.
joe_flash

1
मैं इस प्रश्न के बारे में उत्सुक हूं। हां या ना सुनना पसंद करेंगे। हम अपनी D7 परियोजनाओं में से एक में कतार एपीआई का भारी उपयोग करते हैं। नेत्रहीन मैंने देखा है कि क्रोन के चलने पर टेबल की कतारें साफ हो जाती हैं। तो मान लीजिए कि यह हाँ है।
शिवाजी

जवाबों:


19

जब द्रुपाल क्रोन कार्यों को चलाता है, तो यह मॉड्यूल से परिभाषित किसी भी क्रोन कतार को स्वचालित रूप से संभालता है drupal_cron_run(); पहले hook_cron()कार्यान्वयन लागू किए जाते हैं, और फिर क्रोन कतारों को खाली कर दिया जाता है।

लागू करते हुए hook_cronapi(), आप अपने मॉड्यूल की क्रोन कतार को संभालने वाले दूसरे फ़ंक्शन के लिए एक प्रविष्टि जोड़ सकते हैं।

function mymodule_cronapi($op, $job = NULL) {
  $items = array();

  $items['queue_users_for_synch'] = array(
    'description' => 'Queue all user accounts for synching.',
    'rule' => '0 3 * * *', // Run this job every day at 3am.
    'callback' => 'mymodule_queue_all_users_for_synching',
  );

  $items['clean_queue'] = array(
    'description' => 'Clean the queue for the user synching.',
    'rule' => '0 4 * * *', // Run this job every day at 4 AM.
    'callback' => 'mymodule_clean_queue',
  );

  return $items;
}

function mymodule_clean_queue() {
  $queues = module_invoke('mymodule', 'cron_queue_info');
  drupal_alter('cron_queue_info', $queues);

  // Make sure every queue exists. There is no harm in trying to recreate an
  // existing queue.
  foreach ($queues as $queue_name => $info) {
    DrupalQueue::get($queue_name)->createQueue();
  }

  foreach ($queues as $queue_name => $info) {
    $function = $info['worker callback'];
    $end = time() + (isset($info['time']) ? $info['time'] : 15);
    $queue = DrupalQueue::get($queue_name);
    while (time() < $end && ($item = $queue->claimItem())) {
      $function($item->data);
      $queue->deleteItem($item);
    }
  }
}

विकल्प ड्रुपल को आपके लिए क्रोन कतार को संभालने दे रहा है, लेकिन ऐसा तब होता है जब ड्रुपल क्रोन कार्यों को निष्पादित किया जाता है। यदि आप अपने मॉड्यूल की क्रोन कतार को अधिक बार खाली करना चाहते हैं, तो आप केवल एलीसिया क्रोन मॉड्यूल द्वारा संभाला एक नया क्रोन कार्य जोड़ सकते हैं।

एलिसिया क्रोन मॉड्यूल में क्रोन कतारों को संभालता है elysia_cron_run(); इस फ़ंक्शन को elysia_cron_cron()(अपने कार्यान्वयन से hook_cron()), drush_elysia_cron_run_wrapper()(Drush कमांड कॉलबैक), और अपने स्वयं के cron.php से लागू किया जा रहा है । यदि आपने INSTALL.txt फ़ाइल (विशेष रूप से "STEP B: CHANGE SYSTEM CRONTAB (OPTIONAL)") में निर्देशों का पालन किया है , और http: // उदाहरण के साथ http://example.com/cron.php के किसी भी आह्वान को प्रतिस्थापित किया है। .com / साइटों / सभी / मॉड्यूल / elysia_cron / cron.php , Elysia Cron मॉड्यूल को पहले से ही क्रोन कतारों को संभालना चाहिए। मेरे द्वारा सुझाए गए कोड का उपयोग आपके मॉड्यूल से उपयोग होने वाली क्रोन कतारों को संभालने के लिए किया जा सकता है, यदि प्रभावी रूप से ऐसा करने की आवश्यकता है।

// This code is part of the code executed from modules/elysia_cron/cron.php.
define('DRUPAL_ROOT', getcwd());

include_once DRUPAL_ROOT . '/includes/bootstrap.inc';
drupal_override_server_variables(array(
  'SCRIPT_NAME' => '/cron.php',
));
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);

if (!isset($_GET['cron_key']) || variable_get('cron_key', 'drupal') != $_GET['cron_key']) {
  watchdog('cron', 'Cron could not run because an invalid key was used.', array(), WATCHDOG_NOTICE);
  drupal_access_denied();
}
elseif (variable_get('maintenance_mode', 0)) {
  watchdog('cron', 'Cron could not run because the site is in maintenance mode.', array(), WATCHDOG_NOTICE);
  drupal_access_denied();
}
else {
  if (function_exists('elysia_cron_run')) {
    elysia_cron_run();
  }
  else {
    drupal_cron_run();
  }
}

आह, धन्यवाद @kiam! यही कारण है कि मुझे संदेह है, लेकिन मैं अपने मस्तिष्क को इसके चारों ओर नहीं लपेट सकता।
joe_flash

दरअसल, मुझे लगता है कि मुझे यहां कुछ याद आ रहा है। आपने कहा कि विकल्प ड्रुपल को मेरे लिए क्रोन कतार संभालने दे रहा है; मुझे लगता है कि मेरे मूल प्रश्न का एक हिस्सा यह है कि वास्तव में ऐसा कब होता है ? हर बार क्रेस्टब अनुरोध करता है cron.php? अगर ऐसा है, तो हर मिनट ऐसा होता है (@ डेविड के जवाब पर मेरी पहली टिप्पणी देखें)।
joe_flash

1
यह उल्लेख के लायक है कि यह प्रतीत होता है कि एलिसिया क्रोन का अपना क्रोन_केयू प्रोसेसर कार्यान्वयन है, elysia_cron_runजिसमें क्रोन कतारों को स्वचालित रूप से संसाधित किया जाता है, एलीसिया का क्रोन.फपी अनुरोध किया जाता है।
डेविड थॉमस

@joe_flash मुझे खेद है: मुझे स्पष्ट होना चाहिए था। हाँ, ड्रुपल क्रोन कार्यों को चलाता है जब cron.php लागू होता है (प्रत्येक ड्रुपल संस्करण के लिए ड्रुपल 7 तक)। Drupal 8 में, cron.php अब मौजूद नहीं है, और cron कार्यों को एक अलग सिस्टम पथ का उपयोग करके निष्पादित किया जाता है।
kiamlaluno

2

निर्धारित समय पर कतार को एलिसिया क्रोनपी हुक के माध्यम से आबाद किया जाएगा।

हालाँकि, मानक Drupal cron रन होने पर कतार संसाधित हो जाएगी।

कोर के अंत में इस कार्यकर्ता कॉलबैक प्रसंस्करण स्निपेट को देखें: drupal_cron_run

 foreach ($queues as $queue_name => $info) {
    $function = $info['worker callback'];
    $end = time() + (isset($info['time']) ? $info['time'] : 15);
    $queue = DrupalQueue::get($queue_name);
    while (time() < $end && ($item = $queue->claimItem())) {
      $function($item->data);
      $queue->deleteItem($item);
    }
  }

डेविड, शायद एलिसिया यहां थोड़ी जटिलता का परिचय देता है? मैंने हर मिनट एलीसिया cron.phpस्क्रिप्ट को ट्रिगर करने के लिए कोंटैब सेट किया है , जो एलीसिया को मिनट-वार रिज़ॉल्यूशन के साथ कार्य समय को नियंत्रित करने की अनुमति देता है। कोई भी कार्य वास्तव में हर मिनट नहीं चलता है - जो कि मुझे लगता है कि मुझे विशेष रूप से कतारों में काम करने के लिए एक कार्य बनाने की आवश्यकता है?
joe_flash

@joe_flash जब तक drupal_cron_runबुलाया जा रहा है, आपके क्रोन कतार कार्यकर्ता कॉलबैक पर कार्रवाई की जाएगी।
डेविड थॉमस

आह, मुझे लगता है कि तुम सही हो। हालाँकि, drupal_cron_runएलिसिया cron.phpस्क्रिप्ट से नहीं बुलाया जाता है (जब एलिसिया सक्षम है); elysia_cron_runके बजाय प्रयोग किया जाता है।
joe_flash

उस स्थिति में, ऐसा लगता है कि आप hook_cron_queue_infoएलिसिया क्रोन के साथ उपयोग नहीं कर सकते हैं , जब तक कि आप अपने स्वयं के कार्यकर्ता कॉलबैक को निर्दिष्ट नहीं करते हैं, जैसा कि drupal_cron_runऊपर मुख्य फ़ंक्शन स्निपेट है।
डेविड थॉमस

elysia_cron_runकॉल नहीं करता है drupal_cron_run, लेकिन यह कॉल करता हैmodule_invoke_all('cron_queue_info') और कुछ फैंसी-पैंट मल्टी-चैनल हैंडलिंग करता है जो मेरे कानों से धुआं निकलता है।
joe_flash

1

जैसा कि ऊपर बताया गया है कि एलिसिया क्रोन का उपयोग करते समय आपकी कतारें संसाधित नहीं होती हैं।

आप (और ड्रुपल) की कतारों तक पहुंच नहीं है जो अन्यथा ड्रुपल_रुन_क्रोन पर चलेगी

वर्कअराउंड एक कस्टम क्रोन कार्य बनाने के लिए है - (यह एलीसिया क्रोन को दिखाई देगा) या तो सभी कतारों को संसाधित करने के लिए या आप जो चाहते हैं और वहां कतार प्रसंस्करण लागू करें। अर्थात:

function mymodule_cron() {
// below is copied from drupal_cron_run() in common.inc

// Grab the defined cron queues.
$queues = module_invoke_all('cron_queue_info');
drupal_alter('cron_queue_info', $queues);

//if you want to target only one queue you can remove 'foreach'
and your $info = $queues['your_queue'];

  foreach ($queues as $queue_name => $info) {
    if (!empty($info['skip on cron'])) {
      // Do not run if queue wants to skip.
      continue;
    }
    $callback = $info['worker callback'];
    $end = time() + (isset($info['time']) ? $info['time'] : 15);
    $queue = DrupalQueue::get($queue_name);
     while (time() < $end && ($item = $queue->claimItem())) {
      try {
        call_user_func($callback, $item->data);
        $queue->deleteItem($item);
      }
      catch (Exception $e) {
        // In case of exception log it and leave the item in the queue
        // to be processed again later.
        watchdog_exception('cron', $e);
      }
    }
  }
}

अब क्वींस प्रोसेसिंग को एलीसिया क्रोन द्वारा नियंत्रित किया जा सकता है


0

मैं एलिसिया का उपयोग नहीं करता, लेकिन मेरा समाधान हमेशा कुछ इस तरह से रहा है:

function mymodule_cron() {
  $queue = DrupalQueue::get('mymoudule_queue');
  $queue->createQueue();
  $item = $queue->claimItem(300);

  if (!empty($item->data)) {

    // Do the work.

    if ($sucess) {
      $queue->deleteItem($item);
      watchdog('mymodule', 'It worked.');
    }
    else {
      watchdog('mymodule', 'It did not work!', array(), WATCHDOG_ALERT);
    }
  }
}

यह केवल एक आइटम को संभालता है, प्रत्येक क्रोन रन के लिए। शायद आप उसे बदलना चाहते हैं।


0

मैं भी इस के चारों ओर अपना सिर लपेटने की कोशिश कर रहा हूं, क्योंकि मैं पहली बार एलीसिया क्रोन के साथ कतार एपीआई का उपयोग कर रहा हूं। करीब से निरीक्षण करने पर आप देख सकते हैं कि जब एल्सिया_क्रॉन_रुन को कहा जाता है , तो एलिसिया क्रॉन कतार वस्तुओं को निष्पादित करता है। इस रेखा को 1044 से फ़ाइल elysia_cron.module के भीतर देखें :

if (EC_DRUPAL_VERSION >= 7) {
  // D7 Queue processing
  foreach ($queues as $queue_name => $info) {
    $function = $info['worker callback'];
    $end = time() + (isset($info['time']) ? $info['time'] : 15);
    $queue = DrupalQueue::get($queue_name);
    while (time() < $end && ($item = $queue->claimItem())) {
      $function($item->data);
      $queue->deleteItem($item);
    }
  }
}

एलीसिया क्रोन का उपयोग करते समय मेरे लिए कतार प्रसंस्करण को ध्वस्त करने में मदद मिली।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.