Compare commits
No commits in common. "7984461d2c4ed0800f811b43fa487e27c6ae95f7" and "5c1db6f948fdc9215dc8c00a6c32a6b97e8b05c5" have entirely different histories.
7984461d2c
...
5c1db6f948
|
|
@ -1,34 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace DoctrineMigrations;
|
|
||||||
|
|
||||||
use Doctrine\DBAL\Schema\Schema;
|
|
||||||
use Doctrine\Migrations\AbstractMigration;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Auto-generated Migration: Please modify to your needs!
|
|
||||||
*/
|
|
||||||
final class Version20260116104840 extends AbstractMigration
|
|
||||||
{
|
|
||||||
public function getDescription(): string
|
|
||||||
{
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function up(Schema $schema): void
|
|
||||||
{
|
|
||||||
// this up() migration is auto-generated, please modify it to your needs
|
|
||||||
$this->addSql('DROP INDEX unique_quartal');
|
|
||||||
$this->addSql('CREATE UNIQUE INDEX unique_quartal ON contacts (phone_number, due_quartal) WHERE due_quartal IS NOT NULL');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function down(Schema $schema): void
|
|
||||||
{
|
|
||||||
// this down() migration is auto-generated, please modify it to your needs
|
|
||||||
$this->addSql('CREATE SCHEMA public');
|
|
||||||
$this->addSql('DROP INDEX unique_quartal');
|
|
||||||
$this->addSql('CREATE INDEX unique_quartal ON contacts (phone_number, due_quartal) WHERE (due_quartal IS NOT NULL)');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -5,8 +5,6 @@ declare(strict_types=1);
|
||||||
namespace App\Command;
|
namespace App\Command;
|
||||||
|
|
||||||
use App\Entity\Contacts;
|
use App\Entity\Contacts;
|
||||||
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
|
|
||||||
use Doctrine\Persistence\ManagerRegistry;
|
|
||||||
use Symfony\Component\Uid\Uuid;
|
use Symfony\Component\Uid\Uuid;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use League\Csv\Reader;
|
use League\Csv\Reader;
|
||||||
|
|
@ -35,9 +33,8 @@ final class CleanMobileCommand extends Command
|
||||||
private string $backendApiURL = 'https://umfragetool.ukbonn.de/api/api/participant/create-qm-befr-participant';
|
private string $backendApiURL = 'https://umfragetool.ukbonn.de/api/api/participant/create-qm-befr-participant';
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private EntityManagerInterface $em,
|
private readonly EntityManagerInterface $em,
|
||||||
private readonly HttpClientInterface $http,
|
private readonly HttpClientInterface $http
|
||||||
private readonly ManagerRegistry $doctrine,
|
|
||||||
) {
|
) {
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
}
|
}
|
||||||
|
|
@ -222,8 +219,7 @@ final class CleanMobileCommand extends Command
|
||||||
// Create a Contact entity for DB insertion
|
// Create a Contact entity for DB insertion
|
||||||
$contact = new Contacts();
|
$contact = new Contacts();
|
||||||
$contact->setPhoneNumber($row['HANDY_E164']);
|
$contact->setPhoneNumber($row['HANDY_E164']);
|
||||||
$today = new \DateTime('today');
|
$dueDate = (new \DateTime('today'))->setTime(12, 0, 0);
|
||||||
$dueDate = ($today)->setTime(12, 0, 0);
|
|
||||||
$contact->setDueDate($dueDate);
|
$contact->setDueDate($dueDate);
|
||||||
$contact->setContacted(false);
|
$contact->setContacted(false);
|
||||||
$contact->setParsedFilename($inputPath);
|
$contact->setParsedFilename($inputPath);
|
||||||
|
|
@ -231,10 +227,7 @@ final class CleanMobileCommand extends Command
|
||||||
$contact->setStudyId($study_id);
|
$contact->setStudyId($study_id);
|
||||||
$contact->setParsedFileLinenum($rowCount + 1);
|
$contact->setParsedFileLinenum($rowCount + 1);
|
||||||
$contact->setParsedFileLine($sanitiseUtf8(implode(';', $row)));
|
$contact->setParsedFileLine($sanitiseUtf8(implode(';', $row)));
|
||||||
// $contact->setMsgContentType($rowCount % 2 ? 1 : 2); // alternativ lang oder kurz
|
$contact->setMsgContentType($rowCount % 2 ? 1 : 2);
|
||||||
$contact->setMsgContentType(2); // nur kurzformat
|
|
||||||
$quartal = $today->format('Y') . ceil($today->format('n') / 3);
|
|
||||||
$contact->setDueQuartal((int) $quartal);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$result = $this->http->request('POST', $this->backendApiURL . "/" . $study_id . "/" . $study_id_chain, [
|
$result = $this->http->request('POST', $this->backendApiURL . "/" . $study_id . "/" . $study_id_chain, [
|
||||||
|
|
@ -261,29 +254,16 @@ final class CleanMobileCommand extends Command
|
||||||
// 6️⃣ Persist the valid contacts (batch insert)
|
// 6️⃣ Persist the valid contacts (batch insert)
|
||||||
// -------------------------------------------------------------
|
// -------------------------------------------------------------
|
||||||
if (\count($validContacts) > 0) {
|
if (\count($validContacts) > 0) {
|
||||||
$batch = [];
|
$batchSize = 100;
|
||||||
|
|
||||||
foreach ($validContacts as $i => $contact) {
|
foreach ($validContacts as $i => $contact) {
|
||||||
$batch[] = $contact;
|
$this->em->persist($contact);
|
||||||
if (count($batch) === 100) {
|
if ((($i + 1) % $batchSize) === 0) {
|
||||||
$this->flushBatch($batch, $io);
|
$this->em->flush();
|
||||||
$batch = [];
|
$this->em->clear(); // free memory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($batch) {
|
$this->em->flush();
|
||||||
$this->flushBatch($batch, $io);
|
$this->em->clear();
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// foreach ($validContacts as $i => $contact) {
|
|
||||||
// $this->em->persist($contact);
|
|
||||||
// try {
|
|
||||||
// $this->em->flush();
|
|
||||||
// } catch(UniqueConstraintViolationException $e) {
|
|
||||||
// $io->warning(['The number ', $contact->getPhoneNumber(), ' already contacted for quartal', $contact->getDueQuartal()]);
|
|
||||||
// }
|
|
||||||
// $this->em->clear();
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------
|
// -------------------------------------------------------------
|
||||||
|
|
@ -300,64 +280,4 @@ final class CleanMobileCommand extends Command
|
||||||
|
|
||||||
return Command::SUCCESS;
|
return Command::SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function flushBatch(array $batch, $io): void
|
|
||||||
{
|
|
||||||
$this->em = $this->resetEntityManager();
|
|
||||||
foreach ($batch as $c) {
|
|
||||||
$this->em->persist($c);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
$this->em->flush(); // versucht, den kompletten Batch zu speichern
|
|
||||||
} catch (UniqueConstraintViolationException $e) {
|
|
||||||
$io->warning('Batch conflict – falling back to element‑wise');
|
|
||||||
|
|
||||||
// Transaction rollback (falls aktiv)
|
|
||||||
$conn = $this->em->getConnection();
|
|
||||||
if ($conn->isTransactionActive()) {
|
|
||||||
$conn->rollBack();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Der EM ist jetzt *geschlossen* → resetten
|
|
||||||
if (!$this->em->isOpen()) {
|
|
||||||
$this->em = $this->resetEntityManager(); // hol dir einen frischen EM
|
|
||||||
}
|
|
||||||
|
|
||||||
// Einzelweise weiter versuchen, damit die „guten“ Zeilen nicht verloren gehen
|
|
||||||
$this->flushElementsIndividually($batch, $io);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Batch erfolgreich – Speicher freigeben
|
|
||||||
$this->em->clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
private function flushElementsIndividually(array $contacts, $io): void
|
|
||||||
{
|
|
||||||
$io->warning('flushing individually');
|
|
||||||
foreach ($contacts as $contact) {
|
|
||||||
$this->em->persist($contact);
|
|
||||||
$io->warning('flushing individually2');
|
|
||||||
try {
|
|
||||||
$this->em->flush();
|
|
||||||
$io->warning('flushing individually3');
|
|
||||||
} catch (UniqueConstraintViolationException $e) {
|
|
||||||
$io->warning(['The number ', $contact->getPhoneNumber(), ' already contacted for quartal', $contact->getDueQuartal()]);
|
|
||||||
// das duplizierte Objekt aus dem Unit‑of‑Work entfernen
|
|
||||||
$this->em->detach($contact);
|
|
||||||
$io->warning('flushing individually4');
|
|
||||||
if (!$this->em->isOpen()) {
|
|
||||||
$this->em = $this->resetEntityManager(); // hol dir einen frischen EM
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// jedes Entity einzeln freigeben, sonst wächst der Speicher
|
|
||||||
$this->em->clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function resetEntityManager(): EntityManagerInterface
|
|
||||||
{
|
|
||||||
return $this->doctrine->resetManager();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,6 @@ use App\Repository\ContactsRepository;
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
|
||||||
#[ORM\Entity(repositoryClass: ContactsRepository::class)]
|
#[ORM\Entity(repositoryClass: ContactsRepository::class)]
|
||||||
#[ORM\UniqueConstraint(
|
|
||||||
name: 'unique_quartal',
|
|
||||||
columns: ['phone_number', 'due_quartal'],
|
|
||||||
options: ['where' => "due_quartal IS NOT NULL"]
|
|
||||||
)]
|
|
||||||
class Contacts
|
class Contacts
|
||||||
{
|
{
|
||||||
#[ORM\Id]
|
#[ORM\Id]
|
||||||
|
|
@ -24,9 +19,6 @@ class Contacts
|
||||||
#[ORM\Column(nullable: true)]
|
#[ORM\Column(nullable: true)]
|
||||||
private ?\DateTime $due_date = null;
|
private ?\DateTime $due_date = null;
|
||||||
|
|
||||||
#[ORM\Column(nullable: true)]
|
|
||||||
private ?int $due_quartal = null;
|
|
||||||
|
|
||||||
#[ORM\Column]
|
#[ORM\Column]
|
||||||
private ?bool $contacted = null;
|
private ?bool $contacted = null;
|
||||||
|
|
||||||
|
|
@ -192,14 +184,4 @@ class Contacts
|
||||||
{
|
{
|
||||||
$this->study_id_short = $study_id_short;
|
$this->study_id_short = $study_id_short;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDueQuartal(): ?int
|
|
||||||
{
|
|
||||||
return $this->due_quartal;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setDueQuartal(?int $due_quartal): void
|
|
||||||
{
|
|
||||||
$this->due_quartal = $due_quartal;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user