복붙노트

[REDIS] 외부 Laravel (NodeJS)로부터 Laravel 대기열로 푸시

REDIS

외부 Laravel (NodeJS)로부터 Laravel 대기열로 푸시

나는 Laravel 5.3 설치가 순수 API 응용 프로그램으로 실행하고 여러 응용 프로그램에서 연결해야합니다.

를 제외하고 내가 할 수있는 한 가지 밖에 없습니다 그림 : 모든 (P는 Laravel있어 결국 우리가 이야기하고있는) 잘 작동한다 :

나는 여러 장치 (중요하지 않음)의 메시지를 듣고있다 MQTT 서버가 있습니다. 이러한 메시지는 백엔드 호출 할 필요가 작업 클래스 및 방법에 대한 정보가 포함되어 있습니다.

나는 (그들이 있지만, 전송 데이터에 MQTT를 사용하는 것보다 훨씬 더 많은 노력이다) 장치가 간단하게이 기능을 지원하지 않는 직접 API를 호출 할 수 없습니다. 내 생각은 전화 (그리고 어떤 방법)에있는 Laravel 작업 클래스를 정의하는 큐에 새 작업을 추진했다. 문제는 JSON 직렬화입니다 ...

MQTT 서버 내 대기열 레디 스에서 실행되고, NodeJS에서 실행되고 있습니다. 나는 그가 그 이론적으로는 Laravel에 의해 처리 작업을 JSON이 필요하고 외부 Laravel에서 큐에 밀어 직렬화 및 가질 수있을 수 언급 테일러에서 트윗을 기억한다.

누구나 어떤 아이디어는 어떻게 접근 하는가? json으로의 구조에 대한 사용할 수있는 문서가 있습니까?

또한 Laravel 노동자에 의해 소비 NodeJS가 큐를 밀어이 솔루션은 나를 위해 일을하지 않았다 것을 언급해야한다. 동일한 결과 상기와 같은 작업을 큐에 배치되지만 폐기 처리없이 또는 에러가 발생된다.

A에 대한 샘플 데이터 구조는 다음과 같이 레디 스의 모습에 이벤트를 대기 :

"{\"작업 \ "\"를 분명히 \\\\ 방송 \\\\ BroadcastEvent \ ", \"데이터 \ ": {\"이벤트 \ "\"O : 28 : \\\ "앱 \\ \\ 이벤트 \\\\ NotificationEvent \\\ ": 5 : {S : 7 : \\\"\\ u0000의 * \\ u0000name \\\ ", S : 12 : \\\"통지 \\\ "; S : 4 : \\\ "\\\ 데이터"A는 4 : {(S) : 4 : \\\ "testkey \\\", S : 14 : \\\ "\\\ testVal에"; S : 9 \\\ "소인 \\\", S : 19 : \\\ "2017년 2월 24일 11시 7분 48초 \\\", S : 5 : \\\ "\\\ 이벤트"; S : 12 : \\\ "통지 \\\";의 : 5 : \\\ "클래스 \\\"; S : 28 : \\\ "앱 \\\\ 이벤트 \\\\ NotificationEvent \\\"; } S : 10 : \\\ "\\ u0000의 * \\ u0000channel \\\", N, S : 7 : \\\ "\\ u0000의 * \\ u0000user \\\", O : 45 : \\\ "를 분명히 \\\\ 계약 \\\\ 데이터베이스 \\\\ ModelIdentifier \\\": 2 : {S : 5 : \\\ "클래스 \\\"; S : 8 : \\\ "앱 \\ \\ 사용자 \\\ ";의 : 2 : \\\"ID \\\ "; 내가 : 2;}의 : 6 : \\\"소켓 \\\ "; N} \"}, \ " ID \ "\"XuUKRTf8CTSdzaVgp2gRcvmxQqLcpBUG \ ", \"시도 \ ": 1}"

그 구조를 기반으로, 나는 (요구 직렬화 할 것을)이 비슷해야 오브젝트를 생각 :

