Identical groups in Table ADSGroup

Hi everyone,

In version 8.1.3 we have an Eset in ITShop that grants group membership to different AD groups depending on the recipient's internal customer code. To avoid creating all groups objects in advance (they could be a long list), our script checks if the group exists and creates it before assigning the membership. If the product is assigned to one user then everything works fine. However if the product is requested for , let's say, two users at the same time , same customer code, and the group did not exist, the script runs for everyone of them and creates two identical groups in the table ADSGroup. They both have the same name, cn , attributes, even the ObjectGUID except the UID_ADSGroup. Each user if assigned to each group. The projection to AD works fine nonetheless, and in the target system we find only one group with two members (correct). 

How could we avoid this? We have no way (as far as we know) of locking the record so the other simultanous process wont create a duplicate.Which would be your advice?

Thanks in advance,

Laura

Regards!

  • Hi,

    You need to ensure that the step that runs the script always runs on the same job queue.  Then change the step to run the script using scriptexecsingle ...... that way only one instance of the script will run at any one time ..... the other instances will 'wait'.  Assuming the script firstly does a check to see if the group exists ... and continues down another path if it does .... then you should be good to go.

    HTH, Barry.

  • If you are running the script on more than one queue (due to load-balancing), another option would be to use the new task ScriptExecExclusive from 8.1.2+. It executes a script per object exclusive based on the entries in QBMElementAffectedByJob. But if this option is feasible depends on where the process of the script is attached to. Therefore I would stick with the solution from Barry. And if you are using load-balanced queues (using server tags) you could just pin the execution of this script to one queue explicitly by not using the server tags to specify the execution queue but by providing the UID of the QBMServer.

  • I have tried Barry's solution and it has worked. Thanks a lot!
  • Hi Barry

    I think its important to mention that scriptexecsingle will only execute once per queue no matter which script is being executed (its only one instance of the process task itself regardless of the parameters). 

    From my experience if you have lot of different processes lwith  scriptexecsingle, this can really slow down execution, because of independend processes that use the task.

    The other issue is that the objectlayer uniqueness validation doesn't catch race conditions (because it's not on an atomic level like sql) which can cause inconsistencies as described above.

    In my past i successfuly used. a Mutex, locking a critical path within the script code based on a resource.

    In earlies versions (last tested in v6 or7). I also were able to set some were in a jobrunparameter or so MyJob.Maxinstances = 1. The Myjob is a hidden property that is generated when the process is compiled. This sets the maxinstance property in the table jobqueue und overwrites the settings defined on the jobtask/component.

  • Hello Salvatore,

    Thank you for sharing this info.
    Could you provide a code example of this (Mutex, locking a critical path within the script...)

    Kind regards,
    Niels

  • Here's an example.A Mutex is basically a systemwide named lock. Make sure to pin the execution to the same queue or a set of queues belonging to the same machine.
            

    Dim namedlock As String = 'e.g. Build AccProductgroup fullpath
    
    namedlock = namedlock.replace("\","_") 'backslash is reserved for kernelnamespaces
    Using mut As Mutex = new Mutex(False, namedlock)
    	If Not mut.WaitOne(5000, false) Then _
    		Throw New ViException("Lock could not be aquired in time")
    	Try
    		If Session.Source.Exists(... Then 'check accproductgroup exist
    			
    			'get accproducgroup
    		Else
    			'create accproductgroup		
    		End If
    	Finally
    		 mut.ReleaseMutex()
    	End Try
    
    End Using