› Clovertech Forums › Read Only Archives › Cloverleaf › Cloverleaf › message delay questions
I am trying to determine if it is possible to delay all messages going to a certain thread? I was hoping there might be a bit of TCL code that I can use as a pre-proc to delay every message by a few seconds.
Any ideas?
See if this helps any. Here is the argument example {SECS 90}.
#######################################################################################
#######################################################################################
#######################################################################################
#
# Name: tpsDelay
# Purpose: This procedure sleeps for the number of seconds specified.
#
# UPoC type: tps
# Args: tps keyedlist containing the following keys:
# MODE run mode (”start”, “run” or “time”)
# MSGID message handle
# ARGS user-supplied arguments:
# The user supplied segment to remove is in the form of a keyed list
# The key is SECS
# The value is a number that = the number of seconds to sleep
#
# Returns: tps disposition list:
#
# John T. Zalesak 12/11/2008
#
#######################################################################################
#######################################################################################
#######################################################################################
proc tpsDelay { args } {
#######################################################################################
# Setup some globals used
#######################################################################################
global HciConnName
global HciSite
#######################################################################################
# Get the Connection Name for Error/Debug Messages
#######################################################################################
set myname “$HciConnName/[lindex [info level 1] 0]”
#######################################################################################
# Initialize Variables Used
#######################################################################################
set delaytime 0 ;# Seconds to Sleep, Default is 0
set dispList {} ;# Disposition List Returned to Engine
#######################################################################################
# Load in the arguments we need that were passed from the caller
#######################################################################################
keylget args MODE mode ;# The mode the engine called from
keylget args ARGS.SECS delaytime ;# The seconds to sleep
#######################################################################################
# We only want to take action if called from the run mode
#######################################################################################
switch -exact — $mode {
start {
;# Do Nothing
}
run {
echo n n
echo “Site: $HciSite Connection/tps: $myname”
echo “Going to sleep for $delaytime seconds.
— [clock format [clock scan “today”] -format “%Y-%m-%d %H:%M:%S”]”
sleep $delaytime ;# User Specified Sleep Time in Secs
echo “Done Sleeping!”
echo n n
set mh [keylget args MSGID] ;# Get message handle from args
set dispList [list “CONTINUE $mh”] ;# Initialize to good message
}
time {
;# Do Nothing
}
shutdown {
;# Do Nothing
}
} ;# End Switch
return $dispList
} ;# End Proc
Thanks for posting that! However, I was told that the “sleep” command pauses the entire process and this could potientally impact any other threads running under this same process – is there another way to do this without using “sleep”?
ahh, i see. and yes it does the process. Have you looked into message throttling? i have never used it so it may or may not apply.
I would also be concerned with just sleeping/pausing a certain number of seconds.
If another message arrives from your source system during the time the previous one is “sleeping”, it would then wait for the balance of the previous messages sleepy time as well as its own. So, your delay could be compounded on an interface with fairly frequent messages.
But, my primary question would be: “Why do you need the delay in the first place?”
I’ve used message deferral in a few situations, but it’s never been because of a few seconds timing issue – it’s always been to accommodate some sort of system limitation.
For example, our clinical system sends diet orders with a future date. The dietary system can’t handle the future dates (it immediately cancels the active order and replaces it with the future one), so we put the future order in a SQLite database, then wait to send it until its scheduled start time.
Jeff Dinsmore
Chesapeake Regional Healthcare
The reason that I am faced with looking into all of this is as follows:
We have a system that we are sending ADT and SIU messages to. This system needs these messages on different ports. We have one thread setup for ADT and another setup for SIU.
Our sending system sends the ADT and SIU messages very quickly, one after the other – and we send them on to the receiving system – they seem to arrive at just about the same exact time – so close together that sometimes the receiving system processes the SIU before they get the ADT and that is a problem for them.
Because of that, we need a way to delay all SIU messages by a few seconds, so that we are sure the ADT is received and processed first.
What I have done is similar instances is to write the messages I need to hold to a SQLite database with current timestamp. The database would include a field that indicates if the message has been sent or not. Then I would have another thread read the database on a timed schedule and send messages that have been queued for a minimum amount of time, in my case a couple hours, but you could easily shorten to minutes as to not delay the messages to long.
Another option is to ask the receiving system to delay their acknowledtment of the SIU messages for a given amount of time or to provfide a ‘suspense’ process – they should be responsible for the handling in this case in my opinion.
email: jim.kosloskey@jim-kosloskey.com 29+ years Cloverleaf, 59 years IT - old fart.
We use this method for delaying – for similar reasons – but our delays are longer. This would work for seconds, but is simpler for a minute.
Add one extra thread that replaces the outbound thread. This new thread writes OB messages to a repository with date stamped files. The thread also reads the repository and picks up files older than a minute, loads the messages and delivers them.
Thank you all for your comments. I wanted to send out a brief update and also ask another question.
I ended up using Kevin’s code snippit and have a simple tps proc on my outbound thread that delays sending the scheduling messages for a few seconds.
We run this thread in its own process because we were worried the sleep command would have an impact on other code and threads in the same process.
However, I saw an option in any of the TPS selectors where you can “Run in a Sub-Thread” – are any of you familiar with this?
I found a clean way to delay messages. You must put the outbound tread on hold, and call the script in ob_tps that will release one messages latter with the unix “at” command. It take the parameters: DELAY UNIT and HCIPROCESS
[code]
set gVersion:gTpsDelayMsg 1.0
proc gTpsDelayMsg { args } {
global HciConnName
set gVersion:gTpsDelayMsg 1.0
proc gTpsDelayMsg { args } {
global HciConnName
Attempting to use the script posted by Jacques but I get TCL 203 error.
We are on AIX 6.1 and we have Cloverleaf 6.1
May be you have an older version of Cloverleaf ?
using 6.0.2
Does your script contain features that only work on 6.1?
I know the hcicmd is normal command…
I don’t understand this part of your script:
$HciConnName prls_obd 1′ > /dev/null 2> /dev/null” | at now + $delay $unit > /dev/null 2> /dev/null
Thanks for posting that!
Aaron: You are correct, the sleep command affects the whole process and other blocking commands such as at, etc cab be unreliable since they depend on a continuous running process which we do not have.
One way to accomplish what you want – not very pretty but works.
Set up a timer thread that runs periodically. Feed the thread you wish to delay with that one. Have the timer thread send a token when it fires. Anything would do that you would recognize in the other thread.
In the OB thread set a global or namespace value with the time it was last released – set to 0 to start. Also set up a saved message handle buffer – set to empty to start. Each time you receive a token compare global time with current time. If you have messages in the saved buffer end them all. Be sure and KILL the token message handle.
Whenever a message is received in the OB thread, simple save the message handle to the message handle buffer and return the empty string. This makes sure the messages remain in State 10 if shutdown occurs.
When it is time to send, update the time last released and CONTINUE all of the message handles in the message buffer. Be sure and set message buffer to empty string and KILL token message handle
I hope it makes sense
As I said not very elegant but I have used it and it works.
Aaron: You are correct, the sleep command affects the whole process and other blocking commands such as at, etc cab be unreliable since they depend on a continuous running process which we do not have.
One way to accomplish what you want – not very pretty but works.
Set up a timer thread that runs periodically. Feed the thread you wish to delay with that one. Have the timer thread send a token when it fires. Anything would do that you would recognize in the other thread.
In the OB thread set a global or namespace value with the time it was last released – set to 0 to start. Also set up a saved message handle buffer – set to empty to start. Each time you receive a token compare global time with current time. If you have messages in the saved buffer end them all. Be sure and KILL the token message handle.
Whenever a message is received in the OB thread, simple save the message handle to the message handle buffer and return the empty string. This makes sure the messages remain in State 10 if shutdown occurs.
When it is time to send, update the time last released and CONTINUE all of the message handles in the message buffer. Be sure and set message buffer to empty string and KILL token message handle
I hope it makes sense
As I said not very elegant but I have used it and it works.
Sorry about the double send. This internet suks!
using 6.0.2
Does your script contain features that only work on 6.1?
I know the hcicmd is normal command…
I don’t understand this part of your script:
$HciConnName prls_obd 1′ > /dev/null 2> /dev/null” | at now + $delay $unit > /dev/null 2> /dev/null
Let me explain here is the complete line:
exec echo “hcicmd -p $HciProcess -s $HciSite -c ‘$HciConnName prls_obd 1’ > /dev/null 2> /dev/null” | at now + $delay $unit > /dev/null 2> /dev/null
I ask tcl to execute the script in a shell
The script start with an echo of a command that is piped for input to the at command.
at will execute later :
“hcicmd -p $HciProcess -s $HciSite -c ‘$HciConnName prls_obd 1’ > /dev/null 2> /dev/null”
The at command usualy return the log and err with mail, so I redirected every output to /dev/null
The hcicmd release one message with prls_obd .
I think older 6.1 version prls_obd didn”t had a parameter, it was releasing everything that were on hold in the outbound.
Aaron:
Perhaps you are correct but the at command as I understand it will run the process at a given time. It would probably be OK if only one thread used that process
Perhaps you are correct but the at command as I understand it will run the process at a given time.
Jeff’s idea of putting the messages in a database will work well. I’ve done something similar where we write the messages out to files, then we use a fileset-local inbound thread to read the files back in. We use a dirparse proc that filters out the files that have a modification time that’s more recent than the delay that we want to introduce.