public void Perform_RealAdmin_ExistingIdea() { Add_Accessor target = new Add_Accessor(); // TODO: Initialize to an appropriate value IDataStore store = DataStore.GetInstance(); DailyIdea idea = new DailyIdea { Idea = "This is the added message", }; store.Save(idea); Assert.AreNotEqual(0, idea.Id); IncomingSmsMessage message = new IncomingSmsMessage { From = Configuration.GetInstance().AdminNumber, Message = string.Format(CultureInfo.InvariantCulture, "add {0}", idea.Idea), }; target.Perform(message); Assert.AreEqual(1, store.DailyIdeas.Count(i => i.Idea == idea.Idea)); OutgoingSmsMessage response = store.OutgoingMessages.Where(o => o.Message == SmsResponseStrings.Add_Failed_ExistingIdea(idea.Id)).First(); Assert.AreEqual(Configuration.GetInstance().AdminNumber, response.Destination); }
protected static void Say(string destination, string message) { IDataStore store = DataStore.GetInstance(); OutgoingSmsMessage msg = OutgoingSmsMessage.CreateWithDefaults(destination, message); store.Save(msg); }
public void Run() { LogManager.Log.Info("WorkerRole.Run Loop Started"); using (IOutgoingSmsQueue outgoing = OutgoingSmsQueue.GetInstance()) { outgoing.Send(OutgoingSmsMessage.CreateWithDefaults(_Configuration.AdminNumber, "WorkerRole.Run Loop Started"), null, null); while (true) { // waiting for the queue to drain ensures we won't pick up the same one twice if (outgoing.Length == 0) { IDataStore store = DataStore.GetInstance(); ProcessOutgoingMessages(outgoing, store); ProcessSubscriptions(outgoing, store); } else { // there is already a back-log do don't go adding more to it... Thread.Sleep(5 * 1000); } } } }
public void Remove(OutgoingSmsMessage msg) { lock (_lock) { _outgoingMessages.Remove(msg.Id); } }
public override bool OnStart() { // Set the maximum number of concurrent connections ServicePointManager.DefaultConnectionLimit = 12; try { CreateServiceHost(); LogManager.Log.Info("WCF Services started"); } catch (Exception ex) { LogManager.Log.Error("Exception configuring WCF Services", ex); using (IOutgoingSmsQueue outgoing = OutgoingSmsQueue.GetInstance()) { IConfiguration config = Configuration.GetInstance(); outgoing.Send(OutgoingSmsMessage.CreateWithDefaults(config.AdminNumber, "WCF STARTUP ERROR: " + ex.GetType().FullName), null, null); } } return(base.OnStart()); }
public void SenderSends() { ObjectFactory.Initialize(x => { x.For <ILogging>().Use <TraceLogger>(); x.For <ISmsTransport>().Use <SuccessSmsSender>(); x.For <IDataStore>().Use <TestDataStore>(); }); int toSend = 10; int[] count = { 0 }; ManualResetEvent done = new ManualResetEvent(false); bool[] sendFailed = new bool[1] { false }; SendCompleteCallback complete = (SentSmsMessageLogEntry result, OutgoingSmsMessage msg) => { Assert.AreEqual((int)MessageSendStatus.Success, result.Status); Assert.AreEqual(count[0], msg.Id, "The subscription ID was incorrect"); count[0]++; if (count[0] == toSend) { done.Set(); } }; SmsSenderExceptionThrownCallback failed = (OutgoingSmsMessage message, Exception exception) => { sendFailed[0] = true; Assert.Fail(string.Format(CultureInfo.InvariantCulture, "Sending message {0} failed?", message.Id)); }; SmsSenderQueue sender = new SmsSenderQueue(); for (int i = 0; i < 10; i++) { OutgoingSmsMessage msg = new OutgoingSmsMessage { Message = "This is the message", Destination = "+11234567890", Id = i, }; sender.Send(msg, complete, failed); } Assert.IsTrue(done.WaitOne(TimeSpan.FromSeconds(toSend)), "Sending timed out ... that's not good!"); Assert.IsFalse(sendFailed[0], "The send was marked as failed ... wtf???"); }
public void ScheduleMessage(OutgoingSmsMessage msg, Subscription sub) { lock (_lock) { Save(msg); Subscription toUpdate = Subscriptions.Where(s => s.Id == sub.Id).FirstOrDefault(); if (toUpdate != null) { toUpdate.Next = DateTime.Today.AddDays(1).ToUniversalTime().AddHours(2); } } }
public void Save(OutgoingSmsMessage msg) { lock (_lock) { if (msg.Id == 0) { msg.Id = NextId(); } _outgoingMessages[msg.Id] = msg; } }
public void SenderFailsCallback() { ObjectFactory.Initialize(x => { x.For <ILogging>().Use <TraceLogger>(); x.For <ISmsTransport>().Use <FailureSmsSender>(); x.For <IDataStore>().Use <TestDataStore>(); }); int toSend = 10; int[] count = { 0 }; ManualResetEvent done = new ManualResetEvent(false); bool[] sendSucceeded = new[] { false }; SendCompleteCallback complete = (SentSmsMessageLogEntry result, OutgoingSmsMessage msg) => { sendSucceeded[0] = result.Status != (int)MessageSendStatus.Error; Assert.AreEqual(count[0], msg.Id, "The subscription ID was incorrect"); Assert.AreEqual((int)MessageSendStatus.Error, result.Status); count[0]++; if (count[0] == toSend) { done.Set(); } }; SmsSenderExceptionThrownCallback failed = (OutgoingSmsMessage msg, Exception exception) => { Assert.Fail("The exception callback should not have been called"); }; SmsSenderQueue sender = new SmsSenderQueue(); for (int i = 0; i < 10; i++) { OutgoingSmsMessage msg = new OutgoingSmsMessage { Message = "This is the message", Destination = "+11234567890", Id = i, }; sender.Send(msg, complete, failed); } Assert.IsTrue(done.WaitOne(TimeSpan.FromSeconds(toSend)), "Sending timed out ... that's not good!"); Assert.IsFalse(sendSucceeded[0], "The send should not have been marked as successful"); }
void MessageSent(SentSmsMessageLogEntry result, OutgoingSmsMessage message) { IDataStore store = DataStore.GetInstance(); if (result.Status == (int)MessageSendStatus.Success) { // delete copy local to this store store.Remove(store.OutgoingMessages.Where(m => m.Id == message.Id).FirstOrDefault()); } else { ProcessSendFailure(message); } }
public void Perform_RealAdmin() { Add_Accessor target = new Add_Accessor(); // TODO: Initialize to an appropriate value IncomingSmsMessage message = new IncomingSmsMessage { From = Configuration.GetInstance().AdminNumber, Message = "add This is the added message", }; target.Perform(message); IDataStore store = DataStore.GetInstance(); DailyIdea addedIdea = store.DailyIdeas.Where(i => i.Idea == "This is the added message").First(); OutgoingSmsMessage response = store.OutgoingMessages.Where(o => o.Message == SmsResponseStrings.Add_Success_AddedNewIdea(addedIdea.Id)).First(); Assert.AreEqual(Configuration.GetInstance().AdminNumber, response.Destination); }
private void ProcessSendFailure(OutgoingSmsMessage msg) { IDataStore store = DataStore.GetInstance(); // reload from the local store msg = store.OutgoingMessages.Where(m => m.Id == msg.Id).First(); if (msg != null) { if (msg.Attempts < 10) { msg.Attempts++; DateTime next; if (msg.Attempts < 10) { next = DateTime.UtcNow.AddMinutes(msg.Attempts * 10); } else { next = DateTime.UtcNow.AddHours(18); } msg.NextAttempt = next; store.Save(msg); } else { SentSmsMessageLogEntry entry = new SentSmsMessageLogEntry { Date = DateTime.UtcNow, Destination = msg.Destination, Message = msg.Message, Status = (int)MessageSendStatus.Abandoned, Details = string.Format(CultureInfo.InvariantCulture, "Fatal SMS Send error - giving up on sending message {0} - it was attempted {1} times.", msg.Id, msg.Attempts), }; store.Save(entry); store.Remove(msg); } } }
public void Send(OutgoingSmsMessage msg, SendCompleteCallback complete, SmsSenderExceptionThrownCallback exceptionThrown) { ThrowIfDisposed(); lock (_lock) { if (!queued.Contains(msg.Id)) { _processor.Add(new SmsSenderMessage { Message = msg, Complete = complete, Failed = exceptionThrown, }); queued.Add(msg.Id); } } }
public void Perform_UnknownUser() { string destinationNumber = "+11112223333"; Add_Accessor target = new Add_Accessor(); // TODO: Initialize to an appropriate value IncomingSmsMessage message = new IncomingSmsMessage { From = destinationNumber, Message = "add This is the added message", }; target.Perform(message); IDataStore store = DataStore.GetInstance(); Assert.IsFalse(store.DailyIdeas.Any()); OutgoingSmsMessage response = store.OutgoingMessages.Where(o => o.Message == SmsResponseStrings.PublicHelp()).First(); Assert.AreEqual(destinationNumber, response.Destination); }
private static void ProcessSubscriptions(IOutgoingSmsQueue outgoing, IDataStore store) { DailyIdea idea = DailyIdea.TodaysIdea(DateTime.Today.ToUniversalTime()); if (idea != null) { // now deal with the existing subscriptions // all where doing here is creating entries in the OutgoingSmsMessage table and updating the Next field on the // Subscription. These will be picked up on the next pass through the loop by the message sender. IList <Subscription> toProcess = store.Subscriptions.Where(s => s.Next < DateTime.UtcNow) .Take(outgoing.MessagesPerMinute) .ToList(); foreach (Subscription sub in toProcess) { OutgoingSmsMessage msg = OutgoingSmsMessage.CreateWithDefaults(sub.Phone, idea.Idea); store.ScheduleMessage(msg, sub); } } }
void MessageSendThrewException(OutgoingSmsMessage msg, Exception ex) { LogManager.Log.Error("Exception sending SMS message", ex); ProcessSendFailure(msg); }