Başarılı olana kadar bir işlevi yürütmek nasıl?

6 Cevap php

Ben belirli bir kullanıcı için bir posta göndermek için bir işlevi yazıyorum?

Hata ben posta gönderilene kadar posta gönderme tutmak istediğiniz olursa ne yapmam çalışıyorum, olduğunu.

    function sendmail() {
        $name = mysql_escape_string($name);
        $email = mysql_escape_string($email);
        $phone = mysql_escape_string($phone);
        $content = nl2br(mysql_escape_string($content));
        $subject = "mail from ".$name." (".$email.", Ph: ".$phone.")";
        $mail = @mail($feedback,$subject,$content,$headers);
        if($mail) { echo "Your mailis send"; }
        else { echo "We are sorry for the inconvienience, but we could not send your mailnow."; }
}   

Yukarıdaki fonksiyon hata mesajı görüntüler, ancak bunun yerine hata veriyor, ben posta nihayet gönderilene kadar posta göndermek için denemek istiyorum.

6 Cevap

Design for Error Handling:

Ne sayfa göndermek olamazsa? Daemon durdu kullanıcı bağlantısı kesildi, hatalı biçimlendirilmiş veriler girilir, diski yazabilirsiniz, veritabanı sunucusu kullanıcının isteği ile yapmak ne istiyorsun vb mainenance, aşağı mı? Ben daha sonra tekrar başarısızlık üzerine bir sıra kurma öneriyoruz. İyi kuyruk sistemleri bir sürü orada vardır. Eğer (bu bir müşterinin talebi üzerine asılı değil bu şekilde) varsa yeniden deneme Cron. Üstüste yapın ve belirli hata koşullar oluşursa o yöneticisine bildirmek.

Bu bir operasyon / altyapı takım için inşa budur, ama bazı iyi takım ve hata ve istisna işleme için iyi tasarlanmış bir strateji ile başlayabilirsiniz. Kodunuzu miras insanlar size teşekkür edecek.

Ben Pragmatik Programcı okuma edilmiştir ve ben çok bu soru ile özellikle ilgilenen için tavsiye var. Bu hata / istisna işleme düşünmek şekilde bir standart ayarlar ve benim için kesinlikle bir hatadır ne ilişkin sis, vs bir istisna, vs bir iddia durumu (veya olanaksız durum) temizlenir. Özellikle Bölüm 4 Pragmatik Paranoya:

"Herkes aslında seni almak için dışarı olduğunda, paranoya sadece iyi düşünme"-Woody Allen

mail() başarısız olursa Peki, belki yanlış gitmiş olabilir?

  • Sistem yerel daemon el postanıza yapılandırılırsa, cini ölü ya da yanlış olabilir.
  • Doğrudan bir SMTP sunucusuna söz ediyorsanız, sunucu büyük olasılıkla ölü, ya da bir şey yanlış olduğunu.

In both cases, how would you know when the responsible parties become responsive again? How long do you want to keep retrying?
The local mail daemon shouldn't ever die, or at least it should be resurrected immediately by the system. If that doesn't happen, you should fix the server instead of handling this situation in code.
If you're talking to an SMTP server, the only legitimate case where retrying a second or so later may actually succeed is if the server is being overloaded or DDoS'd and you're lucky enough to get through. That case is probably rare enough not to worry about though.

mail() false döndürür eğer başka bir sorunu çözmek kadar iki şekilde de, hiçbir nokta yine çalışırken genellikle var. Bu nedenle, sadece incelikle başarısız gönderilmeyen postanın bir kopyasını şeylerin tam bir günlüğünü tutmak ve daha sonra elle tekrar gönderin.

mail() başarılı yani bile bu noktadan sonra her şey sizin kontrolünüz dışında, e-posta veya hedefine varmak olmayabilir. Elle / yanlış anlamaya çalışın onları geri dönmüş veya error'd postaları ve hareket yakalamak için sunucu admin olarak sizin görevinizdir.

Eğer posta sunucusu fazla 30 saniye boyunca iş dışında ise sadece bu süre döngü ile (genellikle 30 saniye) sahip olduğu zaman egzoz olacağını fark?

Hata daha iyi bir yolu muhtemelen, bu kadar beklemek olmaz bu 30 saniye bant genişliği israf, bitti ve işlemci can sıkıcı bazı insanlar Probabl önce sadece belki, ve üzerinde 782428424 kez gönderecek yeniden gönderin.

Ne daha iyi yapacağını başarısızlık floş bazı veritabanı içeriğini yazmak ve başarı kadar her 5 dakikada bir ya da öylesine göndermek için deneyin.

Ben bir sayaç ve / veya uyku açıklamada koyarak tavsiye ederim.

Sayaç script sonunda çıkar ve sadece etrafında asmak değildir ve başarısız deyimi yürütme tutar sağlamaktır.

Uyku deyimi anlık yük konularla "ilgili" içindir.

Gibi bir şey:

$remainingTries = 5;
while ($remainingTries > 0 && !sendmail())
{
  $remainingTries--; // we used a try, decrement
  sleep(5);          // wait five seconds before next try
}
function sendmail() {
        $name = mysql_escape_string($name);
        $email = mysql_escape_string($email);
        $phone = mysql_escape_string($phone);
        $content = nl2br(mysql_escape_string($content));
        $subject = "mail from ".$name." (".$email.", Ph: ".$phone.")";

        $retries = 0;
        while (!@mail($feedback,$subject,$content,$headers))
        {
            $retries++;

            if ($retries >= MAX_RETRIES)
            {
                break;
            }

            sleep(WAITING_PERIOD);
        }

        if ($retries < MAX_RETRIES) { echo "Your mail has been sent."; }
        else { echo "We are sorry for the inconvienience, but we could not send your mail now." ; }
}

Sadece çok uzun MAX_RETRIES set yoksa veya uzun süre beklemek için sıkışmış, ne de çok düşük WAITING_PERIOD ayarlamak, ya da posta ajan sel olabilir alabilirsiniz, sizin için çalışır bir şey WAITING_PERIOD ve MAX_RETRIES ayarlayın.

Böyle bir şey deneyin:

function doSomething($arg1, $arg2, $retry = 10)
{
    $result = false;

    /* do stuff */

    if ($result === false)
    {
        static $original = null;

        if (is_null($original))
        {
            set_time_limit(0);
            $original = $retry;
        }

        sleep(pow(2, $original - $retry));

        while (--$retry > 0)
        {
            return doSomething($arg1, $arg2, $retry);
        }
    }

    return $result;
}

Başarısız olursa, o $retry kez tekrar deneyin ve bekleyin:

1 second before the 1st retry
2 seconds before the 2nd retry
4 seconds before the 3rd retry
8 seconds before the 4th retry
16 seconds before the 5th retry
32 seconds before the 6th retry
64 seconds before the 7th retry
128 seconds before the 8th retry
256 seconds before the 9th retry
512 seconds before the 10th retry
...
2 ^ ($retry - 1) seconds before the ($retry)th retry

Bunu yaparak size sunucusu aşırı alamadım sağlamak.