Вызов jQuery Ajax в цикле дает мне 503 ошибки - PullRequest
0 голосов
/ 28 сентября 2018

Я использую jQuery Ajax для создания отчетов и отправки этих отчетов по электронной почте клиентам.

  • PHP 5.6.31
  • MySQL 5.5.45
  • Windows Server2016
  • jQuery 1.11.1

Если у меня небольшое количество клиентов (например, 50), это не проблема, но если у меня 100 или более, я получаю 503 ошибки.Первая связка отправит сообщение по электронной почте без проблем, но в определенный момент все «ожидающие» вызовы сценария электронной почты сообщают о 503 ошибках.Обычно около 45 секунд.

Вот мой javascript

function emailInvoices(){

  $('#emailreportbutton').button("option","disabled", true);
  $('#email-progresslabel').text( "Starting..." );

  var recipientarray = $('#recipientarray').val();
  var recipients = JSON.parse(recipientarray);
  var recipientcount = recipients.length;

  var totaldueoption = $('#totaldueoption').val();
  var showaccountnumber = $('#showaccountnumber').val();
  var showmessage = $('#showmessage').val();
  var message = $('#message').val();
  var currentcount = 1;
  var successcounter = 0;
  var failcounter = 0;

  //<!--*** For each invoice returned... ***-->

  for (var i=0; i<recipientcount; i++){
    var obj = recipients[i];

    //<!--*** Generate and email the pdf ***-->

    $.ajax({
          type: 'POST',
          url: 'send-invoice.php',
          data: {
          familyid:recipients[i].familyid,
          invoicenumber:recipients[i].invoicenumber,
          motheremail:recipients[i].motheremail,
          fatheremail:recipients[i].fatheremail,
          primarypayer:recipients[i].primarypayer,
          primarypayeremail:recipients[i].primarypayeremail,
          invoicedate:recipients[i].invoicedate,
          totaldueoption:totaldueoption,
          showaccountnumber:showaccountnumber,
          showmessage:showmessage,
          message:message
          },
          success: function(data) {
            if(data == "success"){
              successcounter ++;
              $('#successcount').html(successcounter + " Sent");
              if(failcounter == 0) $('#successcount').addClass('emailsuccess');
            }
            if(data == "fail"){
              failcounter ++
              $('#failcount').html(failcounter + " Failed");
              $('#failcount').addClass('emailfail');
              $('successcount').removeClass('emailsuccess');
            }

            //<!--*** Update progress bar ***-->

            var percentComplete = Math.round(currentcount * 100 / recipientcount);
            $('#progressbar').progressbar("value", percentComplete);

            currentcount ++;

          },
          error: function() {
          // Failed to call send-invoice.php
          }
    });

  }

  $('#reportlink').html("<a href=# onclick=runReport('emailhistory')>Click here to view your email history report</a>");
}

Он всегда работал раньше, но за последние несколько месяцев я менял некоторые настройки сервера, чтобы попытаться решить не связанную проблему, поэтомуМне интересно, изменил ли я какие-либо настройки PHP, чтобы вызвать эту проблему.

Я не уверен, как на вызов ajax в цикле, как это влияют настройки сервера, поэтому я немного ударил в темноте,Чтобы решить эту проблему, я сделал следующее:

  • Я увеличил memory_limit до 512 МБ с 128 МБ
  • Я увеличил max_input_time до 60 с 20
  • Я увеличил post_max_sizeдо 60M с 20M
  • Я увеличил upload_max_filesize до 30M с 10M
  • Я увеличил max_file_uploads до 60 с 20

Все безрезультатно.

Вот скриншот моих инструментов разработчика Chrome, чтобы вы могли точно понять, что я имею в виду.Не беспокойтесь о красном предупреждении о сбое электронной почты - это просто те, которые не имеют адреса электронной почты.Настоящая проблема - это вызовы send-invoice.php с ошибкой 503.Интересно, что эта ошибка обнаруживается в этих файлах еще до их обработки.Все они переходят от ожидания к ошибке примерно в одно и то же время, как если бы в определенный момент сервер просто сказал: «Я закончил, не более».

enter image description here

Не уверен, что содержание send-invoice.php уместно, но здесь оно так или иначе:

<?php

include("common/common.php");

$familyid = $_POST["familyid"];
$invoicenumber = $_POST["invoicenumber"];
$motheremail = trim($_POST["motheremail"]);
$fatheremail = trim($_POST["fatheremail"]);
$primarypayer = trim($_POST["primarypayer"]);
$primarypayeremail = trim($_POST["primarypayeremail"]);
$attachmentdate = $_POST["invoicedate"];

$totaldueoption = $_POST["totaldueoption"];
$showaccountnumber = $_POST["showaccountnumber"];
$showmessage = $_POST["showmessage"];
$message = $_POST["message"];
$dosend = false;

//<!--********************************************************************************************************-->
//<!-- Get family name -->
//<!--********************************************************************************************************-->

$sql = "select name from families where id = ".$familyid;
$result = mysql_query($sql);

if ($row = mysql_fetch_array($result)){
  $familyname = $row["name"];
}

//<!--********************************************************************************************************-->
//<!-- Get email body -->
//<!--********************************************************************************************************-->

$sql = "select emailbodyinvoice from preferences where companyid = ".$companyid;
$result = mysql_query($sql);

if ($row = mysql_fetch_array($result)){
  $emailbody = $row["emailbodyinvoice"];
}

//<!--********************************************************************************************************-->
//<!-- Generate pdf -->
//<!--********************************************************************************************************-->

