// POST api/bsm public HttpResponseMessage Post([FromBody] BsmBundle bundle) { Trace.TraceInformation("[TRACE] Entering BsmController::Post(BsmBundle)..."); if (srBsmQueue == null) { Trace.TraceError("Unable to add BsmBundle to queue-- Inbound BSM queue not created"); Trace.TraceInformation("[TRACE] Exiting BsmController::Post(BsmBundle)..."); return(this.Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Inbound BSM queue does not exist")); } if (this.ModelState.IsValid) { string strQueueMessage = Newtonsoft.Json.JsonConvert.SerializeObject(bundle); Microsoft.WindowsAzure.Storage.Queue.CloudQueueMessage rMessage = new Microsoft.WindowsAzure.Storage.Queue.CloudQueueMessage(strQueueMessage); const int hours = 1; const int mins = 0; const int secs = 0; TimeSpan rTimeToLive = new TimeSpan(hours, mins, secs); Trace.TraceInformation("Adding BsmBundle message to inbound BSM queue..."); srBsmQueue.AddMessage(rMessage, rTimeToLive); Trace.TraceInformation("[TRACE] Exiting BsmController::Post(BsmBundle)..."); return(this.Request.CreateResponse(HttpStatusCode.OK)); } else { Trace.TraceError("Unable to add BsmBundle to queue-- BsmBundle message not properly formatted"); Trace.TraceInformation("[TRACE] Exiting BsmController::Post(BsmBundle)..."); return(this.Request.CreateErrorResponse(HttpStatusCode.BadRequest, "BsmBundle message not properly formatted")); } }
public override void Run() { Trace.TraceInformation("[TRACE] Entering BsmWorkerRole::Run()..."); if (srBsmQueue == null) { Trace.TraceError("ERROR: Unable to run BsmWorkerRole-- Inbound BSM queue does not exist"); Trace.TraceInformation("[TRACE] Exiting BsmWorkerRole::Run()..."); return; } const int minPollWaitPeriod_ms = 10; const int maxPollWaitPeriod_ms = 1000; const int maxQueueMessagePollCount = 32; //32 is the MAX allowed const int messageLeaseTime = 30; int currPollWaitPeriod_ms = maxPollWaitPeriod_ms; while (true) { var rMessages = srBsmQueue.GetMessages(maxQueueMessagePollCount, new TimeSpan(0, 0, 0, messageLeaseTime * maxQueueMessagePollCount)); if (rMessages.Count() > 0) { List <TME_CVData_Input> rCvDataEntriesToAdd = new List <TME_CVData_Input>(); if (currPollWaitPeriod_ms > minPollWaitPeriod_ms) { // Get the queue message count srBsmQueue.FetchAttributes(); int?messageCount = srBsmQueue.ApproximateMessageCount; Trace.WriteLine(String.Format("Processing {0} new queue messages...", messageCount)); } BsmTimeTableLogger.StartNewLogEntry(srBsmQueue, rMessages); foreach (var rMessage in rMessages) { string strMessageJSON = rMessage.AsString; try { /* * Extract raw bsm data from queue message */ BsmBundle rBsmBundle = Newtonsoft.Json.JsonConvert.DeserializeObject <BsmBundle>(strMessageJSON); foreach (var bsm in rBsmBundle.payload) { TME_CVData_Input rCvData = null; try { DateTimeOffset extractStartTime = DateTimeOffset.Now; //Validate conversion and BSM inside 'GenerateFromBsmMessage'. Throw exception with errors. rCvData = GenerateCvDataFromBsmMessage(bsm); if ((DateTimeOffset.Now - extractStartTime).TotalSeconds > 0.5) { Trace.TraceWarning("Took {0} seconds to extract BSM Data", (DateTimeOffset.Now - extractStartTime).TotalSeconds); } } catch (Exception e) { Trace.TraceWarning("Exception occurred when extracting CV Data from BSM Payload\n{0}", e.Message); } //If conversion was good, add to DbSet. if (rCvData != null) { rCvDataEntriesToAdd.Add(rCvData); } } } catch (Newtonsoft.Json.JsonSerializationException e) { Trace.TraceError("Exception when deserializing queue item. Message: '{0}'", e.Message); } finally { currPollWaitPeriod_ms = minPollWaitPeriod_ms; } } BsmTimeTableLogger.SetDeserializationComplete(); foreach (var rMessage in rMessages) { try { srBsmQueue.DeleteMessage(rMessage); } catch (Exception e) { Trace.TraceError("Exception occurred when deleting message from queue. Did the processing of the BSM take longer then the message's lease time?\n{0}", e.Message); } } BsmTimeTableLogger.SetQueueDeleteComplete(); //Save changes to DB. if (rCvDataEntriesToAdd.Count() > 0) { foreach (var rCvData in rCvDataEntriesToAdd) { try { DateTimeOffset dbSetAddStartTime = DateTimeOffset.Now; /* * This use to take forever when the dbSet got large. * This was fixed by adding "base.Configuration.AutoDetectChangesEnabled = false;" * to the dbContext constructor. */ srDbContext.TME_CVData_Input.Add(rCvData); if ((DateTimeOffset.Now - dbSetAddStartTime).TotalSeconds > 0.5) { Trace.TraceWarning("Took {0} seconds to add CvData to DbSet", (DateTimeOffset.Now - dbSetAddStartTime).TotalSeconds); } } catch (Exception e) { Trace.TraceError("Exception occurred when adding CV Data to DbSet\n{0}", e.Message); } } try { srDbContext.SaveChanges(); } catch (Exception e) { Trace.TraceError("Exception occurred when saving changes to Db\n{0}", e); } rCvDataEntriesToAdd.ForEach(x => srDbContext.Entry <TME_CVData_Input>(x).State = System.Data.Entity.EntityState.Detached); } BsmTimeTableLogger.SubmitLogEntry(rCvDataEntriesToAdd.Count()); } else //if(rMessages.Count() == 0) { Trace.WriteLine(String.Format("Waiting {0}ms for new {1} queue items...", currPollWaitPeriod_ms, srBsmQueueName)); Thread.Sleep(currPollWaitPeriod_ms); // Gradually scale up the poll wait period until we reach the max (10,20,40,80,160,...1000) currPollWaitPeriod_ms *= 2; currPollWaitPeriod_ms = Math.Min(currPollWaitPeriod_ms, maxPollWaitPeriod_ms); } } }