Work Queue with bidirectional communication
Work Queue Manager (WQM) is a feature of InterSystems IRIS that enables you to improve performance by distributing work to multiple concurrent processes programmatically. The idea is that you split the work into chunks, and WQM distributes the chunks across worker processes and can provide the info that the work is done.
However, recently, I got an interesting question: there's a large logical transaction composed of ~1,000,000 individual objects and SQL inserts and updates. Some updates are CPU-intensive, so the original idea was to use WQM to split an update into chunks to speed things up.
But, here's a catch: if one of the individual 1,000,000 changes fails (there's a variety of application-level checks so that it can fail, and that's not even that abnormal a behavior), the entire transaction must be rolled back. That creates a problem: each chunk must report success before committing their individual transactions, and someone must get all these reports and decide if we are committing or not.
Unfortunately, it looks like WQM does not have a bidirectional communication between workers and manager, so I suggested an approach using events:
- Start jobs.
- Wait for all jobs to report success using $System.Event.WaitMsg().
- Send Commit or Rollback using the $System.Event.Signal().
Is there a better approach? How do you resolve similar issues?
Just wondering my initial thought was that just use the master process to initiate the transaction check the returned stati and rollback if it has failed.
This can be done with WQM easily enough.
Set queue=$system.WorkMgr.%New() If (queue="") { // Report Error, can check %objlasterror for %Status code } TSTART For i=1:1:100 { Set sc=queue.Queue("##class(MyClass).ClassMethod",i) If $$$ISERR(sc) { // report error } } Set sc=queue.Sync() If $$$ISERR(sc) { // A worker encounteres an issue TROLLBACK } and { // no errros reported by workers TCOMMIT }
That should work just fine, i haven't tested it though.
That won't rollback transactions inside worker processes (as they might be gone by the point we pass sync).
How can a process commit/rollback transactions of other process(es)??
Technically this is not possible (I think). It can just send a message to the other process that decides to validate or not.
I needed this once (in abnormal situation), see this post
There's an example of that in a sample code.
Sure, that's fine, each process commit/rollback it's own transactions.
My message was to @Timo Lindenschmid where he was trying to commit/rollback worker processes from the "main" process. That's not possible.
Yes, that's not possible.
Eduard,
what is the reason of having nested transactions inside the Worker method?
And how can you distribute single ("root") transaction execution and control among several processes?
I'd take another approach:
Pros: it can be implemented using WQM.
Cons: huge amount of temporary data can be written into IRISTEMP database, but if the results of work items can be processed separately, master process can do it without waiting for all items completeness killing temporary subglobals one by one.
The idea is to check that TCOMMIT works, for additional safety, but yes, inner pair of TSTART/TCOMMIT can be taken out.
No problems with that, transaction iterates over history data, so it's possible to chunk it.
Thank you. Locking situation would be better with this approach.