/// <summary>
        /// Overridden to send job to job processor
        /// </summary>
        /// <param name="resourceDescriptor"></param>
        /// <param name="resource"></param>
        /// <returns></returns>
        public override async Task<Job> Create(ResourceDescriptor resourceDescriptor, Job resource)
        {
            resource.JobStatus = "New";

            // create the job
            var job = await base.Create(resourceDescriptor, resource);

            // get all services
            var services = await DataHandler.Query<Service>(ResourceDescriptor.FromUrl<Service>(Environment.ServiceRegistryServicesUrl()));

            // find first service that has a job processing endpoint
            var serviceResource =
                services
                    .SelectMany(s => s.HasResource.Select(r => new {Service = s, Resource = r}))
                    .FirstOrDefault(
                        sr => sr.Resource.ResourceType == nameof(JobProcess) && !string.IsNullOrWhiteSpace(sr.Resource.HttpEndpoint));

            if (serviceResource == null)
            {
                job.JobStatusReason = "No JobProcessor endpoints registered in the service registry.";
                job.JobStatus = "Failed";

                return await Update(resourceDescriptor, job);
            }

            try
            {
                // gets the authorized url
                var url = AuthorizedUrlBuilder.GetAuthorizedUrl(serviceResource.Resource);
                
                // send the job to the job processing endpoint
                await DataHandler.Create(ResourceDescriptor.FromUrl<JobProcess>(url), new JobProcess {Job = job});

                return await Get(resourceDescriptor);
            }
            catch (Exception ex)
            {
                job.JobStatusReason = $"Failed to send job to JobProcessor endpoint {serviceResource.Resource.HttpEndpoint}: {ex}";
                job.JobStatus = "Failed";

                return await Update(resourceDescriptor, job);
            }
        }
        /// <summary>
        /// Handles creation of a job
        /// </summary>
        /// <param name="resourceDescriptor"></param>
        /// <param name="jobProcess"></param>
        /// <returns></returns>
        public override async Task <JobProcess> Create(ResourceDescriptor resourceDescriptor, JobProcess jobProcess)
        {
            // ensure status is set to New
            jobProcess.JobProcessStatus = "New";

            // call base first
            jobProcess = await base.Create(resourceDescriptor, jobProcess);

            // retrieve the job data
            var job = await DataHandler.Get <Job>(jobProcess.Job.Id);

            if (job != null)
            {
                // validate the job before processing
                job.Validate();

                // set the job process ID
                job.JobProcess = jobProcess.Id;

                // get all services
                var services = await DataHandler.Query <Service>(ResourceDescriptor.FromUrl <Service>(Environment.ServiceRegistryServicesUrl()));

                // find first service that can accept the job type and that has a job assignment endpoint
                var serviceResource =
                    services
                    .Where(s => s.CanAcceptJob(job))
                    .SelectMany(s => s.HasResource.Select(r => new { Service = s, Resource = r }))
                    .FirstOrDefault(
                        sr => sr.Resource.ResourceType == nameof(JobAssignment) && !string.IsNullOrWhiteSpace(sr.Resource.HttpEndpoint));

                // check that we found an acceptable endpoint
                if (serviceResource != null)
                {
                    try
                    {
                        // gets the authorized url
                        var authorizedUrl = AuthorizedUrlBuilder.GetAuthorizedUrl(serviceResource.Resource);

                        // send the job to the job assignment endpoint
                        var jobAssignment =
                            await DataHandler.Create(ResourceDescriptor.FromUrl <JobAssignment>(authorizedUrl),
                                                     new JobAssignment { JobProcess = jobProcess.Id });

                        // set assignment back on the job process
                        jobProcess.JobAssignment = jobAssignment.Id;

                        // set status to Running
                        jobProcess.JobProcessStatus = job.JobStatus = "Running";
                        jobProcess.JobStart         = DateTime.UtcNow;
                    }
                    catch (Exception ex)
                    {
                        Logger.Error("Service '{0}' at {1} failed to accept JobAssignment. Exception: {2}",
                                     serviceResource.Service.Label,
                                     serviceResource.Resource.HttpEndpoint,
                                     ex);

                        job.JobStatus       = jobProcess.JobProcessStatus = "Failed";
                        job.JobStatusReason = jobProcess.JobProcessStatusReason =
                            $"Service '{serviceResource.Service.Label}' at {serviceResource.Resource.HttpEndpoint} failed to accept JobAssignment. Exception: {ex}";
                    }
                }
                else
                {
                    Logger.Warning("No accepting service available for job type {0}.", job.Type);

                    job.JobStatus       = jobProcess.JobProcessStatus = "Failed";
                    job.JobStatusReason = jobProcess.JobProcessStatusReason = $"No accepting service available for job type {job.Type}.";
                }

                // update the job
                try
                {
                    await DataHandler.Update(job);
                }
                catch (Exception ex)
                {
                    Logger.Error("Unable to update job {0}. Exception: {1}", job.Id, ex);

                    jobProcess.JobProcessStatus       = "Failed";
                    jobProcess.JobProcessStatusReason = $"Unable to update job {job.Id}. Exception: {ex}";
                }

                // hit the async callback endpoint
                if (jobProcess.JobProcessStatus == "Failed" && job.AsyncEndpoint != null && !string.IsNullOrWhiteSpace(job.AsyncEndpoint.AsyncFailure))
                {
                    await DataHandler.Get <Resource>(job.AsyncEndpoint.AsyncFailure);
                }
            }
            else
            {
                jobProcess.JobProcessStatus       = "Failed";
                jobProcess.JobProcessStatusReason = $"Unable to retrieve job '{jobProcess.Job}'";
            }

            // update the JobProcess record and return it
            return(await Update(resourceDescriptor, jobProcess));
        }
Example #3
0
 /// <summary>
 /// Updates a resource
 /// </summary>
 /// <typeparam name="T"></typeparam>
 /// <param name="resourceDataHandler"></param>
 /// <param name="resource"></param>
 /// <returns></returns>
 public static Task <T> Update <T>(this IResourceDataHandler resourceDataHandler, T resource) where T : Resource, new()
 {
     return(resourceDataHandler.Update(ResourceDescriptor.FromUrl <T>(resource.Id), resource));
 }
Example #4
0
 /// <summary>
 /// Gets a resource by its url
 /// </summary>
 /// <typeparam name="T"></typeparam>
 /// <param name="resourceDataHandler"></param>
 /// <param name="url"></param>
 /// <returns></returns>
 public static Task <Resource> Get(this IResourceDataHandler resourceDataHandler, string url)
 {
     return(resourceDataHandler.Get(ResourceDescriptor.FromUrl <Resource>(url)));
 }
Example #5
0
 /// <summary>
 /// Gets a resource by its url
 /// </summary>
 /// <typeparam name="T"></typeparam>
 /// <param name="resourceDataHandler"></param>
 /// <param name="url"></param>
 /// <returns></returns>
 public static Task <T> Get <T>(this IResourceDataHandler resourceDataHandler, string url) where T : Resource, new()
 {
     return(resourceDataHandler.Get <T>(ResourceDescriptor.FromUrl <T>(url)));
 }