Comprobación de correo electrónico duplicado en los datos de respuesta de la API
Estoy trabajando en una pequeña aplicación interna que funciona junto con una API externa con fines de aprovisionamiento.
Básicamente, el código se compone de una serie de formularios donde el usuario ingresa datos, estos datos luego se envían a la API para registrar nuevos clientes.
Este es un proceso bastante lineal que intentaré explicar:
- Creación de contactos: Información básica del cliente (correo electrónico, dirección ...).
- Creación de cliente: información más avanzada, para que se cree un cliente debe haber una
contactId
pertenencia a este cliente. - Creación de suscriptor: Información que vincula al cliente con el servicio adquirido. El paso anterior debe completarse y
customerId
debe existir. - Creación de servicios: contiene bits de información avanzada sobre el servicio. Una vez más,
suscriberId
debe existir una para poder vincular el servicio.
Logré un proceso más o menos rápido con algunos ajustes aquí y allá, pero el primer paso (Contacto) tiene un método que parece que no puedo mejorar, lo que a su vez hace que este proceso tome hasta un minuto completo. !
Como todo el proceso descrito anteriormente, la creación de cada uno de estos también es muy lineal.
La documentación de la API establece que los resultados de cualquier GET deben paginarse hasta un máximo de 10 entradas, pero después de esto aumenta aún más el tiempo por minuto. Los experimentos manuales mostraron que la mejor proporción es de alrededor de 500 entradas por página o, en algunos casos, incluso el número total de entradas resultó ser la forma más rápida en lugar de ir de 10 por 10.
Dado que el correo electrónico de contacto no se puede duplicar, una de las primeras cosas que debe hacer es verificar el correo electrónico proporcionado en el formulario y compararlo con todos los correos electrónicos ya existentes almacenados.
Para proporcionar el $page
y $entries
a la llamada API, primero debo buscar el número total de contactos. Este número aparece al llamar a la API para obtener los contactos. Entonces, el primer método que utilizo es:
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;
}
Ahora que $totalContacts
tengo, puedo proceder y buscar si el correo electrónico ya ha sido registrado, y este es el paso que sospecho que es responsable del alto tiempo de ejecución. Este método busca los contactos y sus correos electrónicos, si no encuentra coincidencia, procede a crear el contacto con los datos proporcionados.
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;
}
}
Como puede ver, estas son las opciones más rápidas que he encontrado, ambas hacen que todo el proceso demore 40 segundos, lo cual es demasiado.
La respuesta para es un código de éxito (400, 201 ..), así que cuando quiero ir al siguiente paso, necesito, nuevamente, buscar en todos los contactos para encontrar el que acabo de crear y obtener la identificación. Afortunadamente, aquí puedo simplemente saltar a los últimos 20 contactos (no el último directamente, por lo que se puede usar simultáneamente sin problemas) y buscar allí, esto lo hace realmente rápido, pero para el correo electrónico no hay tal omisión, todas las entradas. debe ser analizado.createContact($uri, $dataContact, $auth);
No sé cómo dejar caer el tiempo aquí, el resto del código consiste en buscar contactId
y crear al cliente, por lo que no hay mucho que hacer allí como ahora.
Si alguno de ustedes considera necesario ver el resto de la página, actualizaré la publicación.
Como recordatorio final, he probado manualmente con diferentes configuraciones de páginas y entradas y para esta página, la más rápida fue 1 page - All entries
. También intenté tomar el bucle for / each fuera del método, sin éxito.
Respuestas
El for
bucle no va a ser el cuello de botella en su bucle, pero lo que me parece obvio es que no se beneficia de contar más de $repeated = 1
. Esto significa que no necesita una variable de contador, realmente necesita un evento de ruptura de bucle, en este caso die()
. Para su información, die()
imprimirá el texto en su primer parámetro, por lo que su uso echo
es redundante.
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);
O de otra forma, que supongo que será más lenta (porque array_column()
recopilaremos todos los correos electrónicos) es este diseño funcional:
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);