How to resend a large number of messages in Ensemble

The message viewer can resend messages but it is not suitable for resending a large number of messages (>100).  For that, you should use Cache Object Script code such as the following:

 

Class Sample.Resender Extends %RegisteredObject
{

ClassMethod Resend()
{
//Resend all messages sent from 'FromComponent' to 'ToComponent' between 2016-06-15 and 2016-06-20
&sql(DECLARE C1 CURSOR FOR
 SELECT ID INTO :id FROM Ens.MessageHeader
 WHERE SourceConfigName='FromComponent' AND TargetConfigName='ToComponent'
 AND TimeCreated BETWEEN '2016-06-15' AND '2016-06-20')

&sql(OPEN C1)
&sql(FETCH C1)

set tSC = $$$OK

while (SQLCODE = 0) {
//id holds the id for one message. Resend it
set tSC = ##class(Ens.MessageHeader).ResendDuplicatedMessage(id)
quit:$$$ISERR(tSC)
&sql(FETCH C1)
}

&sql(CLOSE C1)
quit tSC
}

}

 

You could also add code to this such as better error checking, code to restart where it left off if there's a problem, etc.

Here is documentation for embedded SQL and for Ens.MessageHeader method ResendDuplicatedMessage:

http://docs.intersystems.com/ens20161/csp/docbook/DocBook.UI.Page.cls?KE...

http://docs.intersystems.com/ens20152/csp/documatic/%25CSP.Documatic.cls... 

Comments

I don't understand the technical ins and out of large numbers of messages.

However, I did read some documentation recently on Cache Semaphores.

If I understand what you are  are asking, it seems that Semaphores may be the answer.

Here is a little documentation I found.

Semaphores

This release introduces semaphores to Caché applications. Semaphores provide a fast, efficient mechanism for signaling, control and synchronization among processes, especially between those running on an ECP system. For more about the use of semaphores, consult the class documentation, %SYSTEM.Semaphore, or the technical article on the subject.

Thanks for your response.  This wasn't a question, but an article to explain to Ensemble programmers how to resend a large number of Ensemble messages.  It's not related to semaphores.

 

Personally, I create and use an XXX_Dummy_Service as a generic inbound TCP/IP operation or business service.  In order to grab the messages in question I simply query for them using interface explorer which offers a free 30 or maybe even 45 day trial.  Anyway, using this API to interact with Ensemble is easier for me to filter down to resend only what I desire and is easy to resend to a different environment for testing purposes etc.

Using dynamic SQL it is possible to set the source, target, new target hosts and time ranges for messages resend dynamically as is shown in the sample class method. The last parameter pResend could be used to enable/disable the resend:

ClassMethod ResendMessages(pSource = "MsgRouter", pTarget = "HL7FileOperation", pNewTarget = "FTP_Out", pTimeFrom = "2016-10-16 18:00:00.000", pTimeTo = "2016-10-16 19:00:00.000", pResend = 0)
{
Set tQuery = "select * from Ens.MessageHeader where "
Set tQuery = tQuery_" SourceConfigName="_"'"_pSource_"'"
Set tQuery = tQuery_" and TargetConfigName="_"'"_pTarget_"'"
Set tQuery = tQuery_" and TimeCreated > "_"'"_pTimeFrom_"'"
Set tQuery = tQuery_" and TimeCreated < "_"'"_pTimeTo_"'"
 
Write !, "SQL query for messages resend:", !, tQuery, !
Write !, "Messages new target: ", pNewTarget, !
Write !, "Resend messages? ", pResend, !
 
Set tRS = ##class(%ResultSet).%New("%DynamicQuery:SQL")
Set tRS.RuntimeMode = 1
Do tRS.Prepare(tQuery)
Set tSC = tRS.Execute()
Set tRowcount=0, tHL7count=0
While tRS.Next() {
Set tRowcount = tRowcount + 1
Set tClass = tRS.Data("MessageBodyClassName")
Set tId = tRS.Data("ID")
Set tHL7Id = tRS.Data("MessageBodyId")
Continue:tClass'="EnsLib.HL7.Message"
If pResend {
Set tSC = ##class(Ens.MessageHeader).ResendDuplicatedMessage(tId,,pNewTarget)
If $$$ISERR(tSC) { Do $system.OBJ.DisplayError() Quit }
Set tHL7count = tHL7count + 1
}
 }

 Write !, "Message Headers: ", tRowcount, !
 Write "Resent HL7 messages: ", tHL7count,!
}

Sample ResendMessages call:

ENSEMBLE>do ##class(Sample.Resender).ResendMessages("MsgRouter", "HL7FileOperation", "FTP_Out", "2016-10-16 18:00:00.000", "2016-10-16 19:00:00.000", 1)
 
SQL query for messages resend:
select * from Ens.MessageHeader where  SourceConfigName='MsgRouter' and TargetConfigName='HL7FileOperation' and TimeCreated > '2016-10-16 18:00:00.000' and TimeCreated < '2016-10-16 19:00:00.000'
 
Messages new target: FTP_Out
 
Resend messages? 1
 
Message Headers: 2
Resent HL7 messages: 2

 

Hi 

I am looking for something very similar to this as I would like to pick up suspended messages and resubmit them using SQL.  Are you able to advise how I could modify the SQL in your code to filter suspended messages?

Thank you for your help.

Kind Regards,

Salma

Ens.MessageHeader has a Status column.  You may need to select on the name or its corresponding number depending on select mode.  For example, status "Suspended" is 5.  If selecting in display mode, use Status='Suspended' and in raw mode use Status=5 in your where clause.

The number for each status is defined in macros in EnsConstants.inc - the ones that start with eMessageStatus

Thank you for your reply, this was very useful as I could not figure out why Status='Suspended' was not returning any rows in the raw mode. You have saved me a lot of time :)

Thanks again.

Salma