Author |
Message
|
akil |
Posted: Sun Dec 14, 2014 9:28 pm Post subject: IIB9: Singleton Flow |
|
|
 Partisan
Joined: 27 May 2014 Posts: 338 Location: Mumbai
|
Hi
The system that I have to integrate requires a 'login' to be done before any other API can be called. This 'login' in non-standard, by that I mean no SOAP/HTTPAuth. It is a HTTP-XML API, that returns a session-token. This session-token needs to be passed as a message element in all subsequent API's.
So the msg-flow sequence is as follows :
HTTPInput --> makeLoginReqXML --> HTTPRequest (login) --> makeAPIReqXML --> HTTPRequest (login).
There is no logout , so the above flow works. The only thing is that on every login a new token is created.
As long as there's one thread , all if fine, but when there are more than 1 threads, there are intermittent failures, (both the threads complete login with the same details, thereby making the token for one thread invalid).
One option is for me to have separate credentials per thread - I've to figure out some way of configuring all those credentials (I currently use UserDefineServices to configure credentials).
Is there any other way? Like for example, ensuring that the 'login' is single-threaded, but the other parts of the flow are multi-threaded? I can then do some additional work to not call login every-time, and instead share a session token across multiple threads? _________________ Regards |
|
Back to top |
|
 |
Vitor |
Posted: Mon Dec 15, 2014 6:04 am Post subject: Re: IIB9: Singleton Flow |
|
|
 Grand High Poobah
Joined: 11 Nov 2005 Posts: 26093 Location: Texas, USA
|
akil wrote: |
Is there any other way? Like for example, ensuring that the 'login' is single-threaded, but the other parts of the flow are multi-threaded? I can then do some additional work to not call login every-time, and instead share a session token across multiple threads? |
Yes - either store the session token in an actual Java singelton, an ESQL SHARED variable or the global cache (if using a level of software that contains this feature). _________________ Honesty is the best policy.
Insanity is the best defence. |
|
Back to top |
|
 |
akil |
Posted: Mon Dec 15, 2014 10:27 am Post subject: |
|
|
 Partisan
Joined: 27 May 2014 Posts: 338 Location: Mumbai
|
Hi
How do I get just the login portion of the message flow to be single threaded? _________________ Regards |
|
Back to top |
|
 |
smdavies99 |
Posted: Mon Dec 15, 2014 10:53 am Post subject: |
|
|
 Jedi Council
Joined: 10 Feb 2003 Posts: 6076 Location: Somewhere over the Rainbow this side of Never-never land.
|
If this is just the initial login then an ATOMIC Block might be the solution. _________________ WMQ User since 1999
MQSI/WBI/WMB/'Thingy' User since 2002
Linux user since 1995
Every time you reinvent the wheel the more square it gets (anon). If in doubt think and investigate before you ask silly questions. |
|
Back to top |
|
 |
Vitor |
Posted: Mon Dec 15, 2014 12:14 pm Post subject: |
|
|
 Grand High Poobah
Joined: 11 Nov 2005 Posts: 26093 Location: Texas, USA
|
smdavies99 wrote: |
If this is just the initial login then an ATOMIC Block might be the solution. |
You also need to turn the problem on it's head in your mind. You're not trying to make the logon part of a flow single threaded, but you're trying to ensure only 1 thread does the logon. This is almost but not quite the same thing. If you use ATOMIC to ensure only the first attempt actually logs on, then you have achieved a single threaded solution.... _________________ Honesty is the best policy.
Insanity is the best defence. |
|
Back to top |
|
 |
akil |
Posted: Mon Dec 15, 2014 6:42 pm Post subject: |
|
|
 Partisan
Joined: 27 May 2014 Posts: 338 Location: Mumbai
|
I am trying to understand this,
In the documentation it says
Quote: |
Do not nest BEGIN ATOMIC... END statements, either directly or indirectly, because this could lead to "deadly embraces". For this reason, do not use a PROPAGATE statement from within an atomic block.
|
If that is the case, how do I get a session token? I mean I have to make a http request to get a token, the store it for shared use.. Not able to figure out that part. _________________ Regards |
|
Back to top |
|
 |
Vitor |
Posted: Tue Dec 16, 2014 5:47 am Post subject: |
|
|
 Grand High Poobah
Joined: 11 Nov 2005 Posts: 26093 Location: Texas, USA
|
akil wrote: |
If that is the case, how do I get a session token? I mean I have to make a http request to get a token |
Not if a valid token is already stored. _________________ Honesty is the best policy.
Insanity is the best defence. |
|
Back to top |
|
 |
akil |
Posted: Tue Dec 16, 2014 9:16 pm Post subject: |
|
|
 Partisan
Joined: 27 May 2014 Posts: 338 Location: Mumbai
|
Yes, got that, I can pick-up the session once it is stored..
I am trying to figure out how do I ensure that only one thread makes the HTTP call to get a session token (the very first time or whenever the token expires / invalidates ). _________________ Regards |
|
Back to top |
|
 |
smdavies99 |
Posted: Tue Dec 16, 2014 11:30 pm Post subject: |
|
|
 Jedi Council
Joined: 10 Feb 2003 Posts: 6076 Location: Somewhere over the Rainbow this side of Never-never land.
|
Define Two SHARED boolean variables B1 & B2 defaulted to FALSE
The first thread enters the Atomic block and tests B1.
As this is False, it sets B2 to true and exits the block
Then it tests for B1 = False AND B2 = True
As it is good, the thread does the http request and stores the result
Then it enters another atomic block
Sets B1 = True and B2 = False
exit block
Other threads will see that B1 = True and use the value obtained by the HTTP request.
Well something like this. Try it and see what happens. If it does not work you will soon figure out a way to make it work.
Remember to really test this under every possible workload. _________________ WMQ User since 1999
MQSI/WBI/WMB/'Thingy' User since 2002
Linux user since 1995
Every time you reinvent the wheel the more square it gets (anon). If in doubt think and investigate before you ask silly questions. |
|
Back to top |
|
 |
maurito |
Posted: Wed Dec 17, 2014 12:52 am Post subject: |
|
|
Partisan
Joined: 17 Apr 2014 Posts: 358
|
smdavies99 wrote: |
Define Two SHARED boolean variables B1 & B2 defaulted to FALSE
The first thread enters the Atomic block and tests B1.
As this is False, it sets B2 to true and exits the block
Then it tests for B1 = False AND B2 = True
As it is good, the thread does the http request and stores the result
Then it enters another atomic block
Sets B1 = True and B2 = False
exit block
Other threads will see that B1 = True and use the value obtained by the HTTP request.
Well something like this. Try it and see what happens. If it does not work you will soon figure out a way to make it work.
Remember to really test this under every possible workload. |
This logic is flawed, but even if it was not, you are not allowed to PROPAGATE from inside an ATOMIC block, the deploy will fail. |
|
Back to top |
|
 |
smdavies99 |
Posted: Wed Dec 17, 2014 1:04 am Post subject: |
|
|
 Jedi Council
Joined: 10 Feb 2003 Posts: 6076 Location: Somewhere over the Rainbow this side of Never-never land.
|
maurito wrote: |
This logic is flawed, but even if it was not, you are not allowed to PROPAGATE from inside an ATOMIC block, the deploy will fail. |
Where did I say that I was going to propagate from inside the Atomic block?
I was very explicit about just testing BOOLEANs and setting flags inside the block.
The logic might be flawed a bit. I gave no guarentees as to it working. That is up to the OP to work on. That is why I said
Quote: |
Well something like this.
|
_________________ WMQ User since 1999
MQSI/WBI/WMB/'Thingy' User since 2002
Linux user since 1995
Every time you reinvent the wheel the more square it gets (anon). If in doubt think and investigate before you ask silly questions. |
|
Back to top |
|
 |
maurito |
Posted: Wed Dec 17, 2014 1:07 am Post subject: |
|
|
Partisan
Joined: 17 Apr 2014 Posts: 358
|
smdavies99 wrote: |
maurito wrote: |
This logic is flawed, but even if it was not, you are not allowed to PROPAGATE from inside an ATOMIC block, the deploy will fail. |
Where did I say that I was going to propagate from inside the Atomic block?
I was very explicit about just testing BOOLEANs and setting flags inside the block.
The logic might be flawed a bit. I gave no guarentees as to it working. That is up to the OP to work on. That is why I said
Quote: |
Well something like this.
|
|
If you do not propagate from inside the ATOMIC, then several threads can propagate as you are not single threading, so it does not matter how many BOOLEANs you add, you cannot solve the problem.
The OP might decide to put up with a few failures while the HTTP call(calls) is (are) performed and the SHARED initialized to store the credentials ( in an ATOMIC ). |
|
Back to top |
|
 |
smdavies99 |
Posted: Wed Dec 17, 2014 2:58 am Post subject: |
|
|
 Jedi Council
Joined: 10 Feb 2003 Posts: 6076 Location: Somewhere over the Rainbow this side of Never-never land.
|
maurito wrote: |
The OP might decide to put up with a few failures while the HTTP call(calls) is (are) performed and the SHARED initialized to store the credentials ( in an ATOMIC ). |
That is why I tried to emphasis proper testing.
You could design the flow to get a trigger message when it starts. This would cause the credentials to be retrieved. I think that there might still be a small window there requests are rejected because the credentials are not yet in the shared variables.
The design also does not take into consideration what happens when the HTTP request to get the credentials fails.
I was merely trying to convey some ideas about how to develop a solution and not to develop it for them. _________________ WMQ User since 1999
MQSI/WBI/WMB/'Thingy' User since 2002
Linux user since 1995
Every time you reinvent the wheel the more square it gets (anon). If in doubt think and investigate before you ask silly questions. |
|
Back to top |
|
 |
rekarm01 |
Posted: Wed Dec 17, 2014 6:00 am Post subject: Re: IIB9: Singleton Flow |
|
|
Grand Master
Joined: 25 Jun 2008 Posts: 1415
|
maurito wrote: |
If you do not propagate from inside the ATOMIC, then several threads can propagate as you are not single threading, so it does not matter how many BOOLEANs you add, you cannot solve the problem. |
Given enough auxiliary variables, there are plenty of mutual exclusion algorithms that can solve this problem, even without the use of ATOMIC blocks. It's more difficult without being able to propagate inside an ATOMIC block, but not impossible. Here's a more detailed example, adapted from real working code, (provided as-is, not tested, no guarantees, etc.):
Code: |
DECLARE SharedSessionToken SHARED CHARACTER NULL;
DECLARE SharedLoginLock SHARED BOOLEAN FALSE;
SET Environment.Variables.SessionToken = NULL;
SET Environment.Variables.LoginLock = FALSE;
WHILE Environment.Variables.SessionToken IS NULL DO
-- Declare Handler to release lock and resignal, upon exception
-- ...
-- check if login necessary, and if so, try to grab login lock
LoginMutex: BEGIN ATOMIC
IF SharedSessionToken IS NULL -- no SessionToken
AND NOT SharedLoginLock THEN -- not currently locked
SET SharedLoginLock = TRUE; -- grab lock
SET Environment.Variables.LoginLock = TRUE;
END IF;
END;
-- if lock grabbed, then login
IF Environment.Variables.LoginLock THEN
PROPAGATE TO ... ; -- sets Environment.Variables.SessionToken
END IF;
-- synchronize Shared SessionToken and Environment.Variables
LoginMutex: BEGIN ATOMIC
IF SharedSessionToken IS NULL
AND Environment.Variables.SessionToken IS NOT NULL THEN
SET SharedSessionToken = Environment.Variables.SessionToken;
ELSEIF Environment.Variables.SessionToken IS NULL
AND SharedSessionToken IS NOT NULL THEN
SET Environment.Variables.SessionToken = SharedSessionToken;
END IF;
-- release lock, if necessary
IF Environment.Variables.LoginLock THEN
SET SharedLoginLock = FALSE;
SET Environment.Variables.LoginLock = FALSE;
END IF;
END;
-- sleep, to minimize busy-wait
-- IF Environment.Variables.SessionToken IS NULL THEN
-- ... SLEEP ...;
-- END IF;
END WHILE; |
|
|
Back to top |
|
 |
maurito |
Posted: Thu Dec 18, 2014 3:14 am Post subject: Re: IIB9: Singleton Flow |
|
|
Partisan
Joined: 17 Apr 2014 Posts: 358
|
rekarm01 wrote: |
maurito wrote: |
If you do not propagate from inside the ATOMIC, then several threads can propagate as you are not single threading, so it does not matter how many BOOLEANs you add, you cannot solve the problem. |
Given enough auxiliary variables, there are plenty of mutual exclusion algorithms that can solve this problem, even without the use of ATOMIC blocks. It's more difficult without being able to propagate inside an ATOMIC block, but not impossible. Here's a more detailed example, adapted from real working code, (provided as-is, not tested, no guarantees, etc.):
Code: |
DECLARE SharedSessionToken SHARED CHARACTER NULL;
DECLARE SharedLoginLock SHARED BOOLEAN FALSE;
SET Environment.Variables.SessionToken = NULL;
SET Environment.Variables.LoginLock = FALSE;
WHILE Environment.Variables.SessionToken IS NULL DO
-- Declare Handler to release lock and resignal, upon exception
-- ...
-- check if login necessary, and if so, try to grab login lock
LoginMutex: BEGIN ATOMIC
IF SharedSessionToken IS NULL -- no SessionToken
AND NOT SharedLoginLock THEN -- not currently locked
SET SharedLoginLock = TRUE; -- grab lock
SET Environment.Variables.LoginLock = TRUE;
END IF;
END;
-- if lock grabbed, then login
IF Environment.Variables.LoginLock THEN
PROPAGATE TO ... ; -- sets Environment.Variables.SessionToken
END IF;
-- synchronize Shared SessionToken and Environment.Variables
LoginMutex: BEGIN ATOMIC
IF SharedSessionToken IS NULL
AND Environment.Variables.SessionToken IS NOT NULL THEN
SET SharedSessionToken = Environment.Variables.SessionToken;
ELSEIF Environment.Variables.SessionToken IS NULL
AND SharedSessionToken IS NOT NULL THEN
SET Environment.Variables.SessionToken = SharedSessionToken;
END IF;
-- release lock, if necessary
IF Environment.Variables.LoginLock THEN
SET SharedLoginLock = FALSE;
SET Environment.Variables.LoginLock = FALSE;
END IF;
END;
-- sleep, to minimize busy-wait
-- IF Environment.Variables.SessionToken IS NULL THEN
-- ... SLEEP ...;
-- END IF;
END WHILE; |
|
@rekarm01: yes, that seems to work really well. Thanks for sharing ! |
|
Back to top |
|
 |
|