include("common/pdf/mpdf/mpdf.php");
ob_start();
$report = "invoice";
$selectedinvoice = $invoicenumber;
include("report.php");
$reporthtml = ob_get_clean();

$style = "
<style>
@page {
  margin: 0px;
}
</style>";

$html = $style.$reporthtml;

$mpdf=new mPDF('c');

$mpdf->mirrorMargins = true;
$mpdf->SetDisplayMode('fullpage','two');
$mpdf->WriteHTML($html);

$invoice = $mpdf->Output('Invoice '.$attachmentdate,'S');

//<!--********************************************************************************************************-->
//<!-- Send invoice email -->
//<!--********************************************************************************************************-->

require('common/html2text.php');

$emailbody = rawurldecode(html_entity_decode("<html><body>".$emailbody."<br><br><div style='color:#929292'>This email was sent on behalf of ".$companyname.".  You may reply to this message to contact ".$companyname." but do not use the sender address (no-monitor@timesavr.net) as that mailbox is not monitored and ".$companyname." will not receive your message.</div></body></html>"));

$emailtextbody = html2text(html_entity_decode($emailbody));
$emailsubject = "Invoice from ".$companyname;

//<!--********************************************************************************************************-->
//<!-- Include dependencies
//<!--********************************************************************************************************-->

require("common/smtpemail.php");

//<!--********************************************************************************************************-->
//<!-- Email sender details
//<!--********************************************************************************************************-->

$mail->From     = "no-monitor@timesavr.net";  // Approved sending domain for SendGrid so the emails don't get flagged as spam
$mail->FromName = $companyname;
$mail->AddReplyTo($companyemail,$companyname);
$mail->AddStringAttachment($invoice,'Invoice '.$attachmentdate.'.pdf');

//<!--********************************************************************************************************-->
//<!-- Add recipients
//<!--********************************************************************************************************-->

$mothervalid = validateEmail($motheremail);
$fathervalid = validateEmail($fatheremail);
$primarypayervalid = validateEmail($primarypayeremail);

if($emailinvoicesto == "P"){
  if($primarypayervalid){
    $mail->AddAddress($primarypayeremail,$primarypayeremail);
    $recipient = $primarypayeremail;
    $dosend = true;
  }
}

if($emailinvoicesto == "M" or $emailinvoicesto == "B"){
  if($mothervalid){
    $mail->AddAddress($motheremail,$motheremail);
    $recipient = $motheremail;
    $dosend = true;
  }
}

if($emailinvoicesto == "F" or $emailinvoicesto == "B"){
  if($fathervalid){
    $mail->AddAddress($fatheremail,$fatheremail);
    if($recipient <> ""){
      $recipient .= ";".$fatheremail;
    }else{
      $recipient .= $fatheremail;
    }
    $dosend = true;
  }
}

//<!--********************************************************************************************************-->
//<!-- Send email
//<!--********************************************************************************************************-->

$emailsubject = htmlentities($emailsubject,ENT_QUOTES);
$familyname = htmlentities($familyname,ENT_QUOTES);

if($dosend){
  if($mail->Send()){
    recordEmail("I",$emailsubject,$familyname,$recipient,"S");
    $result = "success";

  }else{
    recordEmail("I",$emailsubject,$familyname,$recipient,"F");
    $result = "fail";

  }
}else{
  recordEmail("I",$emailsubject,$familyname,$recipient,"F","No email address found");
  $result = "fail";
}

echo $result;

mysql_close();
?>

Ответы [ 2 ]

0 голосов
/ 29 сентября 2018

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

Достигается то же самое, что и синхронное выполнение (async = false), но таким образом не блокируется пользовательский интерфейс, и я все еще могу увеличивать индикатор выполнения.

//<!--********************************************************************************************************-->
//<!-- emailInvoices()
//<!--********************************************************************************************************-->

function emailInvoices(){

  var recipientarray = $('#recipientarray').val();
  var recipients = JSON.parse(recipientarray);
  var recipientcount = recipients.length;

  //<!--*** Pass in recipient array, first index and total recipient count... ***-->
  emailInvoice(recipients,0,recipientcount);
}

//<!--********************************************************************************************************-->
//<!-- emailInvoice(recipient,i,recipientcount)
//<!--********************************************************************************************************-->


function emailInvoice(recipients,i,recipientcount){

  $.ajax({
        type: 'POST',
        url: 'send-invoice.php',
        data: {
          familyid:recipients[i].familyid,
          invoicenumber:recipients[i].invoicenumber,
          motheremail:recipients[i].motheremail,
          fatheremail:recipients[i].fatheremail,
          primarypayer:recipients[i].primarypayer,
          primarypayeremail:recipients[i].primarypayeremail,
          invoicedate:recipients[i].invoicedate,
          totaldueoption:totaldueoption,
          showaccountnumber:showaccountnumber,
          showmessage:showmessage,
          message:message
        },
        success: function(data) {

          //<!--*** Update progress bar ***-->
          var percentComplete = Math.round((i+1) * 100 / recipientcount);
          $('#progressbar').progressbar("value", percentComplete);

          //<!--*** Increment index and call this function again -->
          i++;
          if(i < recipientcount){
            emailInvoice(recipients,i,recipientcount);
          }
        }
   });
}

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

0 голосов
/ 28 сентября 2018

Похоже, ваш скрипт достигает максимального времени выполнения.Проверьте этот ответ и посмотрите, поможет ли он https://stackoverflow.com/a/5140299/6312181

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...