2015-09-10 17 views
5

में कच्चे जेसन कतार संदेश का उपभोग करें आम तौर पर लैरवेल उम्मीद करता है कि यह किसी भी संदेश को कतारबद्ध करता है जिसे बाद में उपभोग करता है। यह job विशेषता के साथ एक पेलोड बनाता है जो बाद में इंगित करता है कि कतार संदेश को कैसे संभालना है। जब आप लार्वेल के साथ नौकरियां कतार करते हैं, और बाद में उन्हें लार्वेल के साथ संसाधित करते हैं, तो यह बहुत अच्छा काम करता है!लार्वेल

हालांकि, मेरे पास कुछ गैर-लैरवेल ऐप्स हैं जो एक कतार में जेसन संदेश पोस्ट कर रहे हैं। मुझे इन संदेशों को लेने और उन्हें संभालने के लिए लार्वेल की जरूरत है।

मैं संदेशों को संभालने के लिए एक कमांड बस नौकरी लिख सकता हूं, लेकिन मैं अपने विशिष्ट हैंडलर पर संदेश भेजने के लिए queue:work को कैसे बताना है, यह समझने में सक्षम नहीं हूं।

ऐसा लगता है कि लैरवेल को एक कठिन धारणा है कि किसी भी कतार संदेश को संभालने के लिए कहा जाता है, जिसे उचित रूप से स्वरूपित किया जाएगा, क्रमबद्ध किया जाएगा, और जिस तरह से यह अपेक्षा करता है उसे संरचित किया जाएगा।

लैरवेल इन कच्चे जेसन पेलोड को कैसे उठा सकता है, संरचना को अनदेखा कर सकता है (समझने के लिए वहां कुछ भी नहीं है), और बस मेरे हैंडलर को पेलोड बंद कर दें?

उदाहरण के लिए, अगर मैं करने के लिए इसी तरह की एक कतार संदेश है: तो फिर

{ 
    "foo" : "bar" 
} 

, वहाँ Laravel का निरीक्षण या यहाँ समझने के लिए कुछ भी नहीं है।

लेकिन मैं एक नौकरी हैंडलर को पता है कि यह कैसे संभाल करने के लिए है:

namespace App\Jobs; 

class MyQueueHandler { 
    public function handle($payload) { 
     Log::info($payload['foo']); // yay! 
    } 
} 

अब कैसे बस इस App\Jobs\MyQueueHandler हैंडलर, जहां मैं पर आराम कर सकते हैं के लिए किसी भी पेलोड बंद हाथ करने के लिए queue:work और queue:listen पाने के लिए मेरी स्वामी हैं?

उत्तर

0

आपने लैरवेल का कौन सा संस्करण निर्दिष्ट नहीं किया है, इसलिए मैं 5.1 अनुमान लगा रहा हूं (यह एल 4.2 और एल 5.एक्स में कैसे संभाला जाता है में बड़ा अंतर)।

आप पहले से ही अपने App\Jobs\MyQueueHandler की स्थापना की है, और एक नियंत्रक से नौकरी क़तार में, किसी भी डेटा आप चाहते हैं का उपयोग कर चाहते हैं, तो आप सिर्फ यह कर सकते हैं:

use App\Jobs\MyQueueHandler; 

class MyController 
{ 
    public function myFunction() 
    { 
     $this->dispatch(new MyQueueHandler(['foo' => 'bar'])); 
    } 
} 

अपने MyQueueHandler श्रेणी में, पेलोड वास्तव में आपके कन्स्ट्रक्टर में प्रवेश करता है। यद्यपि आपकी कतार संसाधित होने पर हैंडल-विधि अभी भी निकाल दी गई है। हालांकि, अपने handle -method पर पैरामीटर का उपयोग कर सकते हैं अगर आप dependancy इंजेक्शन पर भरोसा करते हैं (read more here, बस ऊपर "जब चीजें जाओ गलत") तो कुछ इस तरह यह करना चाहिए:

namespace App\Jobs; 

class MyQueueHandler 
{ 

    protected $payload; 

    public function __construct($payload) 
    { 
     $this->payload = $payload; 
    } 

    public function handle() { 
     Log::info($this->payload['foo']); // yay! 
    } 
} 

