/// <summary> /// Get job of type that fufills predicate /// </summary> /// <typeparam name="T"></typeparam> /// <param name="predicate"></param> /// <returns></returns> public T GetJob <T>(Func <T, bool> predicate) where T : IJob { lock (Jobs) { InternalJob internalJob = Jobs.FirstOrDefault(x => x.Job is T t && predicate(t)); return(internalJob == null ? default : (T)internalJob.Job); } }
/// <summary> /// Execute a job, exceptions will propegate. /// </summary> /// <param name="job"></param> /// <returns></returns> Task ExecuteJob(InternalJob job, bool soft) { if (!soft) { lock (Jobs) { if (!job.Repeat) { Jobs.Remove(job); } else { job.Restart(); } } } MethodContext context = JobContext[job.Job.GetType()]; return(JobMethods[job.Job.GetType()].Invoke(job.Job, context)); }
/// <summary> /// Wait for job to complete or a semaphore interupt. /// </summary> /// <param name="job"></param> /// <returns></returns> async Task <bool> WaitForJobOrInterupt(InternalJob job) { Task jobWaitTask = Task.Delay(0); Task waitTask = tcs.Task; if (job.GetEnd() > DateTime.UtcNow) { jobWaitTask = Task.Delay(job.GetEnd() - DateTime.UtcNow); } Task doneTask = await Task.WhenAny(waitTask, jobWaitTask); if (doneTask == waitTask) { lock (tcs) { tcs = new TaskCompletionSource <bool>(); } } return(doneTask == jobWaitTask); }
/// <summary> /// Try to execute a job, all errors will be silent. /// </summary> /// <param name="job"></param> /// <returns></returns> async Task TryExecuteJob(InternalJob job) { lock (Jobs) { if (!job.Repeat) { Jobs.Remove(job); } else { job.Restart(); } } try { MethodContext context = JobContext[job.Job.GetType()]; await JobMethods[job.Job.GetType()].Invoke(job.Job, context); } catch (Exception) { } }
/// <summary> /// Process all added jobs, including incomming while waiting /// </summary> /// <returns></returns> async Task ProcessQueue() { while (true) { if (Jobs.Count == 0) { break; } lock (Jobs) { currentWait = Jobs.Min; } bool jobCompleted = await WaitForJobOrInterupt(currentWait); if (jobCompleted) { await TryExecuteJob(currentWait); } } loopRunning = false; }
/// <summary> /// Manually trigger a job to execute /// </summary> /// <param name="job"></param> /// <returns></returns> public Task TriggerJob(IJob job, bool soft) { InternalJob internalJob = Jobs.Single(x => x.Job == job); return(ExecuteJob(internalJob, soft)); }