Need to prohibit multiuser to run the same codeunit

Purvesh_MaisuriaPurvesh_Maisuria Member Posts: 71
edited 2015-05-28 in NAV Three Tier
Hello Experts,

NAV Version : NAV 2013 R2 (7.10.37563)

Is there any way to prohibit multiuser to run the same codeunit ?

I need the functionality in which if any user running the one codeunit, nobody else is not able to run the same codeunit.

Until finish the user1, another user must wait for finishing it and after finished by user1 another user will continue to run the same codeunit.

Hope someone face this issue and help me out.

Thanks & Regards,
Purvesh Maisuria.

Comments

  • Rob_HansenRob_Hansen Member Posts: 296
    I assume this codeunit is performing data updates and that's the need to prevent multiple concurrent calls (to prevent data conflicts). If so, the simple approach is to add a LOCKTABLE at the start of the process on the table(s) you are updating. Any other users should then be blocked if they attempt to run the codeunit to update the same tables concurrently. When transaction 1 finishes, the table lock is released.
  • satbirsatbir Member Posts: 33
    You can have a Boolean field in some setup table. Set it up when codeunit starts and reset when codeunit ends.
    If the field is set then don't let the codeunit run again.
    you can also use singleinstance codeunit with a Boolean variable.
  • Purvesh_MaisuriaPurvesh_Maisuria Member Posts: 71
    Hi Rob Hansen,

    Yes, my codeunit is doing data update, but not through single codeunit. for data update it is running other codeunit also like,
    COD50001's OnRun
    Begin
    Locktable
    Loop 1 to 10
    Begin
    IF COD50000.RUN THEN
    DO this
    Else
    Do That;
    (Auto fire Commit Bz COD50000 finish its whole cycle - Release the Lock after loop execute first time, in other loop run any user can run this codeunit)
    End;
    End
    So when any codeunit finish its run cycle, it do COMMIT at the end, In this case my Lock is released.

    May be I am wrong, please correct me if is it so.

    Hi Satbir,

    1) Boolean field on setup table :
    I try this technique but my codeunit is processing so much things so it takes time to run code, so I put progress bar in case when I running it from GUI.
    Consider I put true on any setup table and start my codeunit run, if I press cancel in my progress bar window, so it is not go at last line and not set false in my setup table, so it is not allow any user to run this codeunit until I make false in my setup table manually.

    Same codeunit I run in Job Queue, if any one stop the service then also above issue occure.

    2) Singleinstance codeunit with a Boolean variable :
    This technique is not work, because singleinstance codeunit is work in same session only. If same user try to run the codeunit then it will work because it is in same session. In my case any user with different session will run this codeunit. So it is not work in this scenario.

    May be I am wrong, please correct me if is it so.

    I need to show the proper message to the user also that, "XYZ user is running this codeunit, try after XYZ user will finish it".

    Hope you understand my query.

    Thanks & Regards,
    Purvesh Maisuria.
  • satbirsatbir Member Posts: 33
    Try this
    create new Codeunit -
    if the flag is set then error.
    else
    set the flag. and commit.
    Call your processing codeunit using if codeunit.run then.
    After that reset the flag.
  • Rob_HansenRob_Hansen Member Posts: 296
    The things you need to deal with using satbir's approach:

    1. Make sure this is a segregated piece of logic. With satbir's approach you need to do a COMMIT for other users to see the setting for the flag that is changed. If you're doing this as part of a transaction that has updated other tables...that's a problem.

    2. You will also need to deal with cases where an error occurs in your codeunit and the process stops. When that happens, the flag will still be set in the setup table because it was committed and the logic never got to the point where it clears the flag.
  • Rob_HansenRob_Hansen Member Posts: 296
    Sorry - just saw the previous post using IF CODEUNIT.RUN... That should work fine to trap for any errors so that the flag can be reset.
  • Purvesh_MaisuriaPurvesh_Maisuria Member Posts: 71
    Hi Satbit And Rob,

    I tried satbir's idea. It is good but....

    In the case of GUI, when running progressbar, and I press cancel button in between processing then it stop the execution there only. So there is not get any benefit of writing IF Codeunit.RUN Then...

    My flag is not reset, so it prevent all user to run the functionality. ](*,)

    Still searching some solution. If you got any solution then, please reply here.

    Thanks & Regards,
    Purvesh Maisuria.
  • satbirsatbir Member Posts: 33
    Where is your code to reset? in the same codeunit which has the progress bar or outside in other codeunit?
  • Purvesh_MaisuriaPurvesh_Maisuria Member Posts: 71
    Hi Satbir,

    PageAction - OnAction() // page action

    CLEAR(CU50001);
    CU50001.SetFlag(TRUE); // Set the Boolean value in Table's field
    Commit;

    IF CU50001.RUN(Rec) Then; // Here in CU50001, my progress bar is running...

    CU50001.SetFlag(FALSE); // Reset the Boolean value in Table's field


    Thanks & Regards,
    Purvesh Maisuria.
  • navuser1navuser1 Member Posts: 1,329
    what will happen in next time ?

    Suppose your first part (as mentioned below) executed successfully.
    CLEAR(CU50001);
    CU50001.SetFlag(TRUE); // Set the Boolean value in Table's field
    Commit;

    and then suppose you hang in the next part (as mentioned below)
    IF CU50001.RUN(Rec) Then;

    Your table data will remain unchanged (remain TRUE).
    If this will happen then no other user can able to execute the same code.
    Now or Never
  • Purvesh_MaisuriaPurvesh_Maisuria Member Posts: 71
    Hi navuser1,

    You are right, same thing I write in my above post.
    My flag is not reset, so it prevent all user to run the functionality. ](*,)

    Now, the problem you know very well.

    How can I prevent other user to run multiuser to run the same codeunit ?

    [-o< #-o
  • Purvesh_MaisuriaPurvesh_Maisuria Member Posts: 71
    Hello Experts,

    Still searching for this solution. Please reply if any one gone through with same problem.

    Thanks & Regards,
    Purvesh Maisuria.
  • okioki Member Posts: 46
    Hi,
    I think you can afford a locking in the following way:



    The codeunit uses a local copy of itself to wrap the lock functionality in the same object.
    RunProcessingData is a global variable of boolean type which you have to add.

    Hope this helps

    Oli
  • Rob_HansenRob_Hansen Member Posts: 296
    I'm still not sure this is being approached the right way (I'd be looking at table locking myself and how to implement controls that way) but anyway...

    If the risk is a complete crash or infinite loop after the point that the flag is set (so it is never unset) then you can change your logic to add some handling for that. Instead of a simple Boolean flag to indicate the process is locked, switch it to an Integer. "Locked by Session ID". When you set the lock, store the current session ID in that field. Then, when another user goes to run the process and you see that there is a "Locked by Session ID", add some logic to check if the session still exists. If the session crashed it should be gone. If the session no longer exists, simply allow the user to proceed and update the "Locked by Session ID" to the new session that needs to block other users.

    If the session went into an infinite loop then it will still exist...so you'll need to come up with some logic to handle that. If you have infinite loops happening they're going to cause issues for the NAV server anyway, so someone will be restarting it to clear them.
Sign In or Register to comment.