नोट: यदि आप चाहते हैं एक मुख्य नियंत्रक (कि मानक App\Http\Controller श्रेणी से विरासत के बाहर से काम प्रेषण करने के लिए, DispatchesJobs विशेषता का उपयोग करें;।

MyClass 
{ 
    use DispatchesJobs; 

    public function myFunction() 
    { 
     $this->dispatch(new MyQueueHandler(['foo' => 'bar'])); 
    } 
} 

(कोड Laravel 5.1.19 के साथ परीक्षण किया और beanstalkd कतार-अनुकूलक)

0

जो आप पूछते हैं वह संभव नहीं है क्योंकि लैरावेल गियरमैन पेलोड को निष्पादित करने का प्रयास करता है (\Illuminate\Bus\Dispatcher देखें)।

मैं एक ही स्थिति में था और लैरवेल नौकरी कक्षा के आसपास एक रैपर command बनाया।यह सबसे अच्छा समाधान नहीं है क्योंकि यह जेसन कतार पर आने वाली घटनाओं को दोबारा कतार देगा, लेकिन आपको मौजूदा नौकरी कक्षाओं को छूने की जरूरत नहीं है। हो सकता है कि अधिक अनुभव वाला कोई व्यक्ति जानता है कि वास्तव में तार पर इसे भेजने के बिना नौकरी कैसे प्रेषित करें।

मान लें कि हमारे पास एक नियमित लैरवेल कार्यकर्ता वर्ग है जिसे GenerateIdentApplicationPdfJob कहा जाता है।

class GenerateIdentApplicationPdfJob extends Job implements SelfHandling, ShouldQueue 
{ 
    use InteractsWithQueue, SerializesModels; 

    /** @var User */ 
    protected $user; 

    protected $requestId; 

    /** 
    * Create a new job instance. 
    * 
    * QUEUE_NAME = 'ident-pdf'; 
    * 
    * @param User $user 
    * @param  $requestId 
    */ 
    public function __construct(User $user, $requestId) 
    { 
     $this->user  = $user; 
     $this->requestId = $requestId; 
    } 

    /** 
    * Execute the job. 
    * 
    * @return void 
    */ 
    public function handle(Client $client) 
    { 
     // ... 
    } 
} 

इस कक्षा को संभालने में सक्षम होने के लिए, हमें अपने स्वयं के कन्स्ट्रक्टर तर्क प्रदान करने की आवश्यकता है। वे हमारे जेसन कतार से आवश्यक डेटा हैं।

नीचे एक Laravel command वर्ग GearmanPdfWorker, करता है जो सभी Gearman कनेक्शन की बॉयलरप्लेट और json_decode मूल काम वर्ग को संभालने के लिए सक्षम होने के लिए है।

वर्ग GearmanPdfWorker फैली कमान {

/** 
    * The console command name. 
    * 
    * @var string 
    */ 
    protected $name = 'pdf:worker'; 

    /** 
    * The console command description. 
    * 
    * @var string 
    */ 
    protected $description = 'listen to the queue for pdf generation jobs'; 

    /** 
    * @var \GearmanClient 
    */ 
    private $client; 

    /** 
    * @var \GearmanWorker 
    */ 
    private $worker; 

    public function __construct(\GearmanClient $client, \GearmanWorker $worker) { 
     parent::__construct(); 
     $this->client = $client; 
     $this->worker = $worker; 
    } 

    /** 
    * Wrapper listener for gearman jobs with plain json payload 
    * 
    * @return mixed 
    */ 
    public function handle() 
    { 
     $gearmanHost = env('CB_GEARMAN_HOST'); 
     $gearmanPort = env('CB_GEARMAN_PORT'); 

     if (!$this->worker->addServer($gearmanHost, $gearmanPort)) { 
      $this->error('Error adding gearman server: ' . $gearmanHost . ':' . $gearmanPort); 
      return 1; 
     } else { 
      $this->info("added server $gearmanHost:$gearmanPort"); 
     } 

     // use a different queue name than the original laravel command, since the payload is incompatible 
     $queueName = 'JSON.' . GenerateIdentApplicationPdfJob::QUEUE_NAME; 
     $this->info('using queue: ' . $queueName); 

     if (!$this->worker->addFunction($queueName, 
      function(\GearmanJob $job, $args) { 
       $queueName = $args[0]; 
       $decoded = json_decode($job->workload()); 
       $this->info("[$queueName] payload: " . print_r($decoded, 1)); 

       $job = new GenerateIdentApplicationPdfJob(User::whereUsrid($decoded->usrid)->first(), $decoded->rid); 
       $job->onQueue(GenerateIdentApplicationPdfJob::QUEUE_NAME); 
       $this->info("[$queueName] dispatch: " . print_r(dispatch($job))); 
      }, 
      [$queueName])) { 
      $msg = "Error registering gearman handler to: $queueName"; 
      $this->error($msg); 
      return 1; 
     } 

     while (1) { 
      $this->info("Waiting for job on `$queueName` ..."); 
      $ret = $this->worker->work(); 
      if ($this->worker->returnCode() != GEARMAN_SUCCESS) { 
       $this->error("something went wrong on `$queueName`: $ret"); 
       break; 
      } 
      $this->info("... done `$queueName`"); 
     } 
    } 
} 

वर्ग GearmanPdfWorker जरूरतों अपने \Bundle\Console\Kernel में पंजीकृत होने के लिए इस तरह:

class Kernel extends ConsoleKernel 
{ 
    protected $commands = [ 
     // ... 
     \Bundle\Console\Commands\GearmanPdfWorker::class 
    ]; 

    // ... 

ही स्थान में सभी कि बीत रहा है, आप कार्यकर्ता को चलाने के लिए php artisan pdf:worker कॉल कर सकते हैं और कमांडलाइन के माध्यम से गियरमैन में एक नौकरी डालें: gearman -v -f JSON.ident-pdf '{"usrid":9955,"rid":"ABC4711"}'

आप देख सकते हैं सफल ऑपरेशन

added server localhost:4730 
using queue: JSON.ident-pdf 
Waiting for job on `JSON.ident-pdf` ... 
[JSON.ident-pdf] payload: stdClass Object 
(
    [usrid] => 9955 
    [rid] => ABC4711 
) 

0[JSON.ident-pdf] dispatch: 1 
... done `JSON.ident-pdf` 
Waiting for job on `JSON.ident-pdf` ... 
+0

मुझे वापस आना चाहिए और अपडेट होना चाहिए था। मैं इस पैकेज को खोजने के लिए समाप्त हो गया: https://github.com/kristianedlund/laravel-external-queue। किनारों के चारों ओर मोटा बिट, लेकिन यह काम किया। मुझे एसक्यूएस से कच्चे जेसन पेलोड लेने और उन्हें हैंडलर को सौंपने की अनुमति देता है। मैंने इसे आयरनएमक्यू के लिए भी काफी आसानी से बढ़ाया। – jszobody

+0

मैं उस पुस्तकालय को लागू करने के लिए संघर्ष कर रहा हूं (खरगोश का उपयोग करके), क्या आप अपनी यात्रा में किसी भी कोड के नमूने में आए थे? धन्यवाद – mils