/** * @param $queue * * @return int */ public function processMessageQueue($queue) { if (!is_array($queue)) { if (!$queue instanceof MessageQueue) { throw new \InvalidArgumentException('$queue must be an instance of ' . MessageQueue::class); } $queue = [$queue->getId() => $queue]; } $counter = 0; $contacts = []; $byChannel = []; // Lead entities will not have profile fields populated due to the custom field use - therefore to optimize resources, // get a list of leads to fetch details all at once along with company details for dynamic email content, etc /** @var MessageQueue $message */ foreach ($queue as $message) { $contacts[$message->getId()] = $message->getLead()->getId(); } $contactData = $this->leadModel->getRepository()->getContacts($contacts); $companyData = $this->companyModel->getRepository()->getCompaniesForContacts($contacts); foreach ($contacts as $messageId => $contactId) { $contactData[$contactId]['companies'] = $companyData[$contactId]; $queue[$messageId]->getLead()->setFields($contactData[$contactId]); } // Group queue by channel and channel ID - this make it possible for processing listeners to batch process such as // sending emails in batches to 3rd party transactional services via HTTP APIs foreach ($queue as $key => $message) { if (MessageQueue::STATUS_SENT == $message->getStatus()) { unset($queue[$key]); continue; } $messageChannel = $message->getChannel(); $messageChannelId = $message->getChannelId(); if (!$messageChannelId) { $messageChannelId = 0; } if (!isset($byChannel[$messageChannel])) { $byChannel[$messageChannel] = []; } if (!isset($byChannel[$messageChannel][$messageChannelId])) { $byChannel[$messageChannel][$messageChannelId] = []; } $byChannel[$messageChannel][$messageChannelId][] = $message; } // First try to batch process each channel foreach ($byChannel as $messageChannel => $channelMessages) { foreach ($channelMessages as $messageChannelId => $messages) { $event = new MessageQueueBatchProcessEvent($messages, $messageChannel, $messageChannelId); $ignore = null; $this->dispatchEvent('process_batch_message_queue', $ignore, false, $event); } } unset($byChannel); // Now check to see if the message was processed by the listener and if not // send it through a single process event listener foreach ($queue as $message) { if (!$message->isProcessed()) { $event = new MessageQueueProcessEvent($message); $this->dispatchEvent('process_message_queue', $message, false, $event); } if ($message->isSuccess()) { ++$counter; $message->setSuccess(); $message->setLastAttempt(new \DateTime()); $message->setDateSent(new \DateTime()); $message->setStatus(MessageQueue::STATUS_SENT); } elseif ($message->isFailed()) { // Failure such as email delivery issue or something so retry in a short time $this->rescheduleMessage($message, '15M'); } // otherwise assume the listener did something such as rescheduling the message } //add listener $this->saveEntities($queue); return $counter; }