Discussion
· Mar 5

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:

  1. Start jobs.
  2. Wait for all jobs to report success using $System.Event.WaitMsg().
  3. Send Commit or Rollback using the $System.Event.Signal().
 
Here's the code

Is there a better approach? How do you resolve similar issues?

Discussion (9)3
Log in or sign up to continue

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.

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:

  • work manager master process is just distributing work items among workers and waiting for complete
  • each work item is just preparing data in some ^IRISTEMP* global w/o writing to database and reports the status to the master process
  • master process checks completion status to make a choice:
    • to TS, store ^IRISTEMP* inside application database, TC, kill ^IRISTEMP*
    • or just to kill ^IRISTEMP*.

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.

what is the reason of having nested transactions inside the Worker method?

The idea is to check that TCOMMIT works, for additional safety, but yes, inner pair of TSTART/TCOMMIT can be taken out.

And how can you distribute single ("root") transaction execution and control among several processes?

No problems with that, transaction iterates over history data, so it's possible to chunk it.

another approach

Thank you. Locking situation would be better with this approach.