internal static TriggeredJobHistoryData DeserializeTriggeredJobHistoryData(JsonElement element) { Optional <string> kind = default; ResourceIdentifier id = default; string name = default; ResourceType type = default; Optional <IList <TriggeredJobRun> > runs = default; foreach (var property in element.EnumerateObject()) { if (property.NameEquals("kind")) { kind = property.Value.GetString(); continue; } if (property.NameEquals("id")) { id = new ResourceIdentifier(property.Value.GetString()); continue; } if (property.NameEquals("name")) { name = property.Value.GetString(); continue; } if (property.NameEquals("type")) { type = property.Value.GetString(); continue; } if (property.NameEquals("properties")) { if (property.Value.ValueKind == JsonValueKind.Null) { property.ThrowNonNullablePropertyIsNull(); continue; } foreach (var property0 in property.Value.EnumerateObject()) { if (property0.NameEquals("runs")) { if (property0.Value.ValueKind == JsonValueKind.Null) { property0.ThrowNonNullablePropertyIsNull(); continue; } List <TriggeredJobRun> array = new List <TriggeredJobRun>(); foreach (var item in property0.Value.EnumerateArray()) { array.Add(TriggeredJobRun.DeserializeTriggeredJobRun(item)); } runs = array; continue; } } continue; } } return(new TriggeredJobHistoryData(id, name, type, kind.Value, Optional.ToList(runs))); }
private static string CalculateETag(TriggeredJobRun triggeredJobRun) { // during a job's life time, the status and endtime could change, so // a job run state is made of its id, status, and end time. return(string.Format(CultureInfo.CurrentCulture, "\"{0:x}-{1:x}-{2:x}\"", triggeredJobRun.Id.GetHashCode(), triggeredJobRun.Status.GetHashCode(), triggeredJobRun.EndTime.Ticks.GetHashCode())); }
public void DnxWebJobRunsCorrectly() { RunScenario("DnxWebJobRunsCorrectly", appManager => { const string jobName = "dnxJob"; var program = @"using System; namespace WebJob { class Program { static void Main(string[] args) { Console.WriteLine(""Hello Dnx!!""); } } }"; var project = @"{ ""dependencies"": { }, ""frameworks"": { ""dnx451"": { } } }"; appManager.VfsManager.WriteAllText(TriggeredJobBinPath + "/" + jobName + "/" + "Program.cs", program); appManager.VfsManager.WriteAllText(TriggeredJobBinPath + "/" + jobName + "/" + "project.json", project); var expectedWebJob = new TriggeredJob { Name = jobName, JobType = "triggered", RunCommand = "project.json" }; var webjob = appManager.JobsManager.GetTriggeredJobAsync(jobName).Result; AssertTriggeredJob(expectedWebJob, webjob); appManager.JobsManager.InvokeTriggeredJobAsync(jobName).Wait(); TriggeredJobRun jobRun = null; WaitUntilAssertVerified( "Dnx Triggered job", TimeSpan.FromSeconds(30), () => { var jobHistory = appManager.JobsManager.GetTriggeredJobHistoryAsync(jobName).Result; jobRun = jobHistory.TriggeredJobRuns.First(); Assert.Equal("Success", jobRun.Status); }); var logPath = jobRun.OutputUrl.AbsoluteUri.Split(new[] { "/vfs/" }, StringSplitOptions.RemoveEmptyEntries).Last(); var jobOutput = appManager.VfsManager.ReadAllText(logPath); Assert.True(jobOutput.Contains("Hello Dnx!!")); }); }
private async void ReportTriggeredJobFinished(string jobName, string jobRunId) { TriggeredJobRun triggeredJobRun = GetJobRun(jobName, jobRunId); if (triggeredJobRun == null) { return; } await _hooksManager.PublishEventAsync(HookEventTypes.TriggeredJobFinished, triggeredJobRun); }
public HttpResponseMessage GetTriggeredJobRun(string jobName, string runId) { TriggeredJobRun triggeredJobRun = _triggeredJobsManager.GetJobRun(jobName, runId); if (triggeredJobRun != null) { return(Request.CreateResponse(HttpStatusCode.OK, triggeredJobRun)); } return(Request.CreateResponse(HttpStatusCode.NotFound)); }
private void AssertTriggeredJobRun(ApplicationManager appManager, TriggeredJobRun actualTriggeredJobRun, string expectedStatus, string expectedOutput = null, string expectedError = null) { Assert.NotNull(actualTriggeredJobRun); Assert.Equal(expectedStatus, actualTriggeredJobRun.Status); Assert.NotNull(actualTriggeredJobRun.Duration); Assert.NotNull(actualTriggeredJobRun.EndTime); Assert.NotNull(actualTriggeredJobRun.Id); Assert.NotNull(actualTriggeredJobRun.StartTime); Assert.NotNull(actualTriggeredJobRun.Url); AssertUrlContentAsync(appManager, actualTriggeredJobRun.OutputUrl, expectedOutput).Wait(); }
internal TriggeredWebJobData(ResourceIdentifier id, string name, ResourceType resourceType, SystemData systemData, string kind, TriggeredJobRun latestRun, Uri historyUri, Uri schedulerLogsUri, string runCommand, Uri uri, Uri extraInfoUri, WebJobType?webJobType, string error, bool?usingSdk, IDictionary <string, BinaryData> settings) : base(id, name, resourceType, systemData, kind) { LatestRun = latestRun; HistoryUri = historyUri; SchedulerLogsUri = schedulerLogsUri; RunCommand = runCommand; Uri = uri; ExtraInfoUri = extraInfoUri; WebJobType = webJobType; Error = error; UsingSdk = usingSdk; Settings = settings; }
internal TriggeredWebJobData(ResourceIdentifier id, string name, ResourceType type, SystemData systemData, string kind, TriggeredJobRun latestRun, string historyUrl, string schedulerLogsUrl, string runCommand, string url, string extraInfoUrl, WebJobType?webJobType, string error, bool?usingSdk, IDictionary <string, object> settings) : base(id, name, type, systemData, kind) { LatestRun = latestRun; HistoryUrl = historyUrl; SchedulerLogsUrl = schedulerLogsUrl; RunCommand = runCommand; Url = url; ExtraInfoUrl = extraInfoUrl; WebJobType = webJobType; Error = error; UsingSdk = usingSdk; Settings = settings; }
private void VerifyTriggeredJobTriggers(ApplicationManager appManager, string jobName, int expectedNumberOfRuns, string expectedStatus, string expectedOutput = null, string expectedError = null, string arguments = null) { appManager.JobsManager.InvokeTriggeredJobAsync(jobName, arguments).Wait(); WaitUntilAssertVerified( "verify triggered job run", TimeSpan.FromSeconds(20), () => { TriggeredJobHistory triggeredJobHistory = appManager.JobsManager.GetTriggeredJobHistoryAsync(jobName).Result; Assert.NotNull(triggeredJobHistory); Assert.Equal(expectedNumberOfRuns, triggeredJobHistory.TriggeredJobRuns.Count()); TriggeredJobRun triggeredJobRun = triggeredJobHistory.TriggeredJobRuns.FirstOrDefault(); AssertTriggeredJobRun(appManager, triggeredJobRun, jobName, expectedStatus, expectedOutput, expectedError); }); }
public TriggeredJobHistory GetJobHistory(string jobName, string etag, out string currentETag) { currentETag = null; var triggeredJobRuns = new List <TriggeredJobRun>(); DirectoryInfoBase[] jobRunsDirectories = GetJobRunsDirectories(jobName); if (jobRunsDirectories == null) { return(null); } bool isLatest = true; // Order runs by name (date) descending foreach (DirectoryInfoBase jobRunDirectory in jobRunsDirectories.OrderByDescending(j => j.Name)) { TriggeredJobRun triggeredJobRun = BuildJobRun(jobRunDirectory, jobName, isLatest); if (triggeredJobRun != null) { if (isLatest) { // The history state is determined by the most recent invocation, // as previous ones are immutable (beind historical records). currentETag = CalculateETag(triggeredJobRun); if (currentETag == etag) { return(null); } } triggeredJobRuns.Add(triggeredJobRun); isLatest = false; } } if (triggeredJobRuns.Count == 0) { currentETag = string.Format(CultureInfo.CurrentCulture, "\"{0:x}-{1:x}\"", jobName.GetHashCode(), "EMPTY".GetHashCode()); } return(new TriggeredJobHistory { TriggeredJobRuns = triggeredJobRuns }); }
private void OnSchedule(TriggeredJobSchedule triggeredJobSchedule) { bool invoked = false; try { string triggeredJobName = triggeredJobSchedule.TriggeredJob.Name; TriggeredJobRun latestTriggeredJobRun = _triggeredJobsManager.GetLatestJobRun(triggeredJobName); DateTime lastRun = latestTriggeredJobRun != null ? latestTriggeredJobRun.StartTime : DateTime.Now.AddMinutes(-1); // Make sure we are on schedule // Check for the next occurence after the last run (as of now) // If it is still now, invoke the triggered job // If it's not now (in the future) reschedule the triggered job schedule starting with the last triggered job run TimeSpan currentSchedule = triggeredJobSchedule.Schedule.GetNextInterval(lastRun, ignoreMissed: true); if (currentSchedule == TimeSpan.Zero) { _triggeredJobsManager.InvokeTriggeredJob(triggeredJobName, null, "Schedule - " + triggeredJobSchedule.Schedule); invoked = true; } else { triggeredJobSchedule.Reschedule(lastRun); return; } } catch (ConflictException) { // Ignore as this is expected when running multiple instances } catch (Exception ex) { _traceFactory.GetTracer().TraceError(ex); } if (invoked) { triggeredJobSchedule.Logger.LogInformation("WebJob invoked"); } triggeredJobSchedule.Reschedule(DateTime.Now); }
private void VerifyTriggeredJobTriggers(ApplicationManager appManager, string jobName, int expectedNumberOfRuns, string expectedStatus, string expectedOutput = null, string expectedError = null, string arguments = null, bool scheduledTriggeredJob = false) { if (!scheduledTriggeredJob) { Uri runLocation = appManager.JobsManager.InvokeTriggeredJobAsync(jobName, arguments).Result; Assert.Contains("api/triggeredwebjobs", runLocation.AbsoluteUri); Assert.Contains("history", runLocation.AbsoluteUri); } try { WaitUntilAssertVerified( "verify triggered job run", TimeSpan.FromSeconds(30), () => { TriggeredJobHistory triggeredJobHistory = appManager.JobsManager.GetTriggeredJobHistoryAsync(jobName).Result; Assert.NotNull(triggeredJobHistory); Assert.Equal(expectedNumberOfRuns, triggeredJobHistory.TriggeredJobRuns.Count()); TriggeredJobRun triggeredJobRun = triggeredJobHistory.TriggeredJobRuns.FirstOrDefault(); AssertTriggeredJobRun(appManager, triggeredJobRun, jobName, expectedStatus, expectedOutput, expectedError); }); } catch { // On error trace the scheduler log if it is a scheduler job if (scheduledTriggeredJob) { try { string schedulerLog = appManager.VfsManager.ReadAllText(JobsDataPath + "/triggered/" + jobName + "/job_scheduler.log"); TestTracer.Trace("Scheduler log - " + schedulerLog); } catch { } } throw; } }
internal static TriggeredWebJobData DeserializeTriggeredWebJobData(JsonElement element) { Optional <string> kind = default; ResourceIdentifier id = default; string name = default; ResourceType type = default; SystemData systemData = default; Optional <TriggeredJobRun> latestRun = default; Optional <Uri> historyUrl = default; Optional <Uri> schedulerLogsUrl = default; Optional <string> runCommand = default; Optional <Uri> url = default; Optional <Uri> extraInfoUrl = default; Optional <WebJobType> webJobType = default; Optional <string> error = default; Optional <bool> usingSdk = default; Optional <IDictionary <string, BinaryData> > settings = default; foreach (var property in element.EnumerateObject()) { if (property.NameEquals("kind")) { kind = property.Value.GetString(); continue; } if (property.NameEquals("id")) { id = new ResourceIdentifier(property.Value.GetString()); continue; } if (property.NameEquals("name")) { name = property.Value.GetString(); continue; } if (property.NameEquals("type")) { type = property.Value.GetString(); continue; } if (property.NameEquals("systemData")) { systemData = JsonSerializer.Deserialize <SystemData>(property.Value.ToString()); continue; } if (property.NameEquals("properties")) { if (property.Value.ValueKind == JsonValueKind.Null) { property.ThrowNonNullablePropertyIsNull(); continue; } foreach (var property0 in property.Value.EnumerateObject()) { if (property0.NameEquals("latest_run")) { if (property0.Value.ValueKind == JsonValueKind.Null) { property0.ThrowNonNullablePropertyIsNull(); continue; } latestRun = TriggeredJobRun.DeserializeTriggeredJobRun(property0.Value); continue; } if (property0.NameEquals("history_url")) { if (property0.Value.ValueKind == JsonValueKind.Null) { historyUrl = null; continue; } historyUrl = new Uri(property0.Value.GetString()); continue; } if (property0.NameEquals("scheduler_logs_url")) { if (property0.Value.ValueKind == JsonValueKind.Null) { schedulerLogsUrl = null; continue; } schedulerLogsUrl = new Uri(property0.Value.GetString()); continue; } if (property0.NameEquals("run_command")) { runCommand = property0.Value.GetString(); continue; } if (property0.NameEquals("url")) { if (property0.Value.ValueKind == JsonValueKind.Null) { url = null; continue; } url = new Uri(property0.Value.GetString()); continue; } if (property0.NameEquals("extra_info_url")) { if (property0.Value.ValueKind == JsonValueKind.Null) { extraInfoUrl = null; continue; } extraInfoUrl = new Uri(property0.Value.GetString()); continue; } if (property0.NameEquals("web_job_type")) { if (property0.Value.ValueKind == JsonValueKind.Null) { property0.ThrowNonNullablePropertyIsNull(); continue; } webJobType = property0.Value.GetString().ToWebJobType(); continue; } if (property0.NameEquals("error")) { error = property0.Value.GetString(); continue; } if (property0.NameEquals("using_sdk")) { if (property0.Value.ValueKind == JsonValueKind.Null) { property0.ThrowNonNullablePropertyIsNull(); continue; } usingSdk = property0.Value.GetBoolean(); continue; } if (property0.NameEquals("settings")) { if (property0.Value.ValueKind == JsonValueKind.Null) { property0.ThrowNonNullablePropertyIsNull(); continue; } Dictionary <string, BinaryData> dictionary = new Dictionary <string, BinaryData>(); foreach (var property1 in property0.Value.EnumerateObject()) { dictionary.Add(property1.Name, BinaryData.FromString(property1.Value.GetRawText())); } settings = dictionary; continue; } } continue; } } return(new TriggeredWebJobData(id, name, type, systemData, kind.Value, latestRun.Value, historyUrl.Value, schedulerLogsUrl.Value, runCommand.Value, url.Value, extraInfoUrl.Value, Optional.ToNullable(webJobType), error.Value, Optional.ToNullable(usingSdk), Optional.ToDictionary(settings))); }