void SenderWorker(object state) { SenderWorkerState sws = state as SenderWorkerState; if (sws == null) { Log(LogSeverity.Error, "Internal error - SenderWorker got a null state."); return; } string filePath = sws.WorkItemPath; SenderState senderState = sws.State; JsonDeserializer des = senderState.Deserializer; try { string fileText = HttpUtility.UrlDecode(File.ReadAllText(filePath)); if (String.IsNullOrEmpty(fileText)) { Log(LogSeverity.Error, "Empty payload for item '{0}'", filePath); PutWorkItemBack(filePath, senderState); return; } if (!fileText.StartsWith("payload=", StringComparison.Ordinal)) { Log(LogSeverity.Error, "Invalid payload format for item '{0}'", filePath); PutWorkItemBack(filePath, senderState); return; } fileText = fileText.Substring(8); Push push = des.Deserialize <Push> (fileText); push.CHAuthID = senderState.CommitSourceID; Mailer mailer = new Mailer(); if (mailer.Send(push)) { try { File.Delete(filePath); } catch (Exception ex) { Log(LogSeverity.Warning, "Failed to delete work item '{0}', the mail message might be sent twice. Exception {1} was thrown: {2}", filePath, ex.GetType(), ex.Message); } try { CachingFetcher.RemoveCommitsFromCache(push.CHAuthID, push.Commits); } catch (Exception ex) { Log(ex, "Failed to clean up commit cache, some files may have been left behind. {2} ({1})"); } } else { Log(LogSeverity.Info, "Mail not sent."); PutWorkItemBack(filePath, senderState, (push.Commits == null || push.Commits.Count == 0)); } } catch (Exception ex) { Log(ex, "Attempt to send work item '{4}' failed. Exception {1} was thrown: {2}", Path.GetFileName(filePath)); PutWorkItemBack(filePath, senderState); } }
string GetNextWorkItem(SenderState senderState) { string csDataDir = senderState.CsDataDir; lock (senderDirectoryLock) { string file = null; try { string[] files = Directory.GetFiles(csDataDir, "*.json"); if (files == null || files.Length == 0) { return(null); } Array.Sort <string> (files); foreach (string f in files) { if (senderState.IsIgnored(f)) { continue; } file = f; break; } if (file == null) { return(null); } string newFile = file + ".processing"; File.Move(file, newFile); return(newFile); } catch (Exception ex) { if (!String.IsNullOrEmpty(file)) { PutWorkItemBack(file + ".processing", senderState); } Log(ex, "Failed to retrieve next work item from directory '{4}'. Exception '{1}' was thrown: {2}", csDataDir); return(null); } } }
void PutWorkItemBack(string filePath, SenderState senderState, bool isEmpty) { if (String.IsNullOrEmpty(filePath)) { return; } if (!filePath.EndsWith(".processing", StringComparison.Ordinal) || !File.Exists(filePath)) { return; } string newFilePath; if (isEmpty) { newFilePath = filePath.Replace(".processing", ".empty"); } else { newFilePath = filePath.Substring(0, filePath.Length - 11); } lock (senderDirectoryLock) { try { File.Move(filePath, newFilePath); if (isEmpty) { Log(LogSeverity.Info, "Push without commits, file '{0}' marked as empty (will not be processed again).", newFilePath); } else { Log(LogSeverity.Info, "Puting file '{0}' back in queue.", newFilePath); senderState.Ignore(newFilePath); } } catch (Exception ex) { Log(ex, "Failed to put work item file '{4}' back in the queue. Exception '{1} was thrown: {2}", filePath); return; } } }
void Sender(object state) { SenderState senderState = state as SenderState; if (String.IsNullOrEmpty(senderState.CsDataDir)) { Log(LogSeverity.Error, "Need a data directory to work."); return; } if (!Directory.Exists(senderState.CsDataDir)) { return; } string filePath; senderState.Deserializer = new JsonDeserializer(); while (true) { filePath = GetNextWorkItem(senderState); if (filePath == null) { break; } var sws = new SenderWorkerState() { State = senderState, WorkItemPath = filePath }; Thread th = new Thread(_ => { SenderWorker(sws); }); th.IsBackground = true; th.Start(); } }
public void Send(SenderState state) { ThreadPool.QueueUserWorkItem(Sender, state); }
void PutWorkItemBack(string filePath, SenderState senderState) { PutWorkItemBack(filePath, senderState, false); }
public void Send (SenderState state) { ThreadPool.QueueUserWorkItem (Sender, state); }
void PutWorkItemBack (string filePath, SenderState senderState, bool isEmpty) { if (String.IsNullOrEmpty (filePath)) return; if (!filePath.EndsWith (".processing", StringComparison.Ordinal) || !File.Exists (filePath)) return; string newFilePath; if (isEmpty) newFilePath = filePath.Replace (".processing", ".empty"); else newFilePath = filePath.Substring (0, filePath.Length - 11); lock (senderDirectoryLock) { try { File.Move (filePath, newFilePath); if (isEmpty) Log (LogSeverity.Info, "Push without commits, file '{0}' marked as empty (will not be processed again).", newFilePath); else { Log (LogSeverity.Info, "Puting file '{0}' back in queue.", newFilePath); senderState.Ignore (newFilePath); } } catch (Exception ex) { Log (ex, "Failed to put work item file '{4}' back in the queue. Exception '{1} was thrown: {2}", filePath); return; } } }
void PutWorkItemBack (string filePath, SenderState senderState) { PutWorkItemBack (filePath, senderState, false); }
string GetNextWorkItem (SenderState senderState) { string csDataDir = senderState.CsDataDir; lock (senderDirectoryLock) { string file = null; try { string[] files = Directory.GetFiles (csDataDir, "*.json"); if (files == null || files.Length == 0) return null; Array.Sort<string> (files); foreach (string f in files) { if (senderState.IsIgnored (f)) continue; file = f; break; } if (file == null) return null; string newFile = file + ".processing"; File.Move (file, newFile); return newFile; } catch (Exception ex) { if (!String.IsNullOrEmpty (file)) PutWorkItemBack (file + ".processing", senderState); Log (ex, "Failed to retrieve next work item from directory '{4}'. Exception '{1}' was thrown: {2}", csDataDir); return null; } } }