public void FireEvent(Event e) { lock (this) { // Transaction events need their names prefixed with platform and app name if (e.IsTransaction) { e.SetNamePrefix(platformName, appName); } // Add global event params if they have not yet been added // Notify the event that we are going to fire it so it can record the time and bake its post data e.Prepare(config.GlobalEventParams); if (e.OneTimeOnly) { if (firedEvents.Contains(e.Name)) { Logging.Log(LogLevel.INFO, "Tapstream ignoring event named \"{0}\" because it is a one-time-only event that has already been fired", e.Name); listener.ReportOperation("event-ignored-already-fired", e.EncodedName); listener.ReportOperation("job-ended", e.EncodedName); return; } else if (firingEvents.Contains(e.Name)) { Logging.Log(LogLevel.INFO, "Tapstream ignoring event named \"{0}\" because it is a one-time-only event that is already in progress", e.Name); listener.ReportOperation("event-ignored-already-in-progress", e.EncodedName); listener.ReportOperation("job-ended", e.EncodedName); return; } firingEvents.Add(e.Name); } Core self = this; string url = String.Format(EVENT_URL_TEMPLATE, accountName, e.EncodedName); string data = postData.ToString() + e.PostData; // Always ask the delegate what the delay should be, regardless of what our delay member says. // The delegate may wish to override it if this is a testing scenario. int actualDelay = del.GetDelay(); #if WINDOWS_PHONE scheduler.Schedule(new Action(() => { #else Task.Delay(TimeSpan.FromSeconds(actualDelay)).ContinueWith((prevResult) => { #endif Response response = platform.Request(url, data, "POST"); bool failed = response.Status < 200 || response.Status >= 300; bool shouldRetry = response.Status < 0 || (response.Status >= 500 && response.Status < 600); lock (self) { if (e.OneTimeOnly) { self.firingEvents.Remove(e.Name); } if (failed) { // Only increase delays if we actually intend to retry the event if (shouldRetry) { // Not every job that fails will increase the retry delay. It will be the responsibility of // the first failed job to increase the delay after every failure. if (delay == 0) { // This is the first job to fail, it must be the one to manage delay timing failingEventId = e.Uid; IncreaseDelay(); } else if (failingEventId == e.Uid) { // This job is failing for a subsequent time IncreaseDelay(); } } } else { if (e.OneTimeOnly) { self.firedEvents.Add(e.Name); platform.SaveFiredEvents(self.firedEvents); listener.ReportOperation("fired-list-saved", e.EncodedName); } // Success of any event resets the delay delay = 0; } } if (failed) { if (response.Status < 0) { Logging.Log(LogLevel.ERROR, "Tapstream Error: Failed to fire event, error={0}", response.Message); } else if (response.Status == 404) { Logging.Log(LogLevel.ERROR, "Tapstream Error: Failed to fire event, http code {0}\nDoes your event name contain characters that are not url safe? This event will not be retried.", response.Status); } else if (response.Status == 403) { Logging.Log(LogLevel.ERROR, "Tapstream Error: Failed to fire event, http code {0}\nAre your account name and application secret correct? This event will not be retried.", response.Status); } else { string retryMsg = ""; if (!shouldRetry) { retryMsg = " This event will not be retried."; } Logging.Log(LogLevel.ERROR, "Tapstream Error: Failed to fire event, http code {0}.{1}", response.Status, retryMsg); } listener.ReportOperation("event-failed", e.EncodedName); if (shouldRetry) { listener.ReportOperation("retry", e.EncodedName); listener.ReportOperation("job-ended", e.EncodedName); if (del.IsRetryAllowed()) { FireEvent(e); } return; } } else { Logging.Log(LogLevel.INFO, "Tapstream fired event named \"{0}\"", e.Name); listener.ReportOperation("event-succeeded", e.EncodedName); } listener.ReportOperation("job-ended", e.EncodedName); #if WINDOWS_PHONE }), TimeSpan.FromSeconds(actualDelay)); #else }); #endif } }
public void prepareEvent(Tapstream ts, Event e) { e.Prepare(ts.config.GlobalEventParams); }
public void prepareEvent(Tapstream ts, Event e) { e.Prepare(ts.config.GlobalEventParams); }
public void FireEvent(Event e) { lock (this) { // Transaction events need their names prefixed with platform and app name if(e.IsTransaction) { e.SetNamePrefix(platformName, appName); } // Add global event params if they have not yet been added // Notify the event that we are going to fire it so it can record the time and bake its post data e.Prepare(config.GlobalEventParams); if (e.OneTimeOnly) { if (firedEvents.Contains(e.Name)) { Logging.Log(LogLevel.INFO, "Tapstream ignoring event named \"{0}\" because it is a one-time-only event that has already been fired", e.Name); listener.ReportOperation("event-ignored-already-fired", e.EncodedName); listener.ReportOperation("job-ended", e.EncodedName); return; } else if (firingEvents.Contains(e.Name)) { Logging.Log(LogLevel.INFO, "Tapstream ignoring event named \"{0}\" because it is a one-time-only event that is already in progress", e.Name); listener.ReportOperation("event-ignored-already-in-progress", e.EncodedName); listener.ReportOperation("job-ended", e.EncodedName); return; } firingEvents.Add(e.Name); } Core self = this; string url = String.Format(EVENT_URL_TEMPLATE, accountName, e.EncodedName); string data = postData.ToString() + e.PostData; // Always ask the delegate what the delay should be, regardless of what our delay member says. // The delegate may wish to override it if this is a testing scenario. int actualDelay = del.GetDelay(); #if WINDOWS_PHONE scheduler.Schedule(new Action(() => { #else Task.Delay(TimeSpan.FromSeconds(actualDelay)).ContinueWith((prevResult) => { #endif Response response = platform.Request(url, data, "POST"); bool failed = response.Status < 200 || response.Status >= 300; bool shouldRetry = response.Status < 0 || (response.Status >= 500 && response.Status < 600); lock(self) { if(e.OneTimeOnly) { self.firingEvents.Remove(e.Name); } if(failed) { // Only increase delays if we actually intend to retry the event if(shouldRetry) { // Not every job that fails will increase the retry delay. It will be the responsibility of // the first failed job to increase the delay after every failure. if(delay == 0) { // This is the first job to fail, it must be the one to manage delay timing failingEventId = e.Uid; IncreaseDelay(); } else if(failingEventId == e.Uid) { // This job is failing for a subsequent time IncreaseDelay(); } } } else { if(e.OneTimeOnly) { self.firedEvents.Add(e.Name); platform.SaveFiredEvents(self.firedEvents); listener.ReportOperation("fired-list-saved", e.EncodedName); } // Success of any event resets the delay delay = 0; } } if(failed) { if(response.Status < 0) { Logging.Log(LogLevel.ERROR, "Tapstream Error: Failed to fire event, error={0}", response.Message); } else if(response.Status == 404) { Logging.Log(LogLevel.ERROR, "Tapstream Error: Failed to fire event, http code {0}\nDoes your event name contain characters that are not url safe? This event will not be retried.", response.Status); } else if(response.Status == 403) { Logging.Log(LogLevel.ERROR, "Tapstream Error: Failed to fire event, http code {0}\nAre your account name and application secret correct? This event will not be retried.", response.Status); } else { string retryMsg = ""; if(!shouldRetry) { retryMsg = " This event will not be retried."; } Logging.Log(LogLevel.ERROR, "Tapstream Error: Failed to fire event, http code {0}.{1}", response.Status, retryMsg); } listener.ReportOperation("event-failed", e.EncodedName); if(shouldRetry) { listener.ReportOperation("retry", e.EncodedName); listener.ReportOperation("job-ended", e.EncodedName); if(del.IsRetryAllowed()) { FireEvent(e); } return; } } else { Logging.Log(LogLevel.INFO, "Tapstream fired event named \"{0}\"", e.Name); listener.ReportOperation("event-succeeded", e.EncodedName); } listener.ReportOperation("job-ended", e.EncodedName); #if WINDOWS_PHONE }), TimeSpan.FromSeconds(actualDelay)); #else }); #endif } }