Exemplo n.º 1
0
        /// <inheritdoc/>
        public async Task OnJobCreatingAsync(IJobService manager, JobInfoModel job)
        {
            var jobDeviceId = GetJobDeviceId(job);

            try {
                var deviceTwin = await _ioTHubTwinServices.GetAsync(jobDeviceId);

                if (deviceTwin == null)
                {
                    deviceTwin = new DeviceTwinModel {
                        Id = jobDeviceId
                    };
                    await _ioTHubTwinServices.CreateAsync(deviceTwin);
                }
                var cs = await _ioTHubTwinServices.GetConnectionStringAsync(deviceTwin.Id);

                if (job.JobConfiguration?.Type == JTokenType.Object &&
                    job.JobConfiguration is JObject o)
                {
                    var connectionString = JToken.FromObject(cs.ToString());
                    if (o.ContainsKey(TwinProperties.ConnectionString))
                    {
                        o[TwinProperties.ConnectionString] = connectionString;
                    }
                    else
                    {
                        o.Add(TwinProperties.ConnectionString, connectionString);
                    }
                    _logger.Debug("Added connection string to job {id}", jobDeviceId);
                }
            }
            catch (Exception ex) {
                _logger.Error(ex, "Error while creating IoT Device.");
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Deserialize the monitored item job
        /// </summary>
        /// <param name="job"></param>
        /// <returns></returns>
        private WriterGroupJobModel AsJob(JobInfoModel job)
        {
            if (job.JobConfiguration != null)
            {
                var publishJob = (WriterGroupJobModel)_serializer.DeserializeJobConfiguration(
                    job.JobConfiguration, job.JobConfigurationType);
                if (publishJob != null)
                {
                    return(publishJob);
                }
            }

            return(new WriterGroupJobModel {
                MessagingMode = MessagingMode.Samples,
                WriterGroup = new WriterGroupModel {
                    WriterGroupId = job.Id,
                    MessageSettings = new WriterGroupMessageSettingsModel()
                    {
                        NetworkMessageContentMask = NetworkMessageContentMask.PublisherId |
                                                    NetworkMessageContentMask.WriterGroupId |
                                                    NetworkMessageContentMask.SequenceNumber |
                                                    NetworkMessageContentMask.PayloadHeader |
                                                    NetworkMessageContentMask.NetworkMessageHeader |
                                                    NetworkMessageContentMask.Timestamp |
                                                    NetworkMessageContentMask.DataSetMessageHeader
                    },
                    // ...
                    DataSetWriters = new List <DataSetWriterModel>()
                },
                Engine = null,
                ConnectionString = null
            });
        }
        public ActionResult Create(TenantScheduledJobViewModel vm)
        {
            if (ModelState.IsValid)
            {
                var jobInfo = new JobInfoModel
                {
                    JobType        = "Scheduled",
                    CronExpression = vm.CronExpression,
                    Url            = vm.Url
                };

                var newScheduledJob = new TenantScheduledJob
                {
                    TenantId = vm.TenantId,
                    Name     = vm.Name,
                    JobInfo  = JsonConvert.SerializeObject(jobInfo)
                };

                db.TenantScheduledJobs.Add(newScheduledJob);
                db.SaveChanges();


                // Create Hangfire Job
                var selectedTenant = db.Tenants.FirstOrDefault(t => t.Id == vm.TenantId);
                if (selectedTenant != null)
                {
                    RecurringJob.AddOrUpdate(vm.Name, () => WebClientHelper.InvokeUrl(vm.Url), vm.CronExpression);
                }

                return(RedirectToAction("Details", "Tenants", new { id = vm.TenantId }));
            }

            return(View(vm));
        }
Exemplo n.º 4
0
        public ActionResult Create(ScheduledJobViewModel vm)
        {
            if (ModelState.IsValid)
            {
                var jobInfo = new JobInfoModel
                {
                    JobType        = "Scheduled",
                    CronExpression = vm.CronExpression,
                    Url            = vm.Url
                };

                var newScheduledJob = new ScheduledJob
                {
                    Name    = vm.Name,
                    JobInfo = JsonConvert.SerializeObject(jobInfo)
                };

                _db.ScheduledJobs.Add(newScheduledJob);
                _db.SaveChanges();

                try
                {
                    // Create Hangfire Job
                    RecurringJob.AddOrUpdate(vm.Name, () => WebClientHelper.InvokeUrl(vm.Url), vm.CronExpression);
                    return(RedirectToAction("Index"));
                }
                catch (Exception ex) {
                    ViewBag.jobException = "Invalid cron expression";
                }
            }

            return(View(vm));
        }
Exemplo n.º 5
0
        /// <inheritdoc/>
        public async Task OnJobCreatingAsync(IJobService manager, JobInfoModel job)
        {
            if (job.JobConfiguration?.IsObject != true)
            {
                return;
            }
            try {
                var jobDeviceId = GetJobDeviceId(job);
                var deviceTwin  = await _ioTHubTwinServices.FindAsync(jobDeviceId);

                if (deviceTwin == null)
                {
                    deviceTwin = new DeviceTwinModel {
                        Id = jobDeviceId
                    };
                    await _ioTHubTwinServices.CreateOrUpdateAsync(deviceTwin, true);
                }
                var cs = await _ioTHubTwinServices.GetConnectionStringAsync(deviceTwin.Id);

                job.JobConfiguration[TwinProperties.ConnectionString].AssignValue(cs.ToString());
                _logger.Debug("Added connection string to job {id}", jobDeviceId);
            }
            catch (Exception ex) {
                _logger.Error(ex, "Error while creating IoT Device.");
            }
        }
Exemplo n.º 6
0
        /// <inheritdoc/>
        public async Task <JobInfoModel> AddAsync(JobInfoModel job, CancellationToken ct)
        {
            if (job == null)
            {
                throw new ArgumentNullException(nameof(job));
            }
            while (true)
            {
                var document = await _documents.FindAsync <JobDocument>(job.Id, ct);

                if (document != null)
                {
                    throw new ConflictingResourceException($"Job {job.Id} already exists.");
                }
                job.LifetimeData.Created = job.LifetimeData.Updated = DateTime.UtcNow;
                try {
                    var result = await _documents.AddAsync(job.ToDocumentModel(), ct);

                    return(result.Value.ToFrameworkModel());
                }
                catch (ConflictingResourceException) {
                    // Try again
                    continue;
                }
                catch {
                    throw;
                }
            }
        }
Exemplo n.º 7
0
 /// <summary>
 /// Convert to storage
 /// </summary>
 /// <param name="job"></param>
 /// <param name="etag"></param>
 /// <returns></returns>
 public static JobDocument ToDocumentModel(this JobInfoModel job,
                                           string etag = null)
 {
     if (job?.LifetimeData == null)
     {
         return(null);
     }
     return(new JobDocument {
         ETag = etag,
         Id = job.Id,
         JobId = job.Id,
         Name = job.Name,
         JobConfiguration = new JobConfigDocument {
             JobId = job.Id,
             Job = job.JobConfiguration.Copy()
         },
         Type = job.JobConfigurationType,
         Demands = job.Demands?.Select(d => d.ToDocumentModel(job.Id)).ToList(),
         DesiredActiveAgents = job.RedundancyConfig?.DesiredActiveAgents ?? 1,
         DesiredPassiveAgents = job.RedundancyConfig?.DesiredPassiveAgents ?? 0,
         Created = job.LifetimeData.Created,
         ProcessingStatus = job.LifetimeData.ProcessingStatus?
                            .ToDictionary(k => k.Key, v => v.Value.ToDocumentModel(job.Id)),
         Status = job.LifetimeData.Status,
         Updated = job.LifetimeData.Updated
     });
 }
Exemplo n.º 8
0
        /// <summary>
        /// Deserialize the monitored item job
        /// </summary>
        /// <param name="job"></param>
        /// <returns></returns>
        private WriterGroupJobModel AsJob(JobInfoModel job)
        {
            if (job.JobConfiguration != null)
            {
                var publishJob = (WriterGroupJobModel)_serializer.DeserializeJobConfiguration(
                    job.JobConfiguration, job.JobConfigurationType);
                if (publishJob != null)
                {
                    if (publishJob.Engine == null)
                    {
                        publishJob.Engine = new EngineConfigurationModel {
                            BatchSize             = _config.DefaultBatchSize,
                            BatchTriggerInterval  = _config.DefaultBatchTriggerInterval,
                            DiagnosticsInterval   = TimeSpan.FromSeconds(60),
                            MaxMessageSize        = 0,
                            MaxEgressMessageQueue = _config.DefaultMaxEgressMessageQueue
                        };
                    }
                    else
                    {
                        publishJob.Engine.BatchTriggerInterval  = _config.DefaultBatchTriggerInterval;
                        publishJob.Engine.BatchSize             = _config.DefaultBatchSize;
                        publishJob.Engine.MaxEgressMessageQueue = _config.DefaultMaxEgressMessageQueue;
                    }
                    return(publishJob);
                }
            }

            return(new WriterGroupJobModel {
                MessagingMode = _config.DefaultMessagingMode,
                WriterGroup = new WriterGroupModel {
                    MessageType = _config.DefaultMessageEncoding,
                    WriterGroupId = job.Id,
                    DataSetWriters = new List <DataSetWriterModel>(),
                    MessageSettings = new WriterGroupMessageSettingsModel()
                    {
                        NetworkMessageContentMask =
                            NetworkMessageContentMask.PublisherId |
                            NetworkMessageContentMask.WriterGroupId |
                            NetworkMessageContentMask.NetworkMessageNumber |
                            NetworkMessageContentMask.SequenceNumber |
                            NetworkMessageContentMask.PayloadHeader |
                            NetworkMessageContentMask.Timestamp |
                            NetworkMessageContentMask.DataSetClassId |
                            NetworkMessageContentMask.NetworkMessageHeader |
                            NetworkMessageContentMask.DataSetMessageHeader
                    },
                },
                Engine = new EngineConfigurationModel {
                    BatchSize = _config.DefaultBatchSize,
                    BatchTriggerInterval = _config.DefaultBatchTriggerInterval,
                    DiagnosticsInterval = TimeSpan.FromSeconds(60),
                    MaxMessageSize = 0,
                    MaxEgressMessageQueue = _config.DefaultMaxEgressMessageQueue
                },
                ConnectionString = null
            });
        }
Exemplo n.º 9
0
        /// <inheritdoc/>
        public async Task OnJobDeletedAsync(IJobService manager, JobInfoModel job)
        {
            var jobDeviceId = GetJobDeviceId(job);

            try {
                await _ioTHubTwinServices.DeleteAsync(jobDeviceId);
            }
            catch (Exception ex) {
                _logger.Error(ex, "Failed to delete device job {id}", jobDeviceId);
            }
        }
Exemplo n.º 10
0
        /// <inheritdoc/>
        public async Task <JobInfoModel> NewOrUpdateJobAsync(string jobId,
                                                             Func <JobInfoModel, Task <bool> > predicate, CancellationToken ct)
        {
            var created = false;
            var job     = await _jobRepository.AddOrUpdateAsync(jobId, async model => {
                if (model == null)
                {
                    created = true;

                    // Create new job
                    model = new JobInfoModel {
                        Id = jobId
                    };
                    SetDefaultValues(model);
                    if (!await predicate(model))
                    {
                        return(null);
                    }

                    foreach (var jreh in _jobRepositoryEventHandlers)
                    {
                        await jreh.OnJobCreatingAsync(this, model);
                    }
                    return(model);
                }

                created     = false;
                var updated = model.Clone();
                if (!await predicate(updated))
                {
                    return(null);
                }
                if (!model.RedundancyConfig.Equals(updated.RedundancyConfig))
                {
                    updated.RedundancyConfig = updated.RedundancyConfig;
                    updated.LifetimeData.ProcessingStatus.Clear();
                }
                return(updated);
            });

            if (created)
            {
                foreach (var jreh in _jobRepositoryEventHandlers)
                {
                    await jreh.OnJobCreatedAsync(this, job);
                }
            }
            return(job);
        }
Exemplo n.º 11
0
        /// <inheritdoc/>
        public async Task OnJobAssignmentAsync(IJobService manager, JobInfoModel job, string workerId)
        {
            if (job.JobConfiguration?.IsObject != true)
            {
                return;
            }
            if (string.IsNullOrEmpty(workerId))
            {
                throw new ArgumentNullException("empty WorkerId provided");
            }
            try {
                var edgeDeviceTwin = await _ioTHubTwinServices.FindAsync(workerId.Split("_publisher")[0]);

                if (edgeDeviceTwin == null)
                {
                    _logger.Error("IoT Edge Device not found.");
                    return;
                }

                var jobDeviceId = GetJobDeviceId(job);
                var deviceTwin  = await _ioTHubTwinServices.FindAsync(jobDeviceId);

                if (deviceTwin == null)
                {
                    deviceTwin = new DeviceTwinModel {
                        Id          = jobDeviceId,
                        DeviceScope = edgeDeviceTwin.DeviceScope
                    };
                    await _ioTHubTwinServices.CreateOrUpdateAsync(deviceTwin, true);
                }
                else
                {
                    if (deviceTwin.DeviceScope != edgeDeviceTwin.DeviceScope)
                    {
                        deviceTwin.DeviceScope = edgeDeviceTwin.DeviceScope;
                        await _ioTHubTwinServices.CreateOrUpdateAsync(deviceTwin, true);
                    }
                }
                var cs = await _ioTHubTwinServices.GetConnectionStringAsync(deviceTwin.Id);

                job.JobConfiguration[TwinProperties.ConnectionString].AssignValue(cs.ToString());
                _logger.Debug("Added connection string to job {id}", jobDeviceId);
            }
            catch (Exception ex) {
                _logger.Error(ex, "Error while assigning the Job's IoT Device.");
            }
        }
Exemplo n.º 12
0
 /// <summary>
 /// Create model
 /// </summary>
 /// <param name="model"></param>
 /// <returns></returns>
 public static JobInfoApiModel ToApiModel(
     this JobInfoModel model)
 {
     if (model == null)
     {
         return(null);
     }
     return(new JobInfoApiModel {
         LifetimeData = model.LifetimeData.ToApiModel(),
         RedundancyConfig = model.RedundancyConfig.ToApiModel(),
         Demands = model.Demands?
                   .Select(d => d.ToApiModel()).ToList(),
         JobConfiguration = model.JobConfiguration?.DeepClone(),
         JobConfigurationType = model.JobConfigurationType,
         Name = model.Name,
         Id = model.Id
     });
 }
Exemplo n.º 13
0
        /// <inheritdoc/>
        public async Task <JobInfoModel> AddAsync(JobInfoModel job, CancellationToken ct)
        {
            await _lock.WaitAsync();

            try {
                if (_jobs.Any(j => j.Id == job.Id))
                {
                    throw new ConflictingResourceException($"{job.Id} already exists.");
                }
                job.LifetimeData.Created = job.LifetimeData.Updated = DateTime.UtcNow;
                _jobs.Add(job);
                await BufferedUpdate();

                return(job);
            }
            finally {
                _lock.Release();
            }
        }
 /// <summary>
 /// Set default values
 /// </summary>
 /// <param name="model"></param>
 private static void SetDefaultValues(JobInfoModel model)
 {
     if (model.Id == null)
     {
         model.Id = Guid.NewGuid().ToString();
     }
     model.LifetimeData = new JobLifetimeDataModel {
         Created          = DateTime.UtcNow,
         Status           = JobStatus.Active,
         Updated          = DateTime.UtcNow,
         ProcessingStatus = new Dictionary <string, ProcessingStatusModel>()
     };
     if (model.RedundancyConfig == null)
     {
         model.RedundancyConfig = new RedundancyConfigModel {
             DesiredActiveAgents  = 1,
             DesiredPassiveAgents = 0
         };
     }
 }
Exemplo n.º 15
0
        /// <inheritdoc/>
        public async Task OnJobCreatingAsync(IJobService manager, JobInfoModel job)
        {
            if (job.JobConfiguration?.IsObject != true)
            {
                return;
            }
            try {
                var jobDeviceId = GetJobDeviceId(job);
                var deviceTwin  = await _ioTHubTwinServices.FindAsync(jobDeviceId);

                if (deviceTwin == null)
                {
                    deviceTwin = new DeviceTwinModel {
                        Id = jobDeviceId
                    };
                    await _ioTHubTwinServices.CreateOrUpdateAsync(deviceTwin, true);
                }
            }
            catch (Exception ex) {
                _logger.Error(ex, "Error while creating IoT Device.");
            }
        }
        /// <summary>
        /// Calculate new processing instructions if possible
        /// </summary>
        /// <param name="job"></param>
        /// <param name="workerId"></param>
        /// <returns></returns>
        private JobProcessingInstructionModel CalculateInstructions(JobInfoModel job,
                                                                    string workerId)
        {
            var numberOfActiveAgents = job.LifetimeData.ProcessingStatus
                                       .Count(j => j.Value.ProcessMode == ProcessMode.Active &&
                                              j.Value.LastKnownHeartbeat > DateTime.UtcNow.Subtract(_jobOrchestratorConfig.JobStaleTime) &&
                                              j.Key != workerId);
            var numberOfPassiveAgents =
                job.LifetimeData.ProcessingStatus
                .Count(j => j.Value.ProcessMode == ProcessMode.Passive &&
                       j.Value.LastKnownHeartbeat > DateTime.UtcNow.Subtract(_jobOrchestratorConfig.JobStaleTime) &&
                       j.Key != workerId);

            if (numberOfActiveAgents < job.RedundancyConfig.DesiredActiveAgents)
            {
                job.LifetimeData.ProcessingStatus[workerId] = new ProcessingStatusModel {
                    ProcessMode        = ProcessMode.Active,
                    LastKnownHeartbeat = DateTime.UtcNow
                };
                return(new JobProcessingInstructionModel {
                    Job = job,
                    ProcessMode = ProcessMode.Active
                });
            }

            if (numberOfPassiveAgents < job.RedundancyConfig.DesiredPassiveAgents)
            {
                job.LifetimeData.ProcessingStatus[workerId] = new ProcessingStatusModel {
                    ProcessMode        = ProcessMode.Passive,
                    LastKnownHeartbeat = DateTime.UtcNow
                };
                return(new JobProcessingInstructionModel {
                    Job = job,
                    ProcessMode = ProcessMode.Passive
                });
            }
            return(null);
        }
 /// <inheritdoc/>
 public async Task <JobInfoModel> NewJobAsync(JobInfoModel model, CancellationToken ct)
 {
     SetDefaultValues(model);
     foreach (var jreh in _jobRepositoryEventHandlers)
     {
         await jreh.OnJobCreatingAsync(this, model);
     }
     try {
         model = await _jobRepository.AddAsync(model, ct);
     }
     catch {
         foreach (var jreh in _jobRepositoryEventHandlers)
         {
             await jreh.OnJobDeletedAsync(this, model);
         }
         throw;
     }
     foreach (var jreh in _jobRepositoryEventHandlers)
     {
         await jreh.OnJobCreatedAsync(this, model);
     }
     return(model);
 }
Exemplo n.º 18
0
        /// <summary>
        /// Deserialize the monitored item job
        /// </summary>
        /// <param name="job"></param>
        /// <returns></returns>
        private WriterGroupJobModel AsJob(JobInfoModel job)
        {
            if (job.JobConfiguration != null)
            {
                var publishJob = (WriterGroupJobModel)_serializer.DeserializeJobConfiguration(
                    job.JobConfiguration, job.JobConfigurationType);
                if (publishJob != null)
                {
                    return(publishJob);
                }
            }

            return(new WriterGroupJobModel {
                MessagingMode = MessagingMode.Samples,
                WriterGroup = new WriterGroupModel {
                    WriterGroupId = job.Id,
                    // ...
                    DataSetWriters = new List <DataSetWriterModel>()
                },
                Engine = null,
                ConnectionString = null
            });
        }
Exemplo n.º 19
0
 /// <summary>
 /// Create job device identifier
 /// </summary>
 /// <param name="job"></param>
 /// <returns></returns>
 private static string GetJobDeviceId(JobInfoModel job)
 {
     return($"{job.JobConfigurationType}_{job.Id}");
 }
Exemplo n.º 20
0
        //Load Job
        public JsonResult LoadJobInfoData()
        {
            try
            {
                int index = 1;
                List <JobDetailImpl>   jobList     = new List <JobDetailImpl>();
                List <CronTriggerImpl> triggerList = new List <CronTriggerImpl>();
                List <JobInfoModel>    jobInfoList = new List <JobInfoModel>();

                var jobKeySet   = scheduler.GetJobKeys(GroupMatcher <JobKey> .AnyGroup());
                var triggerKeys = scheduler.GetTriggerKeys(GroupMatcher <TriggerKey> .AnyGroup());

                foreach (var jobKey in jobKeySet)
                {
                    var jobDetail = (JobDetailImpl)scheduler.GetJobDetail(jobKey); jobList.Add(jobDetail);
                }
                foreach (var triggerkey in triggerKeys)
                {
                    var triggerDetail = (CronTriggerImpl)scheduler.GetTrigger(triggerkey); triggerList.Add(triggerDetail);
                }

                foreach (var job in jobList)
                {
                    JobInfoModel jobInfo = new JobInfoModel();
                    jobInfo.JobId        = index++;
                    jobInfo.JobName      = job.Name;
                    jobInfo.JobGroupName = job.Group;
                    //jobInfo.IsDurable = job.Durable;
                    //jobInfo.JobDescription = job.Description;

                    var trigger = string.Join(",", scheduler.GetTriggersOfJob(new JobKey(job.Name, job.Group)).Select(m => m.Key.ToString()));

                    var triggerInfo = triggerList.Where(i => i.FullName.Equals(trigger.ToString()) && i.FullJobName.Equals($"{job.Group}.{job.Name}")).Select(i => new JobInfoModel
                    {
                        TriggerName      = i.Name,
                        TriggerGroupName = i.Group,
                        //TriggerDescription = i.Description,
                        StartTime    = i.StartTimeUtc.LocalDateTime.ToString("yyyy-MM-dd HH:mm:ss"),
                        PrevFireTime = i.GetPreviousFireTimeUtc()?.LocalDateTime.ToString("yyyy-MM-dd HH:mm:ss"),
                        NextFireTime = i.GetNextFireTimeUtc()?.LocalDateTime.ToString("yyyy-MM-dd HH:mm:ss"),
                        Cron         = i.CronExpressionString,
                        //Priority = i.Priority,
                        Status = scheduler.GetTriggerState(new TriggerKey(i.Name, i.Group)).ToString(),
                        //JobClassName = scheduler.GetJobDetail(i.JobKey).JobType.FullName
                    }).FirstOrDefault();

                    jobInfo.TriggerName      = triggerInfo.TriggerName;
                    jobInfo.TriggerGroupName = triggerInfo.TriggerGroupName;
                    //jobInfo.TriggerDescription = triggerInfo.TriggerDescription;
                    jobInfo.StartTime    = triggerInfo.StartTime;
                    jobInfo.PrevFireTime = triggerInfo.PrevFireTime;
                    jobInfo.NextFireTime = triggerInfo.NextFireTime;
                    jobInfo.Cron         = triggerInfo.Cron;
                    //jobInfo.Priority = triggerInfo.Priority;
                    jobInfo.Status = GetState(triggerInfo.Status);
                    //jobInfo.JobClassName = triggerInfo.JobClassName;

                    jobInfoList.Add(jobInfo);
                }

                return(Json(jobInfoList, JsonRequestBehavior.AllowGet));
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
Exemplo n.º 21
0
 /// <inheritdoc/>
 public Task OnJobDeletingAsync(IJobService manager, JobInfoModel job)
 {
     return(Task.CompletedTask);
 }