Проверка дубликатов электронной почты в данных ответа API

Aug 20 2020

Я работаю над небольшим внутренним приложением, которое работает с внешним API для целей обеспечения.

Код по существу состоит из серии форм, в которые пользователь вводит данные, которые затем отправляются в API для регистрации новых клиентов.

Это довольно линейный процесс, который я попытаюсь объяснить:

  1. Создание контакта: основная информация о клиенте (электронная почта, адрес ...).
  2. Создание клиента: более подробная информация, для создания клиента он должен contactIdпринадлежать именно этому клиенту.
  3. Создание подписчика: информация, связывающая клиента с полученной услугой. Предыдущий шаг должен быть выполнен и customerIdдолжен существовать.
  4. Создание службы: содержит дополнительную информацию о службе. И снова, suscriberIdчтобы связать сервис , необходимо наличие .

Я справился с более или менее быстрым процессом с несколькими настройками здесь и там, но первый шаг (Контакт) имеет метод, который я не могу улучшить, что, в свою очередь, приводит к тому, что этот процесс занимает около минуты. !

Как и весь процесс, описанный ранее, создание каждого из них также очень линейно.

В документации по API указано, что результаты любого GET должны быть разбиты на страницы максимум до 10 записей, но после этого время еще больше увеличивается в течение минуты. Ручные эксперименты показали, что наилучшее соотношение составляет около 500 записей на страницу или, в некоторых случаях, даже полное количество записей оказалось самым быстрым способом, а не 10 на 10.

Поскольку контактный адрес электронной почты нельзя дублировать, первое, что нужно сделать, это проверить адрес электронной почты, указанный в форме, и сравнить его со всеми уже существующими сохраненными сообщениями электронной почты.

Чтобы предоставить $pageи $entriesдля вызова API, я должен сначала получить общее количество контактов. Этот номер появляется при вызове API для получения контактов. Итак, первый метод, который я использую:

function fetchTotalContacts($uri, $auth){
    $ch = curl_init(); $options = array(
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_SSL_VERIFYHOST => false,
        CURLOPT_SSL_VERIFYPEER => false,
        CURLOPT_URL => $uri.'?page=1&rows=1', CURLOPT_HTTPHEADER => array('Content-Type: application/json', 'Authorization: $auth')
    );

    curl_setopt_array($ch, $options);

    $response = curl_exec($ch);
    $response = json_decode($response, true);
    $totalContacts = $response['total_count'];

    $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

    if ($http_code != 200) { echo "Error en fetchTotalContacts() - Código: $http_code | ";
    }
    
    curl_close($ch); return $totalContacts;
}

Теперь, имея $totalContacts, я могу продолжить и поискать, было ли электронное письмо уже зарегистрировано, и это шаг, который, как я подозреваю, отвечает за высокое время выполнения. Этот метод ищет контакты и их электронные письма, если не находит совпадений, приступает к созданию контакта с предоставленными данными.

function checkDuplicatedEmail($uri, $totalContacts, $contactEmailArray, $auth, $contactEmail, $dataContact){ $ch = curl_init();

    $options = array( CURLOPT_RETURNTRANSFER => true, CURLOPT_SSL_VERIFYHOST => false, CURLOPT_SSL_VERIFYPEER => false, CURLOPT_URL => $uri.'?page=1&rows='.$totalContacts, CURLOPT_HTTPHEADER => array('Content-Type: application/json', 'Authorization: $auth')
    );
    curl_setopt_array($ch, $options);

    $customers = curl_exec($ch);
    $customers = json_decode($customers, true);

    $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    
    if ($http_code != 200) { echo "Error en checkDuplicatedEmail() - Código: $http_code | ";
    }


    curl_close($ch); /* foreach ($customers['_embedded']['ngcp:customercontacts'] as $customer) { $email = $customer['email']; array_push($contactEmailArray, $email); } if (in_array($contactEmail, $contactEmailArray)) { echo('El email utilizado ya ha sido registrado en la base de datos'); die(); }else{ $contactCreated = createContact($uri, $dataContact);
        return $contactCreated; } */ $repeated = 0;
    for ($i=0; $i < $totalContacts ; $i++) {
        if ($contactEmail == $customer["_embedded"]["ngcp:customercontacts"][$i]["email"]) { $repeated += 1;
        }
    }

    if ($repeated > 0) { die(echo('El email utilizado ya ha sido registrado en la base de datos')); }else{ $contactCreated = createContact($uri, $dataContact, $auth); return $contactCreated;
    }
}

Как видите, это самые быстрые варианты, которые я нашел, и в обоих случаях весь процесс занимает 40 секунд, что все еще слишком много.

Ответ для - это код успеха (400, 201 ..), поэтому, когда я хочу перейти к следующему шагу, мне снова нужно поискать все контакты, чтобы найти тот, который я только что создал, и получить идентификатор. К счастью, здесь я могу просто перейти к последним 20 контактам (не к последнему напрямую, чтобы его можно было использовать одновременно без проблем) и искать там, это делает его очень быстрым, но для электронной почты такого пропуска нет, все записи необходимо проанализировать.createContact($uri, $dataContact, $auth);

Я не знаю, как сократить здесь время, остальная часть кода состоит из выборки contactIdи создания клиента, поэтому там не так много работы, как сейчас.

Если кто-то из вас сочтет необходимым просмотреть остальную часть страницы, я обновлю сообщение.

В качестве последнего напоминания я вручную пробовал использовать разные конфигурации страниц и записей, и для этой страницы был самым быстрым 1 page - All entries. Я также попытался взять цикл for / each вне метода, но безрезультатно.

Ответы

2 mickmackusa Aug 20 2020 at 20:27

forЦикл не будет узким местом в цикле, но то , что кажется очевидным для меня является то , что вы не выигрываете от подсчета выше $repeated = 1. Это означает, что вам не нужна переменная счетчика, вам действительно нужно событие разрыва цикла - в этом случае die(). К вашему сведению, die()напечатайте текст в своем первом параметре, поэтому использование echoявляется избыточным.

for ($i=0; $i < $totalContacts; ++$i) { if ($contactEmail == $customer["_embedded"]["ngcp:customercontacts"][$i]["email"]) {
        die('El email utilizado ya ha sido registrado en la base de datos');
    }
}
return createContact($uri, $dataContact, $auth);

Или другой способ, который, как я предполагаю, будет медленнее (потому что array_column()будут собирать все электронные письма), - это функциональный дизайн:

if (in_array($contactEmail, array_column($customer["_embedded"]["ngcp:customercontacts"], "email"))) { die('El email utilizado ya ha sido registrado en la base de datos'); } return createContact($uri, $dataContact, $auth);