From 0ca8918aec8d0198c2fd7ddda793ba2a58859895 Mon Sep 17 00:00:00 2001 From: Louis Jeckel Date: Tue, 7 Apr 2020 21:14:43 +0200 Subject: [PATCH] step 3 ws pusher --- app/Events/ProcessBatch.php | 24 +++++----- app/Jobs/ProcessEmailBatch.php | 41 ++++++++++++++-- composer.json | 3 +- public/js/app.js | 69 ++++++++++++++++++++++++--- resources/js/components/LiveStats.vue | 3 ++ resources/js/components/Step3Send.vue | 46 ++++++++++++++++-- 6 files changed, 157 insertions(+), 29 deletions(-) diff --git a/app/Events/ProcessBatch.php b/app/Events/ProcessBatch.php index 12f7347..c0870a4 100644 --- a/app/Events/ProcessBatch.php +++ b/app/Events/ProcessBatch.php @@ -2,6 +2,7 @@ namespace App\Events; +use http\Exception\InvalidArgumentException; use Illuminate\Broadcasting\Channel; use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Broadcasting\PresenceChannel; @@ -9,27 +10,26 @@ use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Queue\SerializesModels; +use Illuminate\Support\Arr; -class ProcessBatch +class ProcessBatch implements ShouldBroadcast { use Dispatchable, InteractsWithSockets, SerializesModels; + + public $data; /** * Create a new event instance. * - * @param $status - * @param $totalBatches - * @param $currentBatches + * @param $data */ - public function __construct($status, $totalBatches, $currentBatches) + public function __construct($data) { - // - $this->data = [ - 'status' => $status, - 'totalBatches' => $totalBatches, - 'currentBatches' => $currentBatches, - ]; + if(! Arr::has($data, ['batch_id', 'status'])) { + throw new InvalidArgumentException('Missing args'); + } + $this->data = $data; } /** @@ -39,7 +39,7 @@ class ProcessBatch */ public function broadcastOn() { - return new PrivateChannel('emailBatch.'.$this->batch_id); + return new PrivateChannel('emailBatch.'.$this->data['batch_id']); } diff --git a/app/Jobs/ProcessEmailBatch.php b/app/Jobs/ProcessEmailBatch.php index bed26bd..49b2fc9 100644 --- a/app/Jobs/ProcessEmailBatch.php +++ b/app/Jobs/ProcessEmailBatch.php @@ -3,6 +3,7 @@ namespace App\Jobs; use App\EmailBatch; +use App\Events\ProcessBatch; use App\User; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; @@ -10,6 +11,7 @@ use Illuminate\Database\Eloquent\Collection; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; +use Illuminate\Support\Arr; use Mailgun\Mailgun; class ProcessEmailBatch implements ShouldQueue @@ -27,22 +29,41 @@ class ProcessEmailBatch implements ShouldQueue */ public function __construct(EmailBatch $batch) { - // $this->batch = $batch; } + protected function processUpdate($data) + { + event(new ProcessBatch(array_merge($data, [ + 'batch_id' => $this->batch->id + ]))); + + } + /** * Execute the job. * * @return void + * @throws \Throwable */ public function handle() { /** @var Collection $users */ $users = User::subscribed()->get(); - $users->chunk(200)->each(function(Collection $chunk) { - $mailgun = resolve(Mailgun::class); + $size = 2; + $chunks = $users->chunk($size); + + $this->processUpdate([ + 'status' => 'processing', + 'total' => $count = $users->count(), + 'current' => 0 + ]); + $i = 0; + $mailgun = resolve(Mailgun::class); + + foreach($chunks as $chunk) { + $variables = json_encode($chunk->mapWithKeys(function($user) { return [$user->email => [ 'id' => $user->id, @@ -62,12 +83,22 @@ class ProcessEmailBatch implements ShouldQueue 'recipient-variables' => $variables, 'html' => $view, 'o:tag' => ['batch_id_'.$this->batch->id, 'test_psq'], - 'o:tracking' => true, ]; $mailgun->messages()->send(env('MAILGUN_DOMAIN'), $params); + $this->processUpdate([ + 'status' => 'processing', + 'total' => $count, + 'current' => ($i++)*$size + $chunk->count() + ]); + + } - }); + $this->processUpdate([ + 'status' => 'done', + 'total' => $count, + 'current' => $count + ]); diff --git a/composer.json b/composer.json index cfdb1c0..2a42c17 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,8 @@ "mailgun/mailgun-php": "^3.0", "nyholm/psr7": "^1.2", "pusher/pusher-php-server": "~4.0", - "vaites/php-apache-tika": "^0.9.1" + "vaites/php-apache-tika": "^0.9.1", + "ext-http": "*" }, "require-dev": { "facade/ignition": "^2.0", diff --git a/public/js/app.js b/public/js/app.js index 031ae3b..d043a11 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -4446,6 +4446,8 @@ __webpack_require__.r(__webpack_exports__); mounted: function mounted() { Echo["private"]('emailBatch.1').listen('.mailgun.event', function (e) { console.log(e); + }).listen('.batch.status', function (e) { + console.log(e); }); }, methods: {} @@ -4942,18 +4944,50 @@ __webpack_require__.r(__webpack_exports__); // // // +// +// +// +// +// +// +// +// +// +// +// /* harmony default export */ __webpack_exports__["default"] = ({ components: {}, data: function data() { return { upload_result: this.$root.publishState.file, - recipients_count: 0 + recipients_count: 0, + status: 'En attente', + counters: { + delivered: 0, + opened: 0 + }, + publishing: false }; }, computed: {}, methods: { - processEvent: function processEvent(e) { - console.log(e); + processMailEvent: function processMailEvent(e) { + if (e.data.event === 'delivered') this.counters.delivered++; + if (e.data.event === 'opened') this.counters.opened++; + }, + processProgressEvent: function processProgressEvent(e) { + switch (e.data.status) { + case 'init': + this.status = "Préparation en cours"; + break; + + case 'processing': + this.status = "Traitement en cours : (".concat(e.data.current, " / ").concat(e.data.total, ")"); + break; + + case 'done': + this.status = "Termin\xE9, ".concat(e.data.total, " emails envoy\xE9s"); + } }, publish: function publish() { var _this = this; @@ -4965,7 +4999,8 @@ __webpack_require__.r(__webpack_exports__); data: this.$root.publishState } }).then(function (d) { - Echo["private"]("emailBatch.".concat(d.data)).listen('.mailgun.event', _this.processEvent); + Echo["private"]("emailBatch.".concat(d.data.data)).listen('.mailgun.event', _this.processMailEvent).listen('.batch.status', _this.processProgressEvent); + _this.publishing = true; }); } }, @@ -51690,10 +51725,32 @@ var render = function() { _c("div", [ _c( "button", - { staticClass: "btn btn-danger", on: { click: _vm.publish } }, + { + staticClass: "btn btn-danger d-block m-auto", + on: { click: _vm.publish } + }, [_vm._v("Envoyer " + _vm._s(_vm.recipients_count) + " emails !")] ) - ]) + ]), + _vm._v(" "), + _vm.publishing + ? _c("div", { staticClass: "alert alert-success my-3" }, [ + _c("strong", [_vm._v("Statut : ")]), + _vm._v(_vm._s(_vm.status) + "\n ") + ]) + : _vm._e(), + _vm._v(" "), + _vm.publishing + ? _c("div", { staticClass: "row", attrs: { id: "counters" } }, [ + _c("div", { staticClass: "col-6" }, [ + _vm._v("Reçus : " + _vm._s(_vm.counters.delivered)) + ]), + _vm._v(" "), + _c("div", { staticClass: "col-6" }, [ + _vm._v("Ouverts : " + _vm._s(_vm.counters.opened)) + ]) + ]) + : _vm._e() ]) } var staticRenderFns = [ diff --git a/resources/js/components/LiveStats.vue b/resources/js/components/LiveStats.vue index a28d5da..eacd278 100644 --- a/resources/js/components/LiveStats.vue +++ b/resources/js/components/LiveStats.vue @@ -21,6 +21,9 @@ .listen('.mailgun.event', (e) => { console.log(e); }) + .listen('.batch.status', (e) => { + console.log(e); + }) }, methods: { diff --git a/resources/js/components/Step3Send.vue b/resources/js/components/Step3Send.vue index 3f77b3f..d9f82f0 100644 --- a/resources/js/components/Step3Send.vue +++ b/resources/js/components/Step3Send.vue @@ -14,7 +14,18 @@
- + +
+ + +
+ Statut : {{status}} +
+ +
+
Reçus : {{counters.delivered}}
+
Ouverts : {{counters.opened}}
+
@@ -42,6 +53,12 @@ return { upload_result: this.$root.publishState.file, recipients_count: 0, + status: 'En attente', + counters : { + delivered : 0, + opened : 0 + }, + publishing: false, } }, computed: { @@ -49,8 +66,25 @@ }, methods: { - processEvent(e) { - console.log(e); + processMailEvent(e) { + if(e.data.event === 'delivered') + this.counters.delivered++; + if(e.data.event === 'opened') + this.counters.opened++; + + }, + + processProgressEvent(e) { + switch(e.data.status){ + case 'init': + this.status = "Préparation en cours"; + break; + case 'processing': + this.status = `Traitement en cours : (${e.data.current} / ${e.data.total})`; + break; + case 'done': + this.status = `Terminé, ${e.data.total} emails envoyés`; + } }, @@ -61,8 +95,10 @@ data: {data: this.$root.publishState} }).then(d => { - Echo.private(`emailBatch.${d.data}`) - .listen('.mailgun.event', this.processEvent); + Echo.private(`emailBatch.${d.data.data}`) + .listen('.mailgun.event', this.processMailEvent) + .listen('.batch.status', this.processProgressEvent); + this.publishing = true; }) -- 2.39.5