文章
· 一月 8, 2021 阅读大约需 5 分钟

InterSystems 最佳实践之 Ensemble 孤立消息

在本文中,我们将讨论孤立消息。

什么是孤立消息

每个消息正文都与一个保存元数据的消息标头相关联。 标头保存源配置名称、目标配置名称、创建时间、处理时间、关联的消息正文引用、会话信息、消息正文类名、消息状态等信息。 当有消息正文记录没有相应的标头记录时,这些消息正文称为孤立消息正文。 我们将讨论可能导致孤立消息正文产生的原因。

仅清除标头

在清除任务设置中,BodiesToo 设置用于指定是否将消息正文与消息标头一起清除。 如果关闭此设置,清除任务将只删除消息标头,而保留消息正文。 这些消息正文将成为孤立记录,因为所引用的标头已被删除。 如果清除消息标头但保留消息正文,则管理门户将无法清除孤立消息正文。 在这种情况下,必须以编程方式清除消息正文。

 

请参阅有关清除任务的文档

http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=EGMG_purge#EGMG_purge_basic

复杂的消息正文类(对象值属性)

当 Ensemble 清除某条消息正文时,不一定删除该消息正文的对象值属性。 具体来说,只有当其他对象是序列对象或子对象(由关系定义)时,才会删除这些对象。 对于其他对象,必须通过在消息正文类中定义删除触发器或实现 %OnDelete() 方法来适当地处理删除。

OnDelete 实现的示例代码

Class Sample.Address Extends %Persistent{
/// The street address.
Property Street As %String(MAXLEN = 80);
/// The city name.
Property City As %String(MAXLEN = 80);
/// The 2-letter state abbreviation.
Property State As %String(MAXLEN = 2);
/// The 5-digit U.S. Zone Improvement Plan (ZIP) code.
Property Zip As %String(MAXLEN = 5);
}
Class Sample.Person Extends %Persistent{
/// Person's name.
Property Name As %String [ Required ];
/// Person's Social Security number. This is validated using pattern match.
Property SSN As %String(PATTERN = "3N1""-""2N1""-""4N") [ Required ];
/// Person's Date of Birth.
Property DOB As %Date;
/// Person's home address.
Property Home As Address;
/// Person's office address.
Property Office As Address;
///Callback for object deletion
ClassMethod %OnDelete(oid As %ObjectIdentity) As %Status [ Private ]{
      // Delete the property object references.
      Set tSC = $$$OK, tThis = ##class(Sample.Person).%Open(oid)
      If $ISOBJECT(tThis.Home) Set tSC = ##class(Sample.Address).%DeleteId(tThis.Home.%Id())
      If $ISOBJECT(tThis.Office) Set tSC = ##class(Sample.Address).%DeleteId(tThis.Office.%Id())
      Quit tSC
}
///Callback/Trigger for SQL delete
Trigger OnDelete [ Event = DELETE ]{
      // Delete the property object references. {%%ID} holds the id of the record being deleted.
      Set tID={%%ID}
      Set tThis = ##class(Sample.Person).%OpenId(tID)
      If $ISOBJECT(tThis.Home) Do ##class(Sample.Address).%DeleteId(tThis.Home.%Id())
      If $ISOBJECT(tThis.Office) Do ##class(Sample.Address).%DeleteId(tThis.Office.%Id())
      Quit
}
}

已创建但从未发送到其他主机的消息对象

当一条消息被发送/转发到其他主机时,Ensemble 会创建一个新的消息标头,并关联相应的消息正文。 如果在业务服务/流程中创建的消息正文/对象实例已保存到磁盘/数据库,但从未在生产过程中发送到其他主机,它将没有关联的标头,并保留为孤立消息正文。 最佳实践是不创建消息正文,除非它将被转发,或者不对该对象实例调用 %Save()(在将消息放入目标配置队列之前,SendRequestSync/SendRequestAsync API 将保存该对象实例)。 这样,除非将消息正文对象发送到其他主机,否则它将不会持久化。

此问题的最常见原因是开发人员:

  1. 克隆了消息正文,且从未转发克隆的消息正文
  2. 在上下文变量 (BPL) 中创建了消息正文对象,且从未转发。

孤立消息的影响

孤立消息不会被清除任务清除。 这些消息将占用磁盘空间,并且随着它们数量的增长,磁盘使用量也会成比例增加。 不仅消息正文数据使用磁盘空间,每条孤立消息正文记录的任何索引/搜索表条目也都占用磁盘空间。

识别孤立消息

可以通过查询消息标头和正文来确定孤立消息是否存在。 每个消息标头都引用相应的消息正文。 消息正文对象 Id 引用存储在标头的 MessageBodyId 属性中,消息正文类名存储在标头的 MessageBodyClassName 属性中。

在 HL7 消息表中查找孤立消息的示例查询:

SELECT HL7.Id  FROM EnsLib_HL7.Message HL7

   LEFT JOIN Ens.MessageHeader hdr

   ON HL7.Id=hdr.MessageBodyId

   WHERE hdr.MessageBodyId IS NULL

上面的查询将返回所有没有相应标头的 HL7 消息。 可以将该查询修改为查询任何其他消息类型,只需替换消息正文表名即可。

清除孤立消息

管理门户无法提供清除孤立消息正文的方法。 在这种情况下,必须以编程方式清除消息正文。 在 ENSDEMO 数据库中,类 Demo.Util.CleanupSet 提供了一个如何执行此操作的示例。 该例程也执行深度清除,同时处理对象属性引用。

还可以参考另一个例程来清除孤立消息,但该例程不执行深度清除,只对删除消息正文有帮助。 我在下面附上可下载源码的 github 链接:

https://gist.github.com/suriyasv/2ed7f2dbcfd8c79f3b9938762c17c0b5

最佳做法是始终:

  1. 避免编程错误(如前面所讨论)以防止出现孤立消息
  2. 只有需要正文并且知道只能以编程方式清除这些消息正文时,才将清除任务设置成关闭 BodiesToo 设置。
  3. 实施关系或针对持久对象属性实现 OnDelete。

我希望本文对您构建生产环境有所帮助。 如果您有任何问题或疑虑,请联系我们。 谢谢。

讨论 (0)3
登录或注册以继续