{
"job":"EventClass@method", //<-- Just a name
"data":{
    "event":"EventClass", //<-- Just a name
    "name":"EventName", //<-- Just a name
    "data":{
    "key":"value"
    "event":"EventName" //<-- Same as data.name
    "class":"EventClass@method" //<-- This is actually being called
    }
}

Laravel 실제로 큐에 그림을 그리 듯이 (타임 스탬프, 사용자 모델 식별자 등 같은),하지만 난 그 일을 실행하는 데 필요한 생각하지 않습니다 무엇에 포함 된 추가 정보가 있습니다.

데이터 요구의 PHP 직렬화보다 유사한 결과를 달성하기에 JS 직렬화 () (이상, PHP의 때 unserialize ()가 일렬 화 될 수있는 문자열 도착.

나는 PHP를 직렬화 NPM 모듈 때문에 (사이먼 스벤손에게 감사를) 할 달성하지만, 작업은 여전히 ​​Laravel에 의해 소비 (폐기가 아니라 실행)되지 않는

어떤 도움에 미리 감사드립니다 :)

편집 솔루션

사이먼의 대답 덕분에 여기 Laravel의 큐에 어떻게 직렬화하는 작업 자바 스크립트에서 데이터 푸시에 대한 해결책은 (그리고 Laravel 자동으로 모든 일을 처리해야).

이 레디 스에 큐를 사용하는 예입니다 있습니다. Beanstalkd 또는 데이터베이스를 기반으로 큐를 사용하는 경우,이 서로 다른 (여부)를 볼 수 있습니다.

이것은 내가 성공적으로 사용되는 코드입니다 :

var serialize,Class,job,jobUser,jobData,serialized,result;

serialize = require('php-serialization').serialize;
Class = require('php-serialization').Class;

job = new Class("App\\Events\\NotificationEvent");

job.__addAttr__("name","string","notification","string","protected");

jobData = new Class();
jobData.__addAttr__("testkey","string","testval","string");
jobData.__addAttr__("timestamp","string","2017-02-24 11:07:48","string");
jobData.__addAttr__("event","string","notification","string");
jobData.__addAttr__("class","string","App\\Events\\NotificationEvent","string");
job.__addAttr__("data","string",jobData,"array","public");

job.__addAttr__("channel","string",null,"null","protected");

jobUser = new Class("Illuminate\\Contracts\\Database\\ModelIdentifier")
jobUser.__addAttr__("class","string","App\\User","string","public");
jobUser.__addAttr__("id","string",2,"integer","public");
job.__addAttr__("user","string",jobUser,"object","protected");

job.__addAttr__("socket","string",null,"null","public");

serialized = serialize(job,"object");

result = {
    job:"Illuminate\\Broadcasting\\BroadcastEvent",
    data:{
        event:serialized
    },
    id:"XuUKRTf8CTSdzaVgp2gRcvmxQqLcpBUG",
    attempts:1
};

queue.rpush('queues:default',JSON.stringify(result));

나는 ID가 나는 성공적으로 항상 같은 ID를 가진 큐에 작업을 추진을 위해 정확히 무엇인지 아직 파악하지 않았습니다. 난 당신이 빠른 속도로 작업을 추진하는 경우 추측하고는이 문제가 될 수있는 동시에 저장됩니다. 이 문자열이기 때문에 당신은 당신이 원하는 임의의 ID로를 대체 할 수 (Laravel에 의해 생성 된 임의의 ID는 32 자, 나는이 길이를 유지하는 좋은 아이디어라고 생각).

처음에 작업을 밀어 때 시도는 1로 설정해야합니다. Laravel 일을 처리 할 수없는 경우에는 큐에 그것을 다시 밀어 시도 값을 증가시킬 것이다.

해결법

  1. ==============================

    1.이 Laravel 5.3의 데이터베이스 기반의 대기열에있는 작업의 형식입니다 첫째, 참고. Laravel의 최신 버전은 변경 사항이 포함되어 있습니다.

    이 Laravel 5.3의 데이터베이스 기반의 대기열에있는 작업의 형식입니다 첫째, 참고. Laravel의 최신 버전은 변경 사항이 포함되어 있습니다.

    페이로드 열은 다음과 같은 형식의 JSON 객체를 포함해야합니다. 작업이 (... \\ CallQueuedHandler @ 호출)이 시나리오에서 하드 코딩 할 수 있습니다. 나는 커맨드 이름의 키가 디스플레이 목적만을위한 것입니다 생각합니다. 명령 키 그러나, 단단한 부분, 그 때 unserialize ()를 지원하는 유효한 객체이어야한다. 이 목적을 위해 NPM에 사용 가능한 패키지가있는 것 같습니다, 빠른 검색 PHP는 직렬화를 돌았 다.

    {
        "job": "Illuminate\\Queue\\CallQueuedHandler@call",
        "data": {
            "commandName": "App\\Jobs\\MyJobClass",
            "command": "O:19:\"App\\Jobs\\MyJobClass\"... /* stuff */"
        }
    }
    

    json으로는 다음과 같은 객체의 결과를 제공 한 페이로드. 작업 및 데이터 키는 모두 중요하다.

    {
      "job": "Illuminate\\Broadcasting\\BroadcastEvent",
      "data": {
        "event": "O:28:\"App\\Events\\NotificationEvent\":5:{s:7:\"\u0000*\u0000name\";s:12:\"notification\";s:4:\"data\";a:4:{s:4:\"testkey\";s:14:\"testval\";s:9:\"timestamp\";s:19:\"2017-02-24 11:07:48\";s:5:\"event\";s:12:\"notification\";s:5:\"class\";s:28:\"App\\Events\\NotificationEvent\";}s:10:\"\u0000*\u0000channel\";N;s:7:\"\u0000*\u0000user\";O:45:\"Illuminate\\Contracts\\Database\\ModelIdentifier\":2:{s:5:\"class\";s:8:\"App\\User\";s:2:\"id\";i:2;}s:6:\"socket\";N;}"
      },
      "id": "XuUKRTf8CTSdzaVgp2gRcvmxQqLcpBUG",
      "attempts": 1
    }
    

    문제가있는 부분은, 나는 가정, 직렬화 된 객체입니다. 쉽게 읽을 수있는 방식으로 포맷 (하지만 완전히 그것을 나누기) ...

    O:28:"App\Events\NotificationEvent":5:{
        // protected $name = 'notification'
        s:7:" * name";s:12:"notification";
    
        // public $data = array(...)
        s:4:"data";a:4:{
            // 'testkey => 'testval'
            s:4:"testkey";s:14:"testval";
    
            // 'timestamp' => '2017-02-24 11:07:48';
            s:9:"timestamp";s:19:"2017-02-24 11:07:48";
    
            // 'event' => 'notification';
            s:5:"event";s:12:"notification";
    
            // 'class' => App\Events\NotificationEvent::class;
            s:5:"class";s:28:"App\Events\NotificationEvent";
        }
    
        // protected $channel = null;
        s:10:"\0*\0channel";N;
    
        // protected $user = (instance of ModelIdentifier)
        s:7:"\0*\0user";O:45:"Illuminate\Contracts\Database\ModelIdentifier":2:{
            // public $class = App\User::class;
            s:5:"class";s:8:"App\User";
    
            // public $id = 2;
            s:2:"id";i:2;
        }
    
        // public $socket = null;
        s:6:"socket";N;
    }
    

    이 형식은 당신의 작업이 SerializesModels 클래스 + 식별자를 포함하는 간단한 항목으로 모델이 대체합니다 참조를 특징 부 (trait) 사용하고 __wakeup 동안 복원 것이라는 사실을 노출합니다.

    나는 당신의 문제는 JSON과 직렬화 형식의 정신 분석과 판단; 당신의 추측 구조는 ... 잘못된.

    다음 단계는 아무것도 추측하지 않을 것입니다. 이 정확한 테스트 알림을 중복 1. 당신은 이미에 대한 페이로드를 가지고있다. 그냥 복사 - 붙여 넣기를. (당신은 내가이 중복 제거에 사용되는 추측 ID를 변경해야 할 수도 있습니다.) 2. 빌드와 PHP 직렬화를 사용하여 이벤트 데이터는 원래 이벤트 페이로드와 동일 무언가를 구축하는 것을 목표로하고 있습니다. 아니 전혀 변경됩니다. 이 여기까지 작동하는 경우 3. 어떻게되는지 직렬화 된 이벤트 데이터를 변경 주시기 바랍니다.

  2. ==============================

    2.이 솔루션은 매우 지저분하고 미래에 작동하지 않을 수 있습니다,하지만 ...

    이 솔루션은 매우 지저분하고 미래에 작동하지 않을 수 있습니다,하지만 ...

    당신은 대기열에 작업을 전송의 "옛날 방식"을 복제 할 수 있습니다 :

    \Queue::push('\Namespace\Of\Class@handlerMethod', ['foo' => 'bar']);
    

    그리고 핸들러 :

    public function handlerMethods($job, $data)
    {
        $job->delete;
        // do whatever with data
    }
    

    Node.js를에서 당신이 뭔가를 같이 할 것입니다 :

    SQS.sendMessage({
        MessageBody: JSON.stringify({
            job: '\Namespace\Of\Class@handlerMethod',
            data: {
                foo: 'bar',
            }
        }),
        QueueUrl: yourQueueUrl
     }, err => { /* handle */ });
    

    단점

    자신의 위험에이 작업을 수행하지만, 여기의 증명이 가능합니다.

  3. ==============================

    3.는 "고전적인"작업에 갈 필요가 사람들을 위해, 여기에 월 Schuermanns 원래의 질문 및 솔루션을 기반으로, 코드입니다 :

    는 "고전적인"작업에 갈 필요가 사람들을 위해, 여기에 월 Schuermanns 원래의 질문 및 솔루션을 기반으로, 코드입니다 :

    const php = require('php-serialization');
    
    var job_class = 'App\\Jobs\\TestJob';
    var data = {}
    
    job = new php.Class(job_class);
    
    job.__addAttr__("data","string", JSON.stringify(data),"string","private");
    
    result = {
        id: 1,
        type: 'job',
        displayName: job_class,
        job: "Illuminate\\Queue\\CallQueuedHandler@call",
        maxTries: null,
        delay: null,
        timeout: null,
        timeoutAt: null,
        data: {
            commandName: job_class,
            command: php.serialize(job, "object")
        }
    };
    

    샘플 작업 클래스 :

    <?php
    
    namespace App\Jobs;
    
    use Illuminate\Contracts\Queue\ShouldQueue;
    
    class TestJob implements ShouldQueue
    {
        private $data;
    
        public function __construct($data)
        {
            $this->data = $data;
        }
    
        public function handle() {
            var_dump(json_decode($this->data));
            return;
        }
    }
    

    으로 이끌다:

    [2019-08-17 ...] Processing: App\Jobs\TestJob
    object(stdClass)#1870 (0) {
    }
    [2019-08-17 ...] Processed:  App\Jobs\TestJob
    

    편집하다: 당신이 움라우트 또는 기타 특수 문자를 처리해야하는 경우의 iconv 라이트와 라틴 사용해야 할 수 있습니다 :

    iconv.decode(Buffer.from(JSON.stringify(data)), 'latin1')
    

    job.__addAttr__("data","string", JSON.stringify(data),"string","private");
    
    ...
    queueChannel.sendToQueue(queuePublish, Buffer.from(JSON.stringify(result), 'latin1'));
    
  4. from https://stackoverflow.com/questions/42465455/push-to-laravel-queue-from-outside-laravel-nodejs by cc-by-sa and MIT license