I’ve got a UI which can queue up jobs of radically different types. At present, it does this by storing the job in the appropriate table in a database (Table-per-JobType)
My back-end process then comes along, picks up the job(s), and assuming there’s an available worker (thread), uses it to execute the appropriate method for the job.
in PseudoCode:
While(Runnning) {
While(Queue1.HasJobs && Workers.IdleCount > 0) {
FirstIdleWorker.Execute(Queue1Method(Type1Job));
}
...
While(QueueN.HasJobs && Workers.IdleCount > 0) {
FirstIdleWorker.Execute(QueueNMethod(TypeNJob));
}
//Wait for a job to complete or a polling timeout if queues are empty
}
(It’s not actually that naive but it illustrates the order in which work is processed)
As you can see, this works but it doesn’t take into account what order jobs were added in. This isn’t a deal breaker as jobs are atomic but it is annoying from a UI perspective – eg User 1 Queues up 20 jobs of Type 2, then User 2 Queues up 1,000 jobs of Type 1. User 1 now has to wait for all User 2’s jobs to complete before their (relatively) quick jobs are processed.
Jobs do have a CreatedOn property so determining the order isn’t difficult but how best to implement a combined queue in a strongly-typed way that isn’t spaghetti code?
I’m trying to avoid a “GenericJob” object with a .CreatedOn, .Queue1Id, .Queue2Id, .Queue3Id as this just feels sloppy.
While FIFO is broadly what I’m after, it’s not a strict requirement – I just don’t want items to be bumped forever.
Is there a pattern for this sort of thing? If not, can someone point me at a good tutorial please?
(Incidentally, these are potentially long-running jobs. I’m actually using the TPL behind the scenes to manage workers once the jobs are taken from the Queue but I do still need to manage the queue myself as there are far more jobs than I could load into memory in one go)
Poke me if I’m wrong, I hope this pseudo-code explains the Interface Abstraction okay.
An interface might look like:
Each job type processor implements this interface, change and add properties to suit your needs:
You could then mix the job types into one list:
and possibly sort them by date using lambda:
get a list of unprocessed jobs (does not check for those busy processing*)