getIpAddresses() as $ipAddress) { $this->insertIpAddressReference($contact, $ipAddress); } } /** * @param string $ip * * @return IpAddress|null */ public function findOneByIpAddress($ip) { return $this->entityManager->getRepository(IpAddress::class)->findOneByIpAddress($ip); } /** * Tries to insert the Lead/IP relation and continues even if UniqueConstraintViolationException is thrown. */ private function insertIpAddressReference(Lead $contact, IpAddress $ipAddress): void { $ipAddressAdded = isset($contact->getChanges()['ipAddressList'][$ipAddress->getIpAddress()]); if (!$ipAddressAdded || !$ipAddress->getId() || !$contact->getId()) { return; } $qb = $this->entityManager->getConnection()->createQueryBuilder(); $values = [ 'lead_id' => ':leadId', 'ip_id' => ':ipId', ]; $qb->insert(MAUTIC_TABLE_PREFIX.'lead_ips_xref'); $qb->values($values); $qb->setParameter('leadId', $contact->getId()); $qb->setParameter('ipId', $ipAddress->getId()); try { $qb->executeStatement(); } catch (UniqueConstraintViolationException) { $this->logger->warning("The reference for contact {$contact->getId()} and IP address {$ipAddress->getId()} is already there. (Unique constraint)"); } catch (ForeignKeyConstraintViolationException) { $this->logger->warning("The reference for contact {$contact->getId()} and IP address {$ipAddress->getId()} is already there. (Foreign key constraint)"); } $this->entityManager->detach($ipAddress); } /** * @throws \Doctrine\DBAL\Exception */ public function deleteUnusedIpAddresses(int $limit): int { /** @var IpAddressRepository $ipAddressRepo */ $ipAddressRepo = $this->entityManager->getRepository(IpAddress::class); $ipIds = $ipAddressRepo->getUnusedIpAddressesIds($limit); $chunkedIds = array_chunk($ipIds, self::DELETE_SIZE); $count = 0; foreach ($chunkedIds as $ids) { $count += $ipAddressRepo->deleteUnusedIpAddresses($ids); // Use sleep to recover from any potential table locks. usleep(50000); } return $count; } }