2015-09-10 14 views
5

通常、Laravelは、後で消費するメッセージをキューに入れることを想定しています。後でキューメッセージの処理方法を示すjob属性を持つペイロードを作成します。 Laravelでジョブをキューに入れ、後でLaravelで処理すると、うまくいきます!未処理のjsonキューメッセージをLaravelで消費する

しかし、キューにjsonメッセージを投稿しているLaravel以外のアプリがあります。私はこれらのメッセージを受け取り、それらを処理するためにLaravelが必要です。

私はメッセージを処理するコマンドバスジョブを書くことができますが、私は特定のハンドラにメッセージを送信するようにqueue:workに指示する方法を見つけることができませんでした。

Laravelは、扱うように要求されたキューメッセージは、正しくフォーマットされ、シリアライズされ、期待どおりに構造化されるという難しい前提があります。

Laravelにこれらの生のjsonペイロードを持たせるにはどうしたらいいですか?構造を無視してください(単純にペイロードをハンドラに渡します)。

私はに似キューメッセージがある場合たとえば、:

{ 
    "foo" : "bar" 
} 

をので、もう一度、ここで検査または理解するLaravelのためはありません。

しかし、私はこれを処理する方法を知っている仕事のハンドラがあります。今、単純に私は私の上の残りの部分を行うことができ、このApp\Jobs\MyQueueHandlerハンドラに任意のペイロードをハンドオフするqueue:workqueue:listenを取得する方法を

namespace App\Jobs; 

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

を自分の?

答えて

0

あなたはLaravelのバージョンを指定していないので、私は5.1を推測しています(これはL4.2とL5.xでどのように処理されるかの大きな違いです)。あなたはすでにあなたのApp\Jobs\MyQueueHandlerを設定し、あなたが望む任意のデータを使用して、コントローラからのジョブをキューにしたいしている場合

、あなただけのこの操作を行うことができます。

あなた MyQueueHandler級で
use App\Jobs\MyQueueHandler; 

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

、ペイロードは実際にコンストラクタに入ります。あなたのキューが処理されても、handleメソッドはまだ起動されています。あなたは依存性の注入に依存している場合(「物事は間違って行くとき」の真上、read more here)ただし、あなたのhandle -methodのパラメータを使用することができますので、このようなものは、それを行う必要があります。

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

LearvelがGearmanペイロード(\Illuminate\Bus\Dispatcher参照)を実行しようとするため、あなたが求めるものはありません。

私は同じ状況にあり、Laravelジョブクラスのラッパーcommandを作成しました。jsonキューに入ってイベントを再キューに入れるので、これは最も良い解決策ではありませんが、既存のジョブクラスに触れる必要はありません。たぶん、経験豊富な人は実際にワイヤで再びジョブを送信せずにジョブをディスパッチする方法を知っているかもしれません。

GenerateIdentApplicationPdfJobと呼ばれる1つの標準的なLaravelワーカークラスがあるとします。

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) 
    { 
     // ... 
    } 
} 

このクラスを処理できるようにするには、独自のコンストラクタ引数を指定する必要があります。これらは私たちのjsonキューから必要なデータです。

以下はLearvel commandクラスGearmanPdfWorkerです.Gearman接続のすべての定型文を実行し、元のジョブクラスを処理できるようにするにはです。場所にすべてのことを持っ

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

    // ... 

、あなたが労働者を実行するためにphp artisan pdf:workerを呼び出すことができます。

クラス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に登録する必要があります拡張しますコマンドライン経由でGearmanにジョブを1つ入れてください: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。エッジの周りに少し荒いが、それは働いた。 SQSから未処理のjsonペイロードを取り出し、ハンドラに渡すことができます。私はIronMQのためにそれをかなり簡単に拡張しました。 – jszobody

+0

私はそのライブラリ(rabbitmqを使用して)を実装するのに苦労しています、あなたはあなたの旅行の任意のコードサンプルに出くわしましたか?ありがとう – mils

関連する問題