Beispiel #1
0
        public static void Run()
        {
            // If there is mail in the outbound mail queue, do not add more. (This is a primitive
            // protection against dupes. Better will come that doesn't force idle time like this.)

            lock (lockObject)
            {
                if (mailQueueSize > 0)
                {
                    // return;
                }
            }

            // Look for a mail to process, or keep processing.
            OutboundMails mails = OutboundMails.GetTopUnprocessed(100);

            mailQueueSize = 0;

            if (mails.Count == 0)
            {
                // no unprocessed mail, everybody's happy
                return;
            }

            int maxBatchSize = 20; // Total number of recipients to process across all mails

            foreach (OutboundMail mail in mails)
            {
                // If we have already processed past our limit, return for now.
                if (maxBatchSize < 1)
                {
                    return;
                }

                // We are continuing to process, and starting with a fresh outbound mail.

                // Is this the first time we touch this mail?
                if (mail.StartProcessDateTime.Year < 2000)
                {
                    // Yes! Mark it as started and mail our author.
                    mail.StartProcessDateTime = DateTime.Now;

                    if (mail.MailType == (int)TypedMailTemplate.TemplateType.MemberMail ||
                        mail.MailType == (int)TypedMailTemplate.TemplateType.OfficerMail)     // TODO: Set special flag
                    {
                        string mailBody = string.Empty;

                        new MailTransmitter(
                            Strings.MailSenderName, Strings.MailSenderAddress, "Mail transmission begins: " + mail.Title,
                            mailBody, Person.FromIdentity(mail.AuthorPersonId), true).Send();
                    }
                }

                int batchSize = maxBatchSize;

                // If we are debugging, and stepping through this program, avoid the misery of many simultaneous threads.

                if (Debugger.IsAttached)
                {
                    batchSize = 1; // Do NOT multithread while debugging
                }

                while (true)
                {
                    if (!Debugger.IsAttached)
                    {
                        // HeartBeater.Instance.Beat();
                        //Tick the heartbeat to stop exernal restart if this takes a lot of time, but only if not debugging.
                    }

                    OutboundMailRecipients recipients = mail.GetNextRecipientBatch(batchSize);

                    maxBatchSize -= recipients.Count; // Decrement number of recipients to process on next mail, if any

                    if (recipients.Count == 0)
                    {
                        // This mail is complete!

                        mail.SetProcessed();

                        if (mail.MailType == (int)TypedMailTemplate.TemplateType.MemberMail ||
                            mail.MailType == (int)TypedMailTemplate.TemplateType.OfficerMail)
                        // TODO: Set special flag
                        {
                            string body = "Your mail has completed transmitting to " +
                                          mail.RecipientCount.ToString("#,##0") +
                                          " intended recipients. Out of these, " +
                                          mail.RecipientsFail.ToString("#,##0") +
                                          " failed because of invalid, empty, or otherwise bad e-mail addresses. These people have not received your message.\r\n";

                            new MailTransmitter(
                                Strings.MailSenderName, Strings.MailSenderAddress,
                                "Mail transmission completed: " + mail.Title, body,
                                Person.FromIdentity(mail.AuthorPersonId),
                                true).Send();
                        }

                        if (maxBatchSize < 1)
                        {
                            return;
                        }

                        break; //the while loop
                    }
                    List <IAsyncResult> sendInProgress  = new List <IAsyncResult>();
                    List <WaitHandle>   waitHandlesList = new List <WaitHandle>();
                    foreach (OutboundMailRecipient recipient in recipients)
                    {
                        // Skip known invalid mail addresses
                        if (recipient.Person != null &&
                            (recipient.Person.EMailIsInvalid || recipient.Person.MailUnreachable))
                        {
                            lock (lockObject)
                            {
                                recipient.Delete();
                                recipient.OutboundMail.IncrementFailures();
                            }

                            continue;
                        }

                        // Start the transmission process, asynchronously

                        lock (lockObject)
                        {
                            MailTransmissionDelegate   asyncTransmitter = TransmitOneMail;
                            MailTransmissionAsyncState asyncState       = new MailTransmissionAsyncState();
                            asyncState.dlgt      = asyncTransmitter;
                            asyncState.recipient = recipient;
                            IAsyncResult asyncResult = asyncTransmitter.BeginInvoke(recipient, MailSent, asyncState);
                            sendInProgress.Add(asyncResult);
                            waitHandlesList.Add(asyncResult.AsyncWaitHandle);
                            mailQueueSize++;
                        }

                        Thread.Sleep(25);  // Allow some time
                    }

                    // now wait for them to finish;
                    int      numberStillExecuting = sendInProgress.Count;
                    int      numberExecutingLast  = numberStillExecuting + 1;
                    DateTime lastProgress         = DateTime.Now;


                    while (numberStillExecuting > 0)
                    {
                        WaitHandle.WaitAny(waitHandlesList.ToArray(), 100, true);
                        lock (lockObject)
                        {
                            numberStillExecuting = 0;
                            waitHandlesList      = new List <WaitHandle>();

                            for (int i = 0; i < sendInProgress.Count; ++i)
                            {
                                IAsyncResult iares = sendInProgress[i];
                                MailTransmissionAsyncState asyncState = (MailTransmissionAsyncState)iares.AsyncState;

                                if (asyncState.dlgt != null)
                                {
                                    if (!asyncState.callbackCompleted)
                                    {
                                        waitHandlesList.Add(iares.AsyncWaitHandle);
                                        numberStillExecuting++;
                                    }
                                    else
                                    {
                                        //Just finalised
                                        if (asyncState.exception != null)
                                        {
                                            if (asyncState.exception is RetryRecipientException)
                                            {
                                                //Failed in sending due to some reason that can clear up by itself.
                                                asyncState.dlgt = null;
                                            }
                                            else
                                            {
                                                //Make sure recipient is deleted
                                                try
                                                {
                                                    asyncState.recipient.Delete();

                                                    // if RemoveRecipientException everything went ok except for the removal
                                                    if (asyncState.exception is RemoveRecipientException)
                                                    {
                                                        asyncState.recipient.OutboundMail.IncrementSuccesses();
                                                    }

                                                    asyncState.dlgt = null; // mark as done;
                                                    mailQueueSize--;
                                                }
                                                catch
                                                {
                                                    //Keep looping until recipient removed
                                                    numberStillExecuting++;
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }

                        if (numberExecutingLast != numberStillExecuting)
                        {
                            lastProgress = DateTime.Now;
                        }

                        numberExecutingLast = numberStillExecuting;

                        if (lastProgress.AddSeconds(60 * 2) < DateTime.Now)
                        {
                            // since last change, something must have hanged
                            lock (lockObject)
                            {
                                mailQueueSize = -1000;
                            }
                            throw new Exception("Timeout in MailProcessor");
                        }
                    }
                }
            }
        }
Beispiel #2
0
    private void BuildTable()
    {
        tab.Rows.Clear();

        OutboundMails mails = OutboundMails.FromArray(PirateDb.GetDatabase().GetOutboundMailQueue(500));

        TableRow row = new TableRow();

        tab.Rows.Add(row);
        TableCell c = new TableCell(); row.Cells.Add(c);

        c.Text = "Template";

        c      = new TableCell(); row.Cells.Add(c);
        c.Text = "Title";

        c      = new TableCell(); row.Cells.Add(c);
        c.Text = "Release time";

        c      = new TableCell(); row.Cells.Add(c);
        c.Text = "Time until release";

        c      = new TableCell(); row.Cells.Add(c);
        c.Text = "Counts";

        c      = new TableCell(); row.Cells.Add(c);
        c.Text = "Started";

        foreach (OutboundMail mail in mails)
        {
            TypedMailTemplate tmpl = null;
            if (mail.MailType != 0)
            {
                tmpl = TypedMailTemplate.FromName(mail.Title);
                tmpl.Initialize("SE", mail.OrganizationId, mail, "");
                tmpl.InsertAllPlaceHoldersToTemplate();
            }
            row = new TableRow();
            tab.Rows.Add(row);

            if (mail.MailType != 0)
            {
                c      = new TableCell(); row.Cells.Add(c);
                c.Text = mail.Title;

                c      = new TableCell(); row.Cells.Add(c);
                c.Text = tmpl.Template.TemplateTitleText;
            }
            else
            {
                c      = new TableCell(); row.Cells.Add(c);
                c.Text = "none";

                c      = new TableCell(); row.Cells.Add(c);
                c.Text = mail.Title;
            }
            c      = new TableCell(); row.Cells.Add(c);
            c.Text = mail.ReleaseDateTime.ToString();
            if ((new DateTime(1970, 1, 1)) == mail.StartProcessDateTime && mail.ReleaseDateTime < DateTime.Now)
            {
                c.ForeColor = System.Drawing.Color.Red;
                c.Font.Bold = true;
            }

            c      = new TableCell(); row.Cells.Add(c);
            c.Text = Math.Round((DateTime.Now.Subtract(mail.ReleaseDateTime).TotalMinutes)).ToString();


            c       = new TableCell(); row.Cells.Add(c);
            c.Text  = mail.RecipientCount.ToString();
            c.Text += " / " + mail.RecipientsSuccess.ToString();
            c.Text += " / " + mail.RecipientsFail.ToString();

            c      = new TableCell(); row.Cells.Add(c);
            c.Text = mail.StartProcessDateTime.ToString();
        }
    }