
Atenção: Há uma enquete importante no final deste artigo. Estou aguardando ansiosamente suas respostas!
Então, encontramos um obstáculo. Um grande. Não há como pesquisar mensagens em nossa produção.
Claro, uma mensagem chega ao serviço REST, e tudo na produção funciona perfeitamente como deveria.

Aqui está uma requisição de exemplo:
{
"case":"2-12-85-06",
"to":"management of ZOO",
"subject":"Children report that the horse has grown a fifth leg"
}
Tudo parece correr bem na produção!

MAS! Então, ou nós ou o cliente queremos mais:
"Ei, podemos filtrar mensagens por critérios específicos? Por exemplo, já recebemos algo relacionado ao número do caso 2-12-85-06?"
E é aí que as coisas tomaram um rumo sinistro.
O tipo de mensagem padrão, EnsLib.HTTP.GenericMessage, armazena dados JSON em fluxos. Uma ótima ideia, certo? Até que deixa de ser.

Porque pesquisar mensagens em fluxos funciona tão bem quanto uma porta de tela em um submarino. Spoiler: Não funciona. Tipo, nem um pouco.
Você provavelmente já viu esse erro antes:


Este adorável "NÃO" vermelho é o guardião vigilante dos seus dados. Sempre em serviço, sempre impedindo seus dedos suados de tocar em qualquer coisa sensível. Um verdadeiro protetor! Mas também uma grande dor de cabeça.
O Contra Ataque
Nós não recuamos, porém. Nunca.
Existem algumas soluções possíveis. Eu pessoalmente optei por uma com armazenamento limitado porque não quero manter dados extras armazenados. Eu só quero ficar dentro do reino das mensagens de produção.
Então, aqui está o plano:
Nós criamos uma classe de mensagem personalizada, herdando de EnsLib.HTTP.GenericMessage. Algo assim:
Class Production.Message.ZooMessage Extends EnsLib.HTTP.GenericMessage
{
Property RequestJSON As %String(MAXLEN = "")
Property CaseId As %String
Index ZooMessageCaseIdIndex On CaseId
}
Em seguida, precisamos passar esta mensagem personalizada para a operação e incluir dados adicionais prontos para pesquisa (corpo da mensagem e número do caso).
Solução 1: O "Começo Não Tão Bom"
Criamos um serviço herdando de EnsLib.REST.GenericService, e então o adicionamos à produção. Simples, certo?
Class Production.Service.ZooREST Extends EnsLib.REST.GenericService
{
Parameter DOCCLASS = "Production.Message.ZooMessage"
}
Produção:
<Item Name="Service.RESTver1" Category="" ClassName="Production.Service.ZooREST">
<Setting Target="Host" Name="TargetConfigName">Operation.RESTver1</Setting>
<Setting Target="Adapter" Name="Port">1984</Setting>
</Item>
Exceto que não é.

O tipo de mensagem de entrada permanece o mesmo. O parâmetro DOCCLASS = "Production.Message.ZooMessage" não funcionou.
Solução 2: "Gente Demais Metendo a Colher"
Acontece que o problema se resume a esta única linha de código no método OnProcessInput:

Substituindo por:
Set tRequest=$classmethod(..#DOCCLASS,"%New",pRequestBody,,pRequestBody)
.png)
...resolveria o problema. Mas essa mudança tornaria o código do fornecedor inútil em atualizações futuras do IRIS. Uma opção sem saída que deixa um gosto ruim na boca.

Solução 3: O "Caminho Guardado por um Dragão"
A ideia? Passar a mensagem para um roteador, transformá-la e enviá-la para o processo.
Componentes necessários:
- Um roteador
- Uma transformação
- Uma pitada de algo misterioso e arcano
Class Production.Rule.Router Extends Ens.Rule.Definition
{
XData RuleDefinition [ XMLNamespace = "http://www.intersystems.com/rule" ]
{
<ruleDefinition alias="" context="EnsLib.MsgRouter.RoutingEngine" production="Production.Test">
<ruleSet name="ZOO Router" effectiveBegin="" effectiveEnd="">
<rule name="ZOO Process Inbound Http" disabled="false">
<constraint name="source" value="Service.RESTver3"></constraint>
<when condition="1">
<send transform="Production.DataTransformation.ZOO" target="Operation.RESTver3"></send>
<return></return>
</when>
</rule>
</ruleSet>
</ruleDefinition>
}
}
Class Production.DataTransformation.ZOO Extends Ens.DataTransformDTL [ DependsOn = (EnsLib.HTTP.GenericMessage, Production.Message.ZooMessage) ]
{
Parameter IGNOREMISSINGSOURCE = 1
Parameter REPORTERRORS = 1
Parameter TREATEMPTYREPEATINGFIELDASNULL = 0
XData DTL [ XMLNamespace = "http://www.intersystems.com/dtl" ]
{
<transform sourceClass='EnsLib.HTTP.GenericMessage' targetClass='Production.Message.ZooMessage' create='new' language='objectscript' >
<assign value='source.HTTPHeaders' property='target.HTTPHeaders' action='set' />
<assign value='source.Stream.Read(1000000)' property='target.RequestJSON' action='set' />
<assign value='{}.%FromJSON(source.Stream).case' property='target.CaseId' action='set' />
</transform>
}
}
Um pouco mais volumoso, sim, mas funciona. Sem necessidade de danças rituais.


O Veredito?
Honestamente, não consigo decidir. É por isso que estou escrevendo isso.
Então, aqui está uma pergunta para você:
- Devemos implorar à Intersystems para que eles consertem o código?
- Consertar nós mesmos com ferramentas enferrujadas e ética questionável?
- Aceitar o status quo atual e construir algo desajeitado, mas funcional?
- ?
A decisão é sua.
PS: O código dos exemplos acima está disponível neste repositório GitHub:https://github.com/banksiaglobal/http-rest-production