Histórico da Página
Índice | ||
---|---|---|
|
01. Apresentação
Este documento técnico tem por objetivo auxiliar os desenvolvedores dos segmentos na criação de classes que "publicam" e/ou "consomem" mensagens através da plataforma Totvs SmartLink.
02. Responsabilidades
O desenvolvimento e manutenção dos publicadores e consumidores de mensagens são de responsabilidade das equipes de segmentos. Os artefatos genéricos que controlam a fila de execução das mensagens são de responsabilidade da equipe de Framework.
03. Implementando um publicador de mensagens
Para que uma classe seja um publicador de mensagens, deve-se atender aos pré-requisitos listados abaixo:
Pré-requisitos
- Criar um projeto (classLibrary .NET) na solution do segmento em questão, com o seguinte padrão de nome: RM.[Segmento].XXX.SmartLink.Service.
- Exemplo: RM.Glb.SGDP.SmartLink.Service.dll
- Adicionar referência para a dll "RM.Lib.SmartLink.dll";
Criar uma classe que receba em seu construtor instâncias das seguintes interfaces:
"IRMSSmartLinkPublisherService": interface de serviço responsável em incluir a mensagem na fila do RM.SmartLink.Client.
"IRMSLogger": serviço usado para incluir logs relacionados à regra de negócio em questão.
Informações Todos os logs adicionados nesse serviço serão gravados automaticamente na tabela "GTotvsLinkLog"
Para publicar uma mensagem na fila do RM.SmartLink.Client, basta chamar o método "AddMessage" da instância de interface "IRMSSmartLinkPublisherService". Os seguinte dados devem ser enviados através de uma classe de parâmetros do tipo "SmartLinkPublisherAddMessageParams":
Propriedade Descrição Command Nome do comando a ser incluído na fila do SmartLink. Ex: SGDPUpdateTenantMetada CorrelatedId Pode ser ser enviado nessa propriedade um identificador (guid) que correlacionam mensagens de envio e resposta. Data Dados da mensagem contendo informações relacionadas ao negócio. Pode ser em qualquer formato (json, xml, etc) desde que o consumidor consiga interpretá-lo.
RouterMessage Rota de envio da mensagem. Será concatenada ao endpoint do serviço do Totvs SmartLink.Server. ex: /api/v1/link/send/SGDPMaskResponse/SGDP
Na versão 12.1.2402, que utiliza api REST para envio de mensagem, o valor do Audience é definido no final do RouterMessage. No caso desse exemplo o Audience é o SGDP.
A partir da versão 12.1.2406 não é necessário passar o RouterMessage como parâmetro pois utiliza o protocolo gRPC para envio de mensagem.Audience Código do TOTVS App específico que irá receber a mensagem.
Para versões 12.1.2406 e acima, que já utiliza o gRPC para envio de mensagem, o Audience deve ser passado por esse parâmetro.
- Diagrama de classes contendo um publicador de mensagem de exemplo:
5. Diagrama de sequência contendo um exemplo do ciclo de vida da inclusão da mensagem "SGDPTenantMetada"
6. Código fonte de exemplo (extraído da classe "GlbSGDPPublisherMessageService" localizada na solution de Globais, projeto "RM.Glb.SGDP.SmartLink.Service". Esse exemplo é para versões a partir da 12.1.2406 que já utiliza o protocolo gRPC.
Bloco de código | ||||||
---|---|---|---|---|---|---|
| ||||||
using RM.Glb.SGDP.SmartLink.Service.Domain;
using RM.Glb.SGDP.SmartLink.Service.Domain.Interfaces;
using RM.Lib.Log;
using RM.Lib.SmartLink.Domain;
using RM.Lib.SmartLink.Domain.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
namespace RM.Glb.SGDP.SmartLink.Service
{
/// <summary>
/// SGDP Publisher Message Service class
/// </summary>
public class GlbSGDPPublisherMessageService : IGlbSGDPPublisherMessageService
{
private readonly IGlbSGDPResolverService _sgdpResolverService;
private readonly IRMSSmartLinkPublisherService _smartLinkPublisherService;
private readonly IRMSLogger _logService;
private const string ctSGDPAudience = "SGDP"; // <-- SEU CÓDIGO DE AUDIENCE DEVE VIR AQUI. NO CASO DESSE EXEMPLO É SGDP. OBTER O CÓDIGO COM A EQUIPE DE TOTVS APPS.
private const string ctSGDPUpdateTenantMetadata = "SGDPUpdateTenantMetadata";
private const string ctSGDPDataCommand = "SGDPDataCommand";
private const string ctSGDPResponseDataCommand = "SGDPDataResponse";
private const string ctSGDPMaskCommand = "SGDPMaskCommand";
private const string ctSGDPResponseMaskCommand = "SGDPMaskResponse";
private const string ctSGDPLogsCommand = "SGDPLogsCommand";
private const string ctSGDPResponseLogCommand = "SGDPLogsResponse";
private const string ctSmartLinkSetupCommand = "setup";
private const string ctSmartLinkUnSetupCommand = "unSetup";
/// <summary>
/// Constructor
/// </summary>
/// <param name="smartLinkPublisherService"></param>
/// <param name="sgdpResolverService"></param>
/// <param name="logService"></param>
public GlbSGDPPublisherMessageService(IRMSSmartLinkPublisherService smartLinkPublisherService,
IGlbSGDPResolverService sgdpResolverService,
IRMSLogger logService)
{
_smartLinkPublisherService = smartLinkPublisherService;
_sgdpResolverService = sgdpResolverService;
_logService = logService;
}
/// <summary>
/// Adiciona uma mensagem de reposta para o comando "SGDPResponseDataCommand".
/// </summary>
/// <param name="parms"></param>
public void AddResponseDataCommand(AddResponseDataCommandParms parms)
{
SmartLinkPublisherAddMessageParams parPublisher = new SmartLinkPublisherAddMessageParams
{
Command = ctSGDPResponseDataCommand,
CorrelatedId = parms.CorrelatedId,
Data = parms.Message,
Audience = ctSGDPAudience
};
_logService.NotifyLogInfo(Properties.Resources.sconTotvsAppSGDPResponseDataCommandGravadoNaFila);
_smartLinkPublisherService.AddMessage(parPublisher);
}
/// <summary>
/// Adiciona uma mensagem de reposta para o comando "SGDPResponseMaskCommand".
/// </summary>
/// <param name="parms"></param>
public void AddResponseMaskCommand(AddResponseMaskCommandParms parms)
{
SmartLinkPublisherAddMessageParams parPublisher = new SmartLinkPublisherAddMessageParams
{
Command = ctSGDPResponseMaskCommand,
CorrelatedId = parms.CorrelatedId,
Data = parms.Message,
Audience = ctSGDPAudience
};
_logService.NotifyLogInfo(Properties.Resources.sconTotvsAppSGDPResponseMaskCommandGravadoNaFila);
_smartLinkPublisherService.AddMessage(parPublisher);
}
/// <summary>
/// Adiciona uma mensagem de reposta para o comando "SGDPResponseLogCommand".
/// </summary>
/// <param name="parms">Parms</param>
public void AddResponseLogCommand(AddResponseLogCommandParms parms)
{
SmartLinkPublisherAddMessageParams parPublisher = new SmartLinkPublisherAddMessageParams
{
Command = ctSGDPResponseLogCommand,
CorrelatedId = parms.CorrelatedId,
Data = parms.Message,
Audience = ctSGDPAudience
};
_logService.NotifyLogInfo(Properties.Resources.sconTotvsAppSGDPResponseLogCommandGravadoNaFila);
_smartLinkPublisherService.AddMessage(parPublisher);
}
/// <summary>
/// Adiciona uma mensagem para envio de um comando de sgldpdateapplicationmetada.
/// </summary>
/// <param name="parms"></param>
public void AddMessageUpdateTenantMetadata(AddMessageUpdateTenantMetadataParms parms)
{
try
{
if (string.IsNullOrEmpty(parms.TenantId))
{
_logService.NotifyLogWarning(Properties.Resources.sSGDPTenantMetadataInvalidSGDPUpdateTenantMetadata);
return;
}
List<string> jsons = GetUpdateTenandMetadata(parms.TenantId);
foreach (string json in jsons)
{
SmartLinkPublisherAddMessageParams smartLinkParms = new SmartLinkPublisherAddMessageParams
{
Command = ctSGDPUpdateTenantMetadata,
CorrelatedId = "",
Data = json,
Audience = ctSGDPAudience
};
_logService.NotifyLogInfo(Properties.Resources.sconTotvsAppSGDPTenantMetadaGravadoNaFila);
_smartLinkPublisherService.AddMessage(smartLinkParms);
}
}
catch (Exception ex)
{
_logService.NotifyLogWarning(ex, Properties.Resources.sconTotvsAppErroAoEnviarSGDPUpdateTenantMetadata);
}
}
private List<string> GetUpdateTenandMetadata(string tenantId)
{
return _sgdpResolverService.GetSGDPTenantMetadata(
new MetadataTenantParms() { TenantId = tenantId }
)?.JsonsResult;
}
/// <summary>
/// Adiciona mensagem UnSetup
/// </summary>
public void AddMessageUnSetup()
{
var pendingMessages = _smartLinkPublisherService.GetPendingMessages();
var messagesSGDP =
pendingMessages?.Where(y => y.TypeEvent.ToUpper() == ctSGDPUpdateTenantMetadata.ToUpper() &&
y.TypeEvent.ToUpper() == ctSGDPDataCommand.ToUpper() &&
y.TypeEvent.ToUpper() == ctSGDPMaskCommand.ToUpper() &&
y.TypeEvent.ToUpper() == ctSGDPLogsCommand.ToUpper() &&
y.TypeEvent.ToUpper() == ctSGDPResponseDataCommand.ToUpper() &&
y.TypeEvent.ToUpper() == ctSGDPResponseMaskCommand.ToUpper()).ToList();
if (messagesSGDP != null)
{
foreach (SmartLinkMessageEntity model in messagesSGDP)
{
_smartLinkPublisherService.RemoveMessageById(model.Id);
}
}
SmartLinkPublisherAddMessageParams parms = new SmartLinkPublisherAddMessageParams
{
Command = ctSmartLinkUnSetupCommand,
CorrelatedId = "",
Audience = ctSGDPAudience,
Data = _sgdpResolverService.GetSGDPSetup().JsonResult
};
_logService.NotifyLogInfo(Properties.Resources.sconTotvsAppUnSetupGravadoNaFila);
_smartLinkPublisherService.AddMessage(parms);
}
/// <summary>
/// Adiciona messagem setup
/// </summary>
public void AddMessageSetup()
{
SmartLinkPublisherAddMessageParams parms = new SmartLinkPublisherAddMessageParams
{
Command = ctSmartLinkSetupCommand,
CorrelatedId = "",
Audience = ctSGDPAudience,
Data = _sgdpResolverService.GetSGDPSetup().JsonResult
};
_logService.NotifyLogInfo(Properties.Resources.sconTotvsAppSetupGravadoNaFila);
_smartLinkPublisherService.AddMessage(parms);
}
}
} |
7. Código fonte de exemplo (extraído da classe "GlbSGDPPublisherMessageService" localizada na solution de Globais, projeto "RM.Glb.SGDP.SmartLink.Service". Esse exemplo é para a versão 12.1.2402 que ainda utiliza api REST para envio de mensagem. Nesse caso o Audience é definido no final do endpoint passado como parâmetro para o RouterMessage.
Bloco de código | ||||||
---|---|---|---|---|---|---|
| ||||||
using RM.Glb.SGDP.SmartLink.Service.Domain;
using RM.Glb.SGDP.SmartLink.Service.Domain.Interfaces;
using RM.Lib.Log;
using RM.Lib.SmartLink.Domain;
using RM.Lib.SmartLink.Domain.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
namespace RM.Glb.SGDP.SmartLink.Service
{
public class GlbSGDPPublisherMessageService : IGlbSGDPPublisherMessageService
{
private readonly IGlbSGDPResolverService _sgdpResolverService;
private readonly IRMSSmartLinkPublisherService _smartLinkPublisherService;
private readonly IRMSLogger _logService;
private const string ctSGDPUpdateTenantMetadataEndPoint = "/api/v1/link/send/SGDPUpdateTenantMetadata/SGDP";
private const string ctSGDPDataResponseEndPoint = "/api/v1/link/send/SGDPDataResponse/SGDP";
private const string ctSGDPUpdateTenantMetadata = "SGDPUpdateTenantMetadata";
private const string ctSGDPDataCommand = "SGDPDataCommand";
private const string ctSGDPResponseDataCommand = "SGDPDataResponse";
private const string ctSGDPMaskResponseEndPoint = "/api/v1/link/send/SGDPMaskResponse/SGDP";
private const string ctSGDPMaskCommand = "SGDPMaskCommand";
private const string ctSGDPResponseMaskCommand = "SGDPMaskResponse";
private const string ctSGDPLogResponseEndPoint = "/api/v1/link/send/SGDPLogsResponse/SGDP";
private const string ctSGDPLogsCommand = "SGDPLogsCommand";
private const string ctSGDPResponseLogCommand = "SGDPLogsResponse";
private const string ctSmartLinkSetupCommand = "setup";
private const string ctSmartLinkUnSetupCommand = "unSetup";
public GlbSGDPPublisherMessageService(IRMSSmartLinkPublisherService smartLinkPublisherService,
IGlbSGDPResolverService sgdpResolverService,
IRMSLogger logService)
{
_smartLinkPublisherService = smartLinkPublisherService;
_sgdpResolverService = sgdpResolverService;
_logService = logService;
}
/// <summary>
/// Adiciona uma mensagem de reposta para o comando "SGDPResponseDataCommand".
/// </summary>
/// <param name="parms"></param>
public void AddResponseDataCommand(AddResponseDataCommandParms parms)
{
SmartLinkPublisherAddMessageParams parPublisher = new SmartLinkPublisherAddMessageParams
{
Command = ctSGDPResponseDataCommand,
CorrelatedId = parms.CorrelatedId,
Data = parms.Message,
RouterMessage = ctSGDPDataResponseEndPoint
};
_logService.NotifyLogInfo(Properties.Resources.sconTotvsAppSGDPResponseDataCommandGravadoNaFila);
_smartLinkPublisherService.AddMessage(parPublisher);
}
/// <summary>
/// Adiciona uma mensagem de reposta para o comando "SGDPResponseMaskCommand".
/// </summary>
/// <param name="parms"></param>
public void AddResponseMaskCommand(AddResponseMaskCommandParms parms)
{
SmartLinkPublisherAddMessageParams parPublisher = new SmartLinkPublisherAddMessageParams
{
Command = ctSGDPResponseMaskCommand,
CorrelatedId = parms.CorrelatedId,
Data = parms.Message,
RouterMessage = ctSGDPMaskResponseEndPoint
};
_logService.NotifyLogInfo(Properties.Resources.sconTotvsAppSGDPResponseMaskCommandGravadoNaFila);
_smartLinkPublisherService.AddMessage(parPublisher);
}
/// <summary>
/// Adiciona uma mensagem de reposta para o comando "SGDPResponseLogCommand".
/// </summary>
/// <param name="parms">Parms</param>
public void AddResponseLogCommand(AddResponseLogCommandParms parms)
{
SmartLinkPublisherAddMessageParams parPublisher = new SmartLinkPublisherAddMessageParams
{
Command = ctSGDPResponseLogCommand,
CorrelatedId = parms.CorrelatedId,
Data = parms.Message,
RouterMessage = ctSGDPLogResponseEndPoint
};
_logService.NotifyLogInfo(Properties.Resources.sconTotvsAppSGDPResponseLogCommandGravadoNaFila);
_smartLinkPublisherService.AddMessage(parPublisher);
}
/// <summary>
/// Adiciona uma mensagem para envio de um comando de sgldpdateapplicationmetada.
/// </summary>
public void AddMessageUpdateTenantMetadata(AddMessageUpdateTenantMetadataParms parms)
{
try
{
if(string.IsNullOrEmpty(parms.TenantId))
{
_logService.NotifyLogWarning(Properties.Resources.sSGDPTenantMetadataInvalidSGDPUpdateTenantMetadata);
return;
}
List<string> jsons = GetUpdateTenandMetadata(parms.TenantId);
foreach (string json in jsons)
{
SmartLinkPublisherAddMessageParams smartLinkParms = new SmartLinkPublisherAddMessageParams
{
Command = ctSGDPUpdateTenantMetadata,
CorrelatedId = "",
Data = json,
RouterMessage = ctSGDPUpdateTenantMetadataEndPoint
};
_logService.NotifyLogInfo(Properties.Resources.sconTotvsAppSGDPTenantMetadaGravadoNaFila);
_smartLinkPublisherService.AddMessage(smartLinkParms);
}
}
catch (Exception ex)
{
_logService.NotifyLogWarning(ex, Properties.Resources.sconTotvsAppErroAoEnviarSGDPUpdateTenantMetadata);
}
}
private List<string> GetUpdateTenandMetadata(string tenantId)
{
return _sgdpResolverService.GetSGDPTenantMetadata(
new MetadataTenantParms() { TenantId = tenantId }
)?.JsonsResult;
}
public void AddMessageUnSetup()
{
var pendingMessages = _smartLinkPublisherService.GetPendingMessages();
var messagesSGDP =
pendingMessages?.Where(y => y.TypeEvent.ToUpper() == ctSGDPUpdateTenantMetadata.ToUpper() &&
y.TypeEvent.ToUpper() == ctSGDPDataCommand.ToUpper() &&
y.TypeEvent.ToUpper() == ctSGDPMaskCommand.ToUpper() &&
y.TypeEvent.ToUpper() == ctSGDPLogsCommand.ToUpper() &&
y.TypeEvent.ToUpper() == ctSGDPResponseDataCommand.ToUpper() &&
y.TypeEvent.ToUpper() == ctSGDPResponseMaskCommand.ToUpper()).ToList();
if (messagesSGDP != null)
{
foreach (SmartLinkMessageEntity model in messagesSGDP)
{
_smartLinkPublisherService.RemoveMessageById(model.Id);
}
}
SmartLinkPublisherAddMessageParams parms = new SmartLinkPublisherAddMessageParams
{
Command = ctSmartLinkUnSetupCommand,
CorrelatedId = "",
Data = _sgdpResolverService.GetSGDPSetup().JsonResult
};
_logService.NotifyLogInfo(Properties.Resources.sconTotvsAppUnSetupGravadoNaFila);
_smartLinkPublisherService.AddMessage(parms);
}
public void AddMessageSetup()
{
SmartLinkPublisherAddMessageParams parms = new SmartLinkPublisherAddMessageParams
{
Command = ctSmartLinkSetupCommand,
CorrelatedId = "",
Data = _sgdpResolverService.GetSGDPSetup().JsonResult
};
_logService.NotifyLogInfo(Properties.Resources.sconTotvsAppSetupGravadoNaFila);
_smartLinkPublisherService.AddMessage(parms);
}
}
} |
04. Implementando um consumidor de mensagens
Para que uma classe seja um consumidor de mensagens no SmartLink, deve-se atender aos pré-requisitos listados abaixo:
Pré-requisitos
- Criar um projeto (classLibrary .NET) na solution do segmento em questão, com o seguinte padrão de nome: RM.[Segmento].XXX.SmartLink.Service.
- Exemplo: RM.Glb.SGDP.SmartLink.Service.dll
- Adicionar referência para a dll "RM.Lib.SmartLink.dll";
Criar uma classe herdando da ancestral "RMSSmartLinkConsumerMessageBase".
- A classe "RMSSmartLinkConsumerMessageBase" herda da classe RMSObject da Lib. Consequentemente, as classes de "consumers" poderão chamar os métodos "CreateFacade" e "CreateModule" dentro de suas estruturas.
Carimbar a classe com o atributo "RMSSmartLinkConsumerMessageAttr". Nesse atributo, devem ser informados os dados abaixo:
Propriedade Descrição Cod.Sistema Identificador da aplicação Comando Nome do Comando da mensagem - Para realização de tratamento de exceções no caso de ocorrer erro no processamento da mensagem
Quando for considerado um erro e um nova tentativa de processamento deve ser realizada:
A classe RMSSmartLinkConsumerMessageException ou outra, pode ser utilizada.
Neste caso a mensagem será reenfileirada e novas tentativas de processamento serão realizadas.
Sendo considerado que a mensagem deve ser descartada, ou seja, esta mensagem não deve ser processada neste momento ou apenas sob intervenção manual:
A classe RMSSmartLinkConsumerFatalException, deverá ser utilizada e informado o motivo.
Neste caso a mensagem será colocada em um fila de espera (DLQ) e somente será reprocessada por uma intervenção manual ou será descartada. Código fonte de exemplo (extraído da classe "GlbSGDPConsumerDataCommandMessage" localizada na solution de Globais, projeto "RM.Glb.SGDP.SmartLink.Service":
Bloco de código language c# firstline 1 linenumbers true using RM.Glb.SGDP.SmartLink.Service.Domain.Interfaces; using RM.Lib; using RM.Lib.SmartLink.Domain; using RM.Lib.SmartLink.Domain.Consumer; using RM.Lib.SmartLink.Domain.Interfaces; using RM.Lib.SmartLink.Domain.Publisher; using System; using System.Runtime.Serialization; namespace RM.Glb.SGDP.SmartLink.Service.Domain { /// <summary> /// Regras de implementação do mecanismo de processamento da mensagem SGDDataCommand do SGDP /// </summary> [RMSSmartLinkConsumerMessageAttr(CodSistema.Glb, "SGDPDataCommand")] public class GlbSGDPConsumerDataCommandMessage : RMSSmartLinkConsumerMessageBase { protected override ConsumerMessageExecuteResult DoExecute(string message) { logService.NotifyLogInfo(Properties.Resources.sconTotvsAppInicioExecucaoDoConsumerSGDPDataCommandConsumer); ConsumerMessageExecuteResult result = new ConsumerMessageExecuteResult(); IGlbSGDPResolverService resolver = GlbSGDPResolveFactory.NewSGDPResolve(this.DBS, this.logService); IGlbSGDPPublisherMessageService publisher = new GlbSGDPPublisherMessageService(this.SmartLinkPublisherService, resolver, logService); ExecuteDataCommandParms par = new ExecuteDataCommandParms(); par.Message = message; try { var execDataResult = resolver.ExecuteSGDPDataCommand(par); logService.NotifyLogInfo(Properties.Resources.sconTotvsAppJSonSGDPDataResponseCommandForamGerados, Properties.Resources.sconTotvsAppQuantidadeDeJSonsGerados, execDataResult?.JsonResults?.Count); result.CorrelatedID = execDataResult.RequestId; if (execDataResult?.JsonResults != null) { foreach (var jsonResult in execDataResult.JsonResults) { AddResponseDataCommandParms parResponse = new AddResponseDataCommandParms(); parResponse.Message = jsonResult; parResponse.CorrelatedId = execDataResult.RequestId; publisher.AddResponseDataCommand(parResponse); } } } catch(Exception ex) { logService.NotifyLogError(new GlbSGDPConsumerDataCommandMessageException( Properties.Resources.sconTotvsAppErroAoProcessarSGDDataCommand, ex)); } logService.NotifyLogInfo(Properties.Resources.sconTotvsAppFimExecucaoDoConsumerSGDPDataCommandConsumer); return result; } } [Serializable] public class GlbSGDPConsumerDataCommandMessageException : RMSApplicationException { public GlbSGDPConsumerDataCommandMessageException() : base() { } public GlbSGDPConsumerDataCommandMessageException(string message) : base(message) { } public GlbSGDPConsumerDataCommandMessageException(string message, Exception ex) : base(message, ex, string.Empty) { } public GlbSGDPConsumerDataCommandMessageException(SerializationInfo info, StreamingContext context) : base(info, context) { } } }
05. Diagrama de classes
06. DER
Tabela | |
---|---|
GTOTVSLINKMESSAGE | Tabela utilizada para armazenar todos as mensagens geradas e enviadas para execução pelo SmartLink. Sempre que uma mensagem é executa com sucesso, a linha referente a mensagem é excluída dessa tabela , deixando essa tabela sempre leve. Esse procedimento melhora a performance do processo, visto que vários "updates" são realizados nessa tabela.Quando menor o volume de uma tabela, mais rápido será a operação do update. |
GTOTVSLINKMESSAGEEXEC | Tabela contendo todos os dados de execução de uma determinada mensagem. |
GTOTVSLINKLOG | Tabela contendo todos os logs de execução de uma mensagem. |
CONTEÚDO
- Visão Geral
- Configuração passo a passo
- Assistente de ativação / desativação do processo
- Como Funciona
- Visualização de Log
- Habilitar log TLC
- Mecanismo de execução da integração com o TLC
01. VISÃO GERAL
A partir da versão 12.1.28 é possível realizar a integração do RM com o TOTVS App (Carol).
Neste documento é descrito o processo de configuração da integração.
Informações | ||
---|---|---|
| ||
Para a ativação da integração funcionar corretamente em bases Oracle é necessário ter a versão igual ou superior ao Oracle12.2. |
02. CONFIGURAÇÃO PASSO A PASSO
Existem 2 formas de integrar o RM ambiente com o TOTVS App.
Primeira: Com a ativação baseada no Client Id e Client Secret do RAC. Dessa forma é necessário um ambiente provisionado (RAC ou Carol). Esta é a opção indicada para novas integrações.
Os endereços do TotvsApp devem ser recuperados pelos links abaixo:
- Ambiente Dev = https://endpoint-registry.dev.totvs.app/api/v1/services
- Ambiente Staging = https://endpoint-registry.staging.totvs.app/api/v1/services
- Ambiente Produção = https://endpoint-registry.totvs.app/api/v1/services
Segunda: Com ativação baseada nas credenciais da Carol.
Os passos descritos abaixo, dentro do tópico 2, são necessários apenas se a ativação usar as credenciais da Carol. Para ambientes provisionados (Client Id e Client Secret) o arquivo de configuração e os conceitos serão obtido automaticamente pelo sistema, de acordo com a versão do RM e não é necessário alterar os configs do ambiente.
Configuração do RM.Host.exe.config (Ativação baseada nas credenciais da Carol)
Nos arquivos de configuração do host (RM.Host.exe.config, RM.Host.Service.exe.config), adicione a TAG “FileServerPath”. Essa deverá apontar para um caminho compartilhado na rede, conforme abaixo:
Obs: Em ambiente 3 camadas, essa configuração deve ser realizada nas máquinas JobServer.
Verifique se o serviço do Host possui permissão de leitura nesse caminho compartilhado
Cópia dos arquivos de Conceito
Todos os arquivos de conceito, com extensão “*.concept” disponíveis no projeto, deverão ser copiados para esse diretório compartilhado. O configurador fará automaticamente o download desses arquivos e os mesmos serão gravados na tabela GTOTVSAPPCONCEITO.CONCEITO.
Aviso | ||
---|---|---|
| ||
A partir dos patches 12.1.28.221 e 12.1.29.151 não é necessário deixar os conceitos nesse diretório, pois serão obtidos automaticamente pelo sistema. |
.Arquivo de configuração do projeto
Será disponibilizado um modelo de arquivo de configuração Json do projeto. Esse arquivo deve ter obrigatoriamente o nome de “totvsAppConfig.json”. Ele deve ser copiado para o mesmo caminho de rede descrito acima.
O correto preenchimento do mesmo é muito importante para o funcionamento do processo. Segue abaixo uma explicação de cada item da configuração:
Arquivo exemplo: totvsAppConfig.json.
a) RMVersion: versão do RM (essa opção ainda não está sendo usada pelo processo);
b) ScheduleInfo: informações de periodicidade da execução do job de integração. Conforme exemplo acima, o job será executado de 5 em 5 minutos.
Opções:
• Exemplo de execução mensal: [RecurencyType = “Monthly” | DayOfMonth = 14 | Hour = 10 | Minute = 15]. Nesse caso, o job será executado todo dia 14 de cada mês às 10 horas e 15 minutos;
• Exemplo de execução semanal: [RecurrencyType = “Weekly” | Weekdays = “Monday” | Hour = 14 | Minute = 20]. Nesse caso, o job será executado toda segunda feira, às 14 horas e 20 minutos.
• Exemplo de execução horária: [RecurrencyType = “Hourly” | HoursInterval = 2 | MinutesInterval= 0]. Nesse caso, o job será executado todos os dias de 2 em 2 horas.
c) BusinessDomain: Trata-se de uma lista que contemplará todas as integrações futuras do RM com a plataforma Totvs App. No caso do consignado, iremos criar um único objeto dentro dessa lista:
i. AppId: “1” = identificador do aplicativo consignado (valor = 1);
ii. SoftDeleteTables: informe as tabelas que farão parte do soft delete, ou seja, para cada registro excluído no RM na tabela em questão, será gravada uma informação de log na tabela de softDelete da tabela em questão, EX: ppessoa_softdelete;
iii. UpdaterControlColumns: informe as tabelas que terão todos os registros do campo “RecModifiedOn” sendo atualizados para “1900/1/01” se caso ele for null;
iv. ConceptGroup: Lista contendo os grupos de conceito.
1) GroupName: Nome do grupo (essa opção ainda não está sendo usada pelo processo)
2) Concepts: grupo de conceitos contendo informações dos conceitos que participarão do processo:
a) ConceptID: guid contendo a identificação única do conceito. Com esse atributo, poderemos resolver a situação de um conceito ser utilizado por várias integrações (businessDomain). Daí ele será executado apenas uma única vez. Ex: conceito para exportação de dados da GColigada/GFilial.
b) ConceptFileName: Nome físico do arquivo de conceito “*.concept” gravado no caminho de rede compartilhado. Esse nome tem que ser exatamente igual, contendo a extensão.
ex: "ConceptFileName": "ExportacaoFuncionarios.concept",
c) ConceptVersion: guid representando a versão do arquivo de conceito. Se o conceito sofrer alguma alteração que necessita do mesmo ser baixado novamente, esse guid deverá ser modificado. (essa opção ainda não está sendo usada pelo processo)
d) ProcessingDependency: Ordem de dependência de execução dos conceito. Ou seja, o processo não poderá executar o conceito “A” se o conceito “B” não for executado com sucesso. (essa opção ainda não está sendo usada pelo processo)
03. ASSISTENTE DE ATIVAÇÃO / DESATIVAÇÃO DO PROCESSO
Permissão no item de menu
No RM, acesse a opção “Serviços globais / Perfis / Integração” e forneça as permissões para o perfil do usuário em questão.
Selecione o sistema “Integração / Totvs App / Ativação Totvs App” e verifique se o item de menu está habilitado.
Processo de ativação
Nos patches mais recentes são disponibilizados duas formas de autenticação no ambiente: Credenciais do RAC ou credenciais da Carol. Apenas 1 mecanismo de autenticação deve ser utilizado.
Selecione a opção “Consignado” para ativar o processo de integração. Outras opções de integração serão criadas futuramente.
Na versão 12.1.28 está disponível apenas a integração com o "Consignado". A partir da versão 12.1.29 está disponível também o "Antecipa".
Para configuração das credenciais da Carol:
- Informe o endereço da Carol:
ex: https://totvstechfindev.carol.ai/ - Informe o Id do Connector da Carol:
ex: 09ddb0e29e604e599a1356dab2f89df9 - Informe o token da Carol: Esse token, deverá ser recuperado do ambiente Carol, conforme este link.
Para configuração das credenciais do RAC, os dados da Carol não precisam ser preenchidos, pois o sistema usará a autenticação RAC para buscar as credenciais da Carol.
Novas integrações devem ser configuradas com esse modelo de autenticação.
- Informe o RAC Client Id.
- Informe o RAC Client Secret: Essas informações de autenticação (Client Id, Client Secret) serão enviadas automaticamente para o cliente via e-mail ao ser realizado o provisionamento de seu ambiente na plataforma TotvsApp.
Após execução do processo de ativação, os seguintes procedimentos serão realizados:
- Será gravada uma linha na tabela GTOTVSAPP contendo informações globais da configuração.
- Os conceitos disponíveis no caminho de rede ou obtidos pelo sistema de forma automática e que estão mapeados no arquivo de configuração serão baixados e gravados na tabela “GTOTVSAPPCONCEITO”;
- Será criado um Job agendado e recorrente para execução conforme informações de agendamento disponíveis no arquivo de config;
- As stored Procedures de softDelete serão executadas para as tabelas mapeadas para criação automática das estruturas de softDelete;
- As tabelas mapeadas serão atualizadas na colulna “RECMODIFIEDON” para a data “1900/01/01” em caso de possuir o valor null;
Para cada execução do job de exportação:
- Os conceitos serão executados e os dados serão enviados para Carol conforme definido nos conceitos;
- Será gravada uma linha na tabela “GTOTVSAPPCONCEITOHST” conforme informações de execução de cada conceito (sucesso ou erro e mensagem de erro);
- Em caso de sucesso, a coluna “GTOTVSAPPCONCEITOHST.DATAULTEXEC” será atualizada para a data de início da execução do processo.
- O status da execução pode ser consultado também na coluna “GTOTVSAPPCONCEITOHST.STATUS” (1 - sucesso, 2 - falha, 0 - não executado). E na coluna "GTOTVSAPPCONCEITOHST.MENSAGEM" a mensagem do erro ou de sucesso.
12.1.33
A partir da versão 12.1.33, estará disponível apenas autenticação com as Credenciais do RAC.
Além disso, o processo de ativação irá ativar ou desativar a integração com todos os aplicativos disponíveis. Será necessário clicar no botão "Buscar Apps" antes de avançar com o processo, e será retornado todos os Apps disponíveis na Carol para a integração com ambiente RM.
Caso a integração já esteja ativa e um novo App for disponibilizado (Exemplo: SGDP), não será necessário refazer o processo de ativação.
Aviso | ||
---|---|---|
| ||
Ao clicar para Buscar Apps, serão retornados somente os Apps disponíveis em cada Client Id e Client Secret. |
Aviso | ||
---|---|---|
| ||
Após ativar a integração um serviço de monitoramento da saúde do processo será disparado com o intuito de manter o processo da integração executando de acordo com a configuração de periodicidade. Ver mais em: Serviço De Monitoração Da Saúde Da Integração RM x TOTVS App |
Processo de desativação
Após ativado, o usuário poderá a qualquer momento desativar o processo conforme opção abaixo:
O processo de desativação executará os seguintes procedimentos:
- As informações das tabelas “GTOTVSAPP, GTOTVSAPPCONCEITO, GTOTVSAPPCONCEITOHST e GTOTVSAPPLOG " serão excluídas da base;
- O Job Executor do processo será finalizado e excluído;
- As tabelas de softDelete não serão mais alimentadas com informações de deleção.
Aviso | ||
---|---|---|
| ||
Ao desativar a integração todos os serviços que monitoram a saúde do processo serão finalizados. |
04. Como Funciona
Através da ferramenta de Conceito o RM envia para a Carol (Inteligência artificial da TOTVS) informações chaves baseadas nas configurações dos conceitos de cada integração.
Após a ativação da integração o processo ConTotvsAppActivatorProcess que configura a integração será disparado.
Após a execução do processo que configura a integração será iniciado o processo que Executa a integração ConTotvsAppExecutorProcess.
Aviso | ||
---|---|---|
| ||
Pelo fato da integração ser executada através de processos, os processos ConTotvsAppActivatorProcess e ConTotvsAppExecutorProcess NÃO podem ser manipulados pelo usuário. Os menus Iniciar / Parar / Desabilitar / Reiniciar da visão de gerenciamento de Job's foram desativados. Os WebServices que Executam / Agendam processos também foram bloqueados. A atividade ExecutarProcesso da Fórmula Visual também foi bloqueada para não permitir a execução dos processos citados. |
Caso o ambiente utilizado seja um ambiente 3 Camadas, o processo será recorrente de acordo com a configuração de periodicidade utilizada no arquivo totvsAppConfig.json.
Caso o ambiente utilizado seja um ambiente Local, o processo não será recorrente porém o serviço de monitoramento da saúde do processo irá executar o processo em horários bem próximo da configuração de periodicidade.
Informações | ||
---|---|---|
| ||
Para entender como funciona o serviço de Monitoramento da saúde do processo acesse : https://tdn.totvs.com/x/27EMIg |
05. VISUALIZAÇÃO DE LOG
Na tabela GTOTVSAPPLOG é armazenado o log detalhado de cada execução dos conceitos e envios cadastrados na tabela GTOTVSAPPCONCEITOHST.
Informações relevantes sobre a tabela GTOTVSAPPLOG:
Na coluna Tipo, deve ser considerado:
0 - Mensagem de Sucesso
1 - Mensagem de Alerta
2 - Mensagem de Erro
Caso ocorram erros, as colunas Mensagem e Descrição podem ser consultadas para obter mais detalhes.
Exemplo de mensagens de erro:
Mensagem: Erro ao enviar dados para serviço de api!| {"code":404,"message":"HTTP 404 Not Found"}
Mensagem: Pacote '1' de '1' enviado com erro!|Erro ao enviar dados para serviço de api!| {"code":405,"message":"HTTP 405 Method Not Allowed"}
Para analisar os registros da tabela de log, é importante filtrar a busca pela chave GTOTVSAPPLOG.IDTOTVSAPPCONCEITOHST, relacionada a coluna GTOTVSAPPCONCEITOHST.ID
06. HABILITAR TLS
Em alguns casos é necessário ajustar o TLS do servidor.
Para ajustar basta criar um arquivo com a extensão .Reg e escrever o comando abaixo. Após criar o arquivo basta executar.
Aviso | ||
---|---|---|
| ||
Antes de Executar é importante fazer o backup das todas as chaves descritas no bloco de código. |
Bloco de código |
---|
Windows Registry Editor Version 5.00
; 0x00000008 Habilitar o SSL 2.0 por padrão
; 0x00000020 Habilitar SSL 3.0 por padrão
; 0x00000080 Habilitar TLS 1.0 por padrão
; 0x00000200 Habilita o TLS 1.1 por padrão
; 0x00000800 Habilitar TLS 1.2 por padrão
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\WinHttp]
"DefaultSecureProtocols"=dword:0x00000800
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Internet Settings\WinHttp]
"DefaultSecureProtocols"=dword:0x00000800
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client]
"DisabledByDefault"=dword:00000000
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server]
"DisabledByDefault"=dword:00000000 |
Ferramentas de teste de solução de problemas de conexão SSL / TLS (Totvs App precisa de TLS1.2 handshake)
Existe um troubleshooting da Microsoft abordando diversas formas de se testar a comunicação:
Utilizando CURL
curl -v https://endpoint-registry.dev.totvs.app/api/v1/services --tlsv1.0
curl -v https://endpoint-registry.dev.totvs.app/api/v1/services --ciphers ECDHE-RSA-NULL-SHA --tlsv1.2
Resposta esperada (Sucesso)
07. MECANISMO DE EXECUÇÃO DA INTERGRAÇÃO COM O TLC
O campo "IDJOB" já existente na tabela "GTOTVSAPP" é responsável em fazer a subida dos dados para Carol (busca do RM e envia para Carol).
Com a nova implantação do TLC, após realizar a ativação do TotvsApp, será criado um novo IDJOB na tabela "GTOTVSAPP", mas que estará disponível no novo campo "JOIBIDTLC". Ele é o responsável por enviar mensagens localizadas na tabela "GTOTVSLINKMESSAGE" para o TotvsLinkClient.
A cada exportação realizada com sucesso, o dado das métricas será localizado na tabela "GTOTVSLINKMESSAGE", após o envio das métricas serem realizados com sucesso, os dados serão enviados para a tabela "GTOTVSLINKMESSAGEEXEC" e excluído na tabela "GTOTVSLINKMESSAGE".
Aviso | ||
---|---|---|
| ||
Os dois Jobs criados "IDJOB" e "JOIBIDTLC" não poderão ser desabilitados na tela "Gerenciamento de Jobs" localizado no RM.exe, visto que são Jobs de integração. Os mesmo somente serão desabilitados pelo processo de "Desativação da integração". |
Na tabela "GJOBXEXECUCAO", deve existir dois Jobs recorrentes (de acordo com a configuração de periodicidade utilizada), referentes aos Ids criados no campos "JOBID" e "JOIBIDTLC" da tabela "GTOTVSAPP".
E ao realizar a desativação do processo, o Jobs devem ser desabilitados (status = 8).
As métricas, estão sendo enviadas para o Grafana (Uma aplicação web de análise, onde são fornecidos tabelas, gráficos, etc).
A execução do "JOBIDTLC", fará uma leitura na tabela "GTOTVSLINKMESSAGE" e realizará o envio das métrica para o Grafana.
Segue abaixo o exemplo da visualização das métricas dentro da aplicação:
...