Question
· Feb 14

Is there a way to programmatically delete suspended messages?

Is there a way to delete suspended messages rather than using the WebMgmt gui?  

We have over three million in one namespace, and using the gui I can only do 2000 at a time. 

I was thinking of using delete in sql like  Ens.MessageHeader where Status = 'Suspended'

But I don't know if that is a clean way to do it.

Product version: IRIS 2023.1
$ZV: IRIS for UNIX (Red Hat Enterprise Linux 8 for x86-64) 2023.1.4 (Build 580_0_23807U) Mon Nov 25 2024 18:17:37 EST [HealthConnect:5.1.0-3.m4]
Discussion (15)4
Log in or sign up to continue

Whatever you use,  portal, code or SQL, I'd suggest NOT to delete the suspended messages. If you delete a message, only the message header will be deleted, leaving all the associated requests/responses orphaned.

I suggest discarding the messages using SQL.

Be careful doing so with a single update SQL statement for 2M messages, with more that 1000 records lock escalation will lock the entire Ens.MessageHeader table/class and your production will have big trouble. To avoid it use %NOLOCK.

Using Display mode:

Update %NOLOCK Ens.MessageHeader set Status ='Discarded' where Status = 'Suspended'

Using Logical or ODBC mode:

Update %NOLOCK Ens.MessageHeader set Status = 4 where Status = 5

Thank you for the answers! I have a follow up question.

I have been deleting suspended messages already. So how do I go about cleaning up the orphans I've created? 

For instance, in one namespace where I know I deleted some suspended messages (and where all messages older than 7 days are supposed to have been purged), I ran this query:

select * from Ens.MessageHeader nolock
where timecreated < '2025-02-11 00:00:00.000'
order by timecreated 

I get 18298 messages - under four distinct session ids. 

How can I mark these so that will be purged? Or is there some other method of purging these orphans since I deleted their message header? 

Note: These are the settings on our Purge task:

The class Ens.MessageHeader has a classmethod Purge() that deletes message headers and bodies based on the number of days to keep along with a few other criteria; those are used in an SQL query to select the set of messages to purge. That query along with the associated purge code should work as an example to see what's involved in carefully removing messages without collateral damage ... search table indices need to be maintained, for example.

There's also the Ens.Util.MessagePurge task definition that is used for scheduled purges, it has much of the same code but offers a multi-threaded purge feature that leverages the work queue.

@Enrico Parisi's solution moves the actual purge of the messages off to the scheduled Ens.Util.MessagePurge task for messages that exceed the DaysToKeep limit, as long as that is configured to delete bodies too. This is likely the safer solution and requires significantly less effort 😉

Thank you for the answers! I have a follow up question.

I have been deleting suspended messages already. So how do I go about cleaning up the orphans I've created? 

For instance, in one namespace where I know I deleted some suspended messages (and where all messages older than 7 days are supposed to have been purged), I ran this query:

select * from Ens.MessageHeader nolock
where timecreated < '2025-02-11 00:00:00.000'
order by timecreated 

I get 18298 messages - under four distinct session ids. 

How can I mark these so that will be purged? Or is there some other method of purging these orphans since I deleted their message header? 

Note: These are the settings on our Purge task:

@Jeffrey Drumm , it's too late, he has already deleted the headers so the bodies are already orphaned.

@Kirsten Whatley , there is no query using the Ens.MessageHeader that can return orphaned message bodies info/reference. The very definition of orphaned messages is that have lost the link form Ens.MessageHeader.

Do you know the MessageBodyClassName of the messages you have deleted?
If it's a custom defined persistent class, can you provide some detail of the message(es) class(es)?

 

I am pretty sure that the bulk of the orphans are this message class:

Class AH.AHLIB.Custom.NextGate.Message.Patient Extends (Ens.Request, %Persistent, %JSON.Adaptor, %XML.Adaptor)

{

Parameter %JSONIGNOREINVALIDFIELD = 1;

Property header As AH.AHLIB.Custom.NextGate.Message.Patient.Header;

Property event As AH.AHLIB.Custom.NextGate.Message.Patient.Event;

Property entity As list Of AH.AHLIB.Custom.NextGate.Message.Patient.Entity;

Property additionalReferences As AH.AHLIB.Custom.NextGate.Message.Patient.AdditonalReferences;

Storage Default

{

<Data name="PatientDefaultData">

<Subscript>"Patient"</Subscript>

<Value name="1">

<Value>header</Value>

</Value>

<Value name="2">

<Value>event</Value>

</Value>

<Value name="3">

<Value>entity</Value>

</Value>

<Value name="4">

<Value>additionalReferences</Value>

</Value>

</Data>

<DefaultData>PatientDefaultData</DefaultData>

<Type>%Storage.Persistent</Type>

}

}

On a bit of a tangent but I might recommend reviewing the following post by my colleague and considering whether a 2 phase purge schedule would make sense for you. One purge task running as standard to clean up the completed messages and one running on a lag to catch any suspended / leftover messages that are old enough that you think they could be removed:

https://community.intersystems.com/post/why-keep-integrity-important-when-purging-healthshareensemble-data

Glad you found that interesting! One warning I can add is that if you do decide to add a "no-integrity" type purge and if you've never run one, depending on how many messages you have you may trigger a very large purge (and a lot of journaling activity as a result). Often times when making significant purge changes, it can be safer to increment the time period you are purging bit by bit to make sure you're not asking too much of a single purge.

ex. If you run daily message purges then every day you are purging 1 day's worth. If you have "expired" messages going back a few years and decide to purge them all of a sudden, that might be a surprising number.