· Jun 20, 2016 1m read

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
 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)
&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: 

Discussion (7)0
Log in or sign up to continue

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.


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.

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")
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

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 - the ones that start with eMessageStatus