C# Rabbitmq single consumer consume multiple message in single Queue - c#

I have single queue with more than message and i want to consume that message sequencial in
order for another transaction with parse payload foreach message
the problem is when i loop all payload list after get the first paylod why first message
is always still count on list after being loop and always being proceed
and the second message and so on not being consumed
my sample list messsage array is "
first message : ["test123#gmail.com","smtp.email.io","admin","2525","123","Test_200999#yahoo.com","Email Confirmation","Hello World"]
second message :
["test123#gmail.com","smtp.email.io","admin","2525","123","Test_200998#yahoo.com","Email Confirmation","Hello World"]
third message
["test123#gmail.com","smtp.email.io","admin","2525","123","Test_200997#yahoo.com","Email Confirmation","Hello World"]
here's my code
private static async void ExcecutePayload(CancellationToken cancellationToken)
{
var factory = new ConnectionFactory
{
HostName = "localhost"
};
var connection = factory.CreateConnection();
using var channel = connection.CreateModel();
channel.QueueDeclare("email_confirmation_notifications", durable: true, exclusive: false, autoDelete: false,arguments: null);
channel.BasicQos(0, 1, false);
var consumer = new EventingBasicConsumer(channel);
EmailModel _model = new EmailModel();
var s1 = new List<string>();
string s2 = "";
bool
first = false,
second = false;
var random = new Random();
consumer.Received += (model, eventArgs) =>
{
var processingtime = random.Next(1, 10);
var body = eventArgs.Body.ToArray();
var message = Encoding.UTF8.GetString(body);
foreach (char c in message)
{
if (second)
{
s1.Add(s2);
s2 = "";
first = false;
second = false;
}
if (first)
{
if (c == '"')
{
second = true;
}
else
{
s2 += c;
}
}
if (c == '"' && !first && !second)
{
first = true;
}
}
if (second && first)
{
s1.Add(s2);
}
foreach (var item in s1.Select((value, i) => new { i, value }).ToList())
{
var value = item.value;
var index = item.i;
if (index == 0) { _model.Sender = value; };
if (index == 1) { _model.Host = value; };
if (index == 2) { _model.UserName = value; };
if (index == 3) { _model.Port = value; };
if (index == 4) { _model.Password = value; };
if (index == 5) { _model.To = value; };
if (index == 6) { _model.Subject = value; };
if (index == 7) { _model.Body = value; };
}
try
{
InsertTransaction(_model, cancellationToken);
SendEmailAsync(_model, cancellationToken);
}
catch (Exception ex)
{
throw ex;
}
Console.WriteLine($"Notification email has sent to: {string.Join(", ", _model.To)}");
Task.Delay(TimeSpan.FromSeconds(processingtime), cancellationToken).Wait();
channel.BasicAck(deliveryTag: eventArgs.DeliveryTag, multiple: false);
};
await Task.CompletedTask;
channel.BasicConsume(queue: "email_confirmation_notifications", autoAck: false, consumer: consumer);
Console.ReadKey();
}

Related

How to handle New transaction is not allowed because there are other threads running in the session for multiple calls or to save as list of Entities

Hi I am using Entity Framework Code First, I have a collection of Entities that need to be saved, but I have my EF Repository created as below
public T Create(T item)
{
try
{
if (ufb != null && ufb.CurrentUser != null)
{
SetValue("CreatedByUserId", item, ufb.CurrentUser.Id);
SetValue("UpdatedByUserId", item, ufb.CurrentUser.Id);
}
SetValue("DateCreated", item, DateTime.Now);
SetValue("DateUpdated", item, DateTime.Now);
var newEntry = this.DbSet.Add(item);
this.Context.Database.Log = message => LogHandler.LogInfo(1111, message);
try
{
this.Context.SaveChanges();
}
catch (Exception ex)
{
LogHandler.LogInfo(2501, ex.Message);
}
BuildMetaData(item, true, true);
return newEntry;
}
catch (DbEntityValidationException dbEx)
{
// http://forums.asp.net/t/2014382.aspx?Validation+failed+for+one+or+more+entities+See+EntityValidationErrors+property+for+more+details+
string msg = string.Empty;
foreach (var validationErrors in dbEx.EntityValidationErrors)
{
foreach (var validationError in validationErrors.ValidationErrors)
{
msg += validationError.PropertyName;
msg += "---";
msg += validationError.ErrorMessage;
msg += "||";
}
}
throw new Exception("7777 CREATE EntityValidationErrors: " + msg);
}
}
My calling method is as below:
public List<VehicleInfo> Create(List<VehicleInfo> vehicleInfos, string Entity, int EntityId)
{
bool vehicleExists = false; List<VehicleInfo> newVehicleInfos = null;
if ((vehicleInfos != null) && (vehicleInfos.Count > 0))
{
newVehicleInfos = new List<VehicleInfo>();
foreach (VehicleInfo vehicleInfo in vehicleInfos)
{
vehicleExists = false;
if (vehicleInfo != null)
{
vehicleExists = this.VehicleExists(vehicleInfo.VehicleId, Entity, EntityId);
vehicleInfo.Entity = Entity;
vehicleInfo.EntityId = EntityId;
VehicleInfo v = this.UnitOfWork.VehicleInfoRepository.Create(vehicleInfo);
newVehicleInfos.Add(v);
}
}
}
return newVehicleInfos;
}
Hence when I am calling repositories create method for multiple times, its throwing me the above error, any help or suggestion would be very helpful, please thank you.
void BuildMetaDataNoThread(object item, bool active, bool isNew = false)
{
if (item.GetType() != typeof(JsonObject))
{
var dm = new DataAccessUnitOfWork(Constants.DefaultConnection);
var qtype = item.GetType();
if (qtype.BaseType.BaseType != null)
{
if ((isNew && qtype.BaseType.Name == typeof(ModelBase).Name) | qtype.BaseType.BaseType.Name == typeof(ModelBase).Name)
{
Thread.Sleep(500);
//collect data
var element = (ModelBase)item;
element.BuildMetaData(DataRequestType.CurrentItem);
var records = ModelBase.MetaData;
ModelBase.MetaData = new List<ModelRecord> { };
if (records == null) return;
foreach (ModelRecord r in records)
{
if (r!=null)
{
var jsr = new JavaScriptSerializer();
//object meta = r;
object rdata = r.Data;
var type = rdata.GetType();
var token = type.BaseType.Name;
List<string> include = r.Include;
// Cycle-through clieanup of models to be encoded into Json Data.
// this helper eliminates infinate relations by including records specified
// by a list of strings
if (include.Where(x => x.Contains("CreatedByUser")).Count() == 0)
include.Add("CreatedByUser");
if (include.Where(x => x.Contains("UpdatedByUser")).Count() == 0)
include.Add("UpdatedByUser");
var data = ClassCloner.CollectData(rdata, include);
List<string> tags = ClassCloner.CollectTags(data);
string _tags = "";
tags.ForEach((xtm) =>
{
_tags += xtm + ',';
});
var json = jsr.Serialize(data);
int id = 0;
//get identity
foreach (var prop in type.GetProperties())
{
if (id == 0)
{
foreach (var cp in prop.CustomAttributes)
{
if (cp.AttributeType.Name == "KeyAttribute")
{
var _id = ((Dictionary<string, object>)data)[prop.Name];
id = (int)_id;
break;
}
}
}
else { break; }
}
var query = dm.JsonObjectRepository.GetAll();
var key = "_" + token;
var _data = (Dictionary<string, object>)data;
var ExistingMetaData = (from x in query where x.SourceKey == key && x.SourceId == id select x).FirstOrDefault();
if (ExistingMetaData != null)
{
if (_data.ContainsKey("DateUpdated")) ExistingMetaData.Date = (DateTime)_data["DateUpdated"];
ExistingMetaData.SourceData = data;
ExistingMetaData.Encode();
ExistingMetaData.Active = active;
ExistingMetaData.SearchTags = _tags;
dm.JsonObjectRepository.Update(ExistingMetaData);
}
else
{
var newData = new JsonObject
{
Active = true,
Date = (DateTime)_data["DateUpdated"],
SourceData = data,
SourceId = id,
SourceKey = key,
SearchTags = _tags,
TargetKey = "GlobalSearchMetaData"
};
newData.Encode();
dm.JsonObjectRepository.Create(newData);
}
}
}
}
}
}
}
void BuildMetaData(object dataRecord, bool active, bool isNew)
{
new Thread((item) => { BuildMetaDataNoThread(item, active, isNew); }).Start(dataRecord);
}

Skipped 675 frames! The application may be doing too much work on its main thread. How to make app run process in background without freezing the UI?

I have an news aggregator and in debug i have the following:
Skipped 675 frames! The application may be doing too much work on its main thread.
I am loading only from 12 sites. Is there a way to to do all this loading in background without the whole app freezing?
EDIT:
Method to get one news
public async static Task<NewsContent> oneNews(string category,string site)
{
if(sites.Count==0)
addElements();
GetNews gn = new GetNews(site,false);
Random rn = new Random();
var s = await gn.news(rn.Next(0,2));
return s;
}
The GetNews class:
class GetNews
{
string url;
bool isMultiple;
public GetNews(string url,bool isMultiple)
{
this.url = url;
this.isMultiple = isMultiple;
}
public async Task<NewsContent> news(int i)
{
List<NewsContent> feedItemsList = new List<NewsContent>();
try
{
WebRequest webRequest = WebRequest.Create(url);
WebResponse webResponse = webRequest.GetResponse();
Stream stream = webResponse.GetResponseStream();
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load(stream);
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDocument.NameTable);
nsmgr.AddNamespace("dc", xmlDocument.DocumentElement.GetNamespaceOfPrefix("dc"));
nsmgr.AddNamespace("content", xmlDocument.DocumentElement.GetNamespaceOfPrefix("content"));
XmlNodeList itemNodes = xmlDocument.SelectNodes("rss/channel/item");
NewsContent feedItem = new NewsContent();
if (itemNodes[i].SelectSingleNode("title") != null)
{
feedItem.title = itemNodes[i].SelectSingleNode("title").InnerText;
}
if (itemNodes[i].SelectSingleNode("link") != null)
{
feedItem.url = itemNodes[i].SelectSingleNode("link").InnerText;
}
if (itemNodes[i].SelectSingleNode("pubDate") != null)
{
var time = itemNodes[i].SelectSingleNode("pubDate").InnerText;
feedItem.time = getHour(time);
}
if (itemNodes[i].SelectSingleNode("description") != null)
{
feedItem.desc = itemNodes[i].SelectSingleNode("description").InnerText;
}
if (itemNodes[i].SelectSingleNode("content:encoded", nsmgr) != null)
{
feedItem.content = itemNodes[i].SelectSingleNode("content:encoded", nsmgr).InnerText;
}
else
{
feedItem.content = feedItem.desc;
}
feedItem.imageURL = getImage(feedItem.content);
var sourcename = url.Split(new[] { "//" }, StringSplitOptions.None)[1];
feedItem.newsSource = sourcename.Split(new[] { "/" }, StringSplitOptions.None)[0];
if (feedItem.content.Contains("<p>"))
{
var shortContent = feedItem.content.Split(new[] { "<p>" }, StringSplitOptions.None)[1];
string finalShortContent = "";
for (int ii = 0; ii < shortContent.Length; ii++)
{
if (ii > 200 && shortContent[ii].Equals(' '))
break;
while (shortContent[ii].Equals('<') || shortContent[ii].Equals('p') || shortContent[ii].Equals('/') || shortContent[ii].Equals('>'))
ii++;
try
{
finalShortContent += shortContent[ii];
}
catch (Exception e)
{
break;
}
}
finalShortContent += "...";
feedItem.shortcontent = finalShortContent;
}
return feedItem;
}
catch (Exception e)
{
return null;
}
}
string getImage(string full)
{
try
{
var code = full.Split(new[] { "src=\"" }, StringSplitOptions.None)[1];
var fin = code.Split(new[] { "\"" }, StringSplitOptions.None)[0];
return fin;
}
catch(Exception e)
{
return null;
}
}
List<int> getHour(string full)
{
try
{
List<int> smh = new List<int>();
var ph = full.Split(new[] { "2020 " }, StringSplitOptions.None)[1];
var hour = ph.Split(new[] { ":" }, StringSplitOptions.None);
smh.Add(Int32.Parse(hour[0]));
smh.Add(Int32.Parse(hour[1]));
var second = hour[2].Split(new[] { " " }, StringSplitOptions.None)[0];
smh.Add(Int32.Parse(second));
return smh;
}catch(Exception)
{
return null;
}
}
}
Try this. It should put the function in another thread
await Task.Run(async () =>
{
//function
});

Parsing out URLs in email messages

I'm having an issue in some of my code, i cannot seem to think of the best way to do this, all i want to do is extract a URL from a pop3 email message depending on if the domain is in the "to check" array, for example if "stackoverflow.com" is in the email message, i would extract all urls in the message body that contains "stackoverflow.com" in it, and just perform a quick WebClient() request with that url.
Code:
private void BgwEmails_DoWork_1(object sender, DoWorkEventArgs e)
{
try
{
bool finished = false;
Pop3Client pop3 = new Pop3Client();
if (pop3.Connected)
{
pop3.Disconnect();
}
pop3.Connect(txtBoxMailServer.Text, int.Parse(txtBoxPort.Text), chkSSL.Checked);
pop3.Authenticate(txtBoxUsername.Text, txtBoxPassword.Text, AuthenticationMethod.UsernameAndPassword);
int messageCount = pop3.GetMessageCount();
if (messageCount == 0)
{
return;
}
Helpers.ReturnMessage("[ " + messageCount + " ] Message(s) in your inbox.");
int count = 0;
for (int d = 1; d <= messageCount; d++)
{
bgwEmails.WorkerSupportsCancellation = true;
if (bgwEmails.CancellationPending)
{
e.Cancel = true;
Helpers.ReturnMessage($"Cancelling link activator ...");
return;
}
if (finished)
{
return;
}
OpenPop.Mime.Message message = null;
message = pop3.GetMessage(d);
if (null == message || null == message.MessagePart || null == message.MessagePart.MessageParts) {
continue;
}
string textFromMessage = null;
try
{
textFromMessage = message?.MessagePart?.MessageParts[0]?.GetBodyAsText();
} catch (Exception) {
continue;
}
MessagePart messagePart = message.MessagePart.MessageParts[0];
if (null == messagePart || null == messagePart.BodyEncoding || null == messagePart.Body || null == messagePart.BodyEncoding.GetString(messagePart.Body)) {
continue;
}
string linkToCheck;
using (var wc = new WebClient())
{
linkToCheck = wc.DownloadString("https://www.thesite.com/api.php?getActivationLinks=1");
}
var linksToClickArray = linkToCheck.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
//Helpers.ReturnMessage(textFromMessage);
for (var i = 0; i < linksToClickArray.Length; i++)
{
var regex = new Regex(linksToClickArray[i], RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Singleline);
var matches = regex.Matches(textFromMessage);
foreach (Match match in matches)
{
if (match.Success)
{
count++;
Invoke(new MethodInvoker(() => { listBoxEmailsClicked.Items.Add("Clicked: " + match.Value); }));
using (WebClient wc = new WebClient())
{
Helpers.ReturnMessage(match.Value);
wc.DownloadString(match.Value);
}
}
}
}
if (null != textFromMessage)
{
Invoke(new MethodInvoker(() => { txtStatusMessages.AppendText(textFromMessage); }));
}
}
Helpers.ReturnMessage($"Emails downloaded successfully! You clicked [ " + count + " ] activation links.");
} catch (Exception ex) {
Helpers.ReturnMessage($"POP3 Error: " + ex.Message + ".");
}
}
I do a request here: https://www.thesite.com/api.php?getActivationLinks=1 which contains a list of domains to check for in the messages, they just come back one line at a time like:
thesite1.com
thesite2.com
etc
The code works as far as connetcing and downloading, i just cannot seem to think of a way to parse of the urls only if it matches a domain in the target list, any help or advice would be appreciated.

Postmark SendMessageAsync Message not sending Email c#

Here is my Code snippet to send email using postmark
public async Task<bool> SendEmail(CustomMailMessage mailMessage)
{
HeaderCollection headers = new HeaderCollection();
if (mailMessage.Headers != null)
{
var items = mailMessage.Headers.AllKeys.SelectMany(mailMessage.Headers.GetValues, (k, v) => new { key = k, value = v });
foreach (var item in items)
{
headers.Add(item.key, item.value);
}
}
var message = new PostmarkDotNet.PostmarkMessage()
{
To = mailMessage.To,
Cc = mailMessage.Cc,
Bcc = mailMessage.Bcc,
From = mailMessage.FromName + "<" + mailMessage.From + ">",
TrackOpens = true,
Subject = mailMessage.Subject,
TextBody = mailMessage.Body,
HtmlBody = mailMessage.HtmlBody,
Headers = headers,
};
if (mailMessage.AttachmentsPath != null)
{
foreach (string file in mailMessage.AttachmentsPath)
{
var imageContent = File.ReadAllBytes(file);
message.AddAttachment(imageContent, Path.GetFileName(file), MimeMapping.GetMimeMapping(file), null);
}
}
var client = new PostmarkClient(ConfigurationSettings.AppSettings["postmarkServerToken"].ToString(), "https://api.postmarkapp.com", 30);
var sendResult = await client.SendMessageAsync(message);
if (sendResult.Status== PostmarkStatus.Success)
{
return true;
}
else
{
return false;
}
}
When I try to send email "var sendResult = await client.SendMessageAsync(message);" didn't get any response when hitting this line, and when send mail again got message "The transaction has aborted."
Please Help

OutOfMemory Exception for Parallel.ForEach

I have a console application which runs as 32 bit process(we cant change it to 64 bit) and is throwing Out of memory Exception. We traced minor Memory leak(related to Entity Framework repository) in a downstream process but with that too application should not cross 2 GB memory.
One thing i want to understand is sometimes application processes 2500 records while other times it fails at 100.(Server memory utilization is under 60% when this application is running
I am using Parallel.forEach and controlling number of threads to 4 using ParallelOptions. Can anybody suggest making the application on a single thread may by any chance resolve the problem.
(The application didn't fail in any lower environment but only in production and giving us a very hard time).
Below is the code snippet.
Thanks In Advance,
Rohit
protected override void Execute(IEnumerable<PlanPremiumDetails> argument)
{
if (argument.Any())
{
var EnrollmentRequests = argument.GroupBy(c => c.CaseNumber).ToList();
SelectedPlanPremiumDetails request;
EnrollmentResponse enrollmentResponse;
bool taskStatus;
Common.Status.TotalAutoEnrollRecords = EnrollmentRequests.Count;
Common.StartTimer();
Action<IGrouping<int,PlanPremiumDetails>> processRequest = eRequest =>
{
int caseNumber;
List<EnrolledIndividual> enrolledIndividuals;
try
{
string errorMessage;
caseNumber = eRequest.Key;
if (eRequest.Any(f => f.FailedMCOEnrollmentId > 0))
{
request = FailedMcoRequest(eRequest, caseNumber);
enrollmentResponse = InvokeEnrollment(request);
if (enrollmentResponse.OverallStatus == false && enrollmentResponse.ErrorInformationMA != null)
{
StringBuilder messages = new StringBuilder();
if (enrollmentResponse.ErrorInformationMA.ErrorInformationPostMcaps != null)
{
messages.Append(enrollmentResponse.ErrorInformationMA.ErrorInformationPostMcaps.Message);
Exception innerExp = enrollmentResponse.ErrorInformationMA.ErrorInformationPostMcaps.InnerException;
if (innerExp != null)
{
// messages.Append(enrollmentResponse.ErrorInformationMA.ErrorInformationPostMcaps.InnerException.Message);
do
{
messages.Append(innerExp.Message);
innerExp = innerExp.InnerException;
}
while (innerExp != null);
}
}
else
{
if (enrollmentResponse.ErrorInformationMA != null && enrollmentResponse.ErrorInformationMA.InnerErrorInfo != null)
{
foreach (var msg in enrollmentResponse.ErrorInformationMA.InnerErrorInfo)
{
messages.Append( string.Format(#"ErrorCode: {0}, ErrorMessage: {1} ",msg.ErrorCode,msg.ErrorMessage));
}
}
}
errorMessage = Convert.ToString(messages);
Common.Errors.Add(new Exception(String.Format(ConfigurationManager.AppSettings["FailedEnrollErrorText"], caseNumber, errorMessage), enrollmentResponse.ErrorInformationMA.ErrorInformationPostMcaps));
taskStatus = GenerateTask(eRequest, caseNumber, false, errorMessage);
if (taskStatus)
{
UpdateTriggerStatus(caseNumber, "Y");
}
else
{
UpdateTriggerStatus(caseNumber, "N");
Common.Errors.Add(new Exception(String.Format(ConfigurationManager.AppSettings["FailedEnrollErrorText"], caseNumber, "Task Creation")));
}
}
else
{
Common.Status.Success = (Common.Status.Success + 1);
UpdateTriggerStatus(caseNumber, "Y");
}
}
else
{
enrolledIndividuals = eRequest.Select(p => new EnrolledIndividual
{
IndividualId = p.IndividualId,
EdgTraceId = p.EdgTraceId,
EDGNumber = p.EDGNumber
}).ToList();
request = new SelectedPlanPremiumDetails()
{
EmployerId = 0,
CaseNumber = caseNumber,
CallBackId = Common.ApplicationName,
SourceSystem = EnrollmentLibrary.SourceSystem.MAAUTOASSIGN,
AutoAssignMCOIndividuals = enrolledIndividuals
};
enrollmentResponse = InvokeEnrollment(request);
if (enrollmentResponse.OverallStatus == false && enrollmentResponse.ErrorInformationMA != null)
{
StringBuilder messages = new StringBuilder();
if (enrollmentResponse.ErrorInformationMA.ErrorInformationPostMcaps != null)
{
messages.Append(enrollmentResponse.ErrorInformationMA.ErrorInformationPostMcaps.Message);
Exception innerExp = enrollmentResponse.ErrorInformationMA.ErrorInformationPostMcaps.InnerException;
if (innerExp != null)
{
// messages.Append(enrollmentResponse.ErrorInformationMA.ErrorInformationPostMcaps.InnerException.Message);
do
{
messages.Append(innerExp.Message);
innerExp = innerExp.InnerException;
}
while (innerExp != null);
}
}
else
{
if (enrollmentResponse.ErrorInformationMA != null && enrollmentResponse.ErrorInformationMA.InnerErrorInfo.Count != null)
{
foreach (var msg in enrollmentResponse.ErrorInformationMA.InnerErrorInfo)
{
messages.Append(string.Format(#"ErrorCode: {0}, ErrorMessage: {1} ", msg.ErrorCode, msg.ErrorMessage));
}
}
}
errorMessage = Convert.ToString(messages);
Common.Errors.Add(new Exception(String.Format(ConfigurationManager.AppSettings["AutoEnrollErrorText"], caseNumber, errorMessage), enrollmentResponse.ErrorInformationMA.ErrorInformationPostMcaps));
}
else
{
// Update status to be saved in InterfaceSummary table.
Common.Status.Success = (Common.Status.Success + 1);
}
}
}
catch(Exception ex)
{
Common.Errors.Add(new Exception(String.Format(ConfigurationManager.AppSettings["AutoEnrollErrorText"], eRequest.Key, ex.Message), ex));
}
};
}
int dParallelism = Convert.ToInt32(ConfigurationManager.AppSettings["DegreeofParallelism"]);
Parallel.ForEach(EnrollmentRequests,
new ParallelOptions() { MaxDegreeOfParallelism = dParallelism > 0 ? dParallelism : 1 },
processRequest);

Categories

Resources