namespace App\Events;
+use http\Exception\InvalidArgumentException;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
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;
}
/**
*/
public function broadcastOn()
{
- return new PrivateChannel('emailBatch.'.$this->batch_id);
+ return new PrivateChannel('emailBatch.'.$this->data['batch_id']);
}
namespace App\Jobs;
use App\EmailBatch;
+use App\Events\ProcessBatch;
use App\User;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
+use Illuminate\Support\Arr;
use Mailgun\Mailgun;
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,
'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
+ ]);
"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",
mounted: function mounted() {
Echo["private"]('emailBatch.1').listen('.mailgun.event', function (e) {
console.log(e);
+ }).listen('.batch.status', function (e) {
+ console.log(e);
});
},
methods: {}
//
//
//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
/* 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;
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;
});
}
},
_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 = [
.listen('.mailgun.event', (e) => {
console.log(e);
})
+ .listen('.batch.status', (e) => {
+ console.log(e);
+ })
},
methods: {
</div>
<div>
- <button class="btn btn-danger" @click="publish">Envoyer {{recipients_count}} emails !</button>
+ <button class="btn btn-danger d-block m-auto" @click="publish">Envoyer {{recipients_count}} emails !</button>
+ </div>
+
+
+ <div class="alert alert-success my-3" v-if="publishing">
+ <strong>Statut : </strong>{{status}}
+ </div>
+
+ <div id="counters" class="row" v-if="publishing">
+ <div class="col-6">Reçus : {{counters.delivered}}</div>
+ <div class="col-6">Ouverts : {{counters.opened}}</div>
+
</div>
return {
upload_result: this.$root.publishState.file,
recipients_count: 0,
+ status: 'En attente',
+ counters : {
+ delivered : 0,
+ opened : 0
+ },
+ publishing: false,
}
},
computed: {
},
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`;
+ }
},
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;
})