Histórico da Página
...
- Esquema de autenticação integrado com o Fluig Identity para Tenants e usuários da API de administração (utilizando JWT);
- Base de dados Multi-Tenant para armazenamento de mensagens de Insights provenientes do Big-Query Carol;
- Tabela unificada de armazenamento de Modelos de Insights;
- Provisionamento em real-time de novos schemas para recém adicionados Tenants;
- APIs seguras de gerenciamento de Provisionamento e controle de Mensagens de Insights;
- Novo sistema de mensageria capaz de processar requisições de Insights Online;
- Melhor visibilidade nos recursos utilizados por cada Tenant, devido ao banco de dados multi-esquema;
04. Backend ADVPL
Estrutura Atual
Esta atual estrutura de Insights desenvolvida para o cliente Protheus, tem se provado pouco eficiente no tratamento de mensagens on-line e pouco resiliente no tratamento de exceções quando o processamento de mensagens de Insights.
Um outro ponto de atenção é o desempenho no recebimento de mensagens e a execução do processamento da Regra de Negócio do Insight na mesma Thread de recebimento da mensagem, o que impossibilita o Smartlink de processar novas mensagens enquanto as Regras para a atual ainda estiver processando, causando um congestionamento na liberação da fila em momentos de muita demanda.
A seguir serão apresentados alguns pontos que fez parte do aprendizado com a implementação desta estrutura:
- Congestionamento de Fila: Como mencionado anteriormente, a execução de Regras de Negócio de Insights na mesma thread de recebimento da mensagem causa atraso no recebimento de novas mensagens o que torna inviável a utilização desta estrutura em ambientes de alta demanda/disponibilidade;
- Flexibilidade de Dados: Quando utilizada a definição de "criação de uma tabela por Insight", o processo de desenvolvimento de novos Insights torna-se lento e dependente de janelas específicas de release que estão fora do controle da equipe;
- Complexidade do Desenvolvimento: Novos insights tornam-se cada vez mais complexos de serem desenvolvidos devido a certas limitações apresentadas pela inflexibilidade de dados;
- Desempenho Insatisfatório para Insights Online: O congestionamento de Fila torna o custo de tempo para uma resposta de insights online praticamente inviável e pouco performático (como por exemplo o Insight Financeiro de Relaótio de Fluxo de Caixa);
- Limitação de Front-End (Angular App): Os atuais aplicativos utilizando Angular/PO-UI estão utilizando o mecanismo de websocket WebChannel para comunicação com a thread protheus, isto inviabiliza certas funcionalidades como por exemplo paginação de payload de resposta do endpoint;
Estrutura Proposta
A estrutura proposta visa implementar um sistema mais eficiente no recebimento de mensagens de Insights, mais resiliente a falhas e transparente durante o processo desde o início até sua conclusão.
A seguir será apresentado um resumo do funcionamento desta estrutura:
Recebimento e Agendamento de Processamento de Mensagens (Thread A)
Durante o recebimento de uma nova mensagem de insight (InsightModel), o processo "InsightModels Message Consumer" será responsável por fazer uma breve validação estrutural da mensagem e gravar o recebimento de nova mensagem, ou atualização de antiga mensagem na tabela I19 e, em seguida, delegará para o "Agendador de Processamento de Insight" a responsabilidade de direcionar para o local de execução desta mensagem, utilizando o tipo de Modelo de Insight recebido será adquirida a configuração de Insight (tabela I20) para o tipo de Modelo e última versão ativa.
Esta configuração define se o Insight possui prioridade comum de execução ou trata-se de um insight prioritário:
Prioridade Comum: Insights de prioridade comum serão agendados utilizando a ferramenta de "Gerenciamento de Tarefas" disponibilizada pelo Totvs Framework e o processo do Agendador será finalizado;
Insight Prioritário: Insights Prioritários devem ser executados no momento de seu recebimento, o "Agendador de Processamento de Insight" não agendará este insight do modo convencional, ele executará uma nova thread delegando para o "Executor de Mensagens de Insights" a execução. Como esta chamada de uma nova thread não depende de uma resposta de retorno, o processo do Agendador pode ser finalizado;
Após a finalização desta decisão, o processamento da mensagem será concluído, retornando assim um reconhecimento de recebimento da mensagem para o SmartLink, removendo a mensagem da fila e disponibilizando o Consumer para recebimento da próxima mensagem.
Execução de Mensagens de Insight (Thread B):
Quando solicitada a execução de uma mensagem de Insight, o ID da mensagem (tabela I19), bem como sua configuração (tabela I20) deverão ser informados para o "Executor de Mensagens de Insight".
Este então será o responsável por instanciar a classe de Regra de Negócios informada na configuração do tipo de modelo de Insight (tabela I20) e iniciar o processamento chamando as funções definidas pela classe de interface que toda classe de Regra de Negócios de Insights deve implementar.
Recomenda-se a utilização de uma rotina em TLPP para desenvolvimento da classe de Regra de Negócio e a utilização do NAMESPACE totvs.protheus.backoffice.ba.insights para então implementar a interface InsightsProcess.
Os métodos a serem implementados deverão ser os seguintes:
Bloco de código |
---|
Public Method ProcessInsight(oInsightMessage As Object) As Logical
Public Method GetKey() As Character
Public Method GetFilter() As Character
Public Method GetDateFrom() As Date
Public Method GetDateTo() As Date |
Um exemplo simples de implementação de uma classe de Regra de Negócios de Insights utilizando a tabela de Insights Unificada (I21)
Bloco de código |
---|
#INCLUDE "tlpp-core.th"
#include 'totvs.ch'
NAMESPACE defina.seu.namespace
USING NAMESPACE totvs.protheus.backoffice.ba.insights
Class SimpleInsightProcess From InsightsProcess
Public Data oJsonPayload As Object
Public Method New() Constructor
// Overrides
Public Method ProcessInsight(oInsightMessage As Object) As Logical
Public Method GetKey() As Character
Public Method GetFilter() As Character
Public Method GetDateFrom() As Date
Public Method GetDateTo() As Date
EndClass
Method New() Class PermissionAlertsProcess
_Super:New()
Return Self
Method ProcessInsight(oInsightMessage As Object) As Logical Class PermissionAlertsProcess
Local lProcessOk As Logical
Local oException As Object
Local oInsightEntry As Object
Local xJsonParse As Variant
Local lReprocess As Logical
_Super:ProcessInsight(oInsightMessage)
Try
// Extrai o payload da mensagem e aloca o atributo oJsonPayload
// para futura utilizacao em outras funcoes que serao executadas
::oJsonPayload := JsonObject():New()
xJsonParse := ::oJsonPayload:FromJson(oInsightMessage:cMsgPayload)
// Atualiza mensagem de insight (tabela I19) com a informação de início de processamento
oInsightMessage:UpdateProc("Processamneto de insight iniciado", .T., ::oInsightConfig:cVersao)
// Inicia uma nova linha de insight (tabela I21)
oInsightEntry := InsightEntry():New()
oInsightEntry:cMsgUuid := ::oInsightMessage:cMsgUuid
oInsightEntry:cInsightName:= ::oInsightMessage:cMsgInsight
oInsightEntry:cModulo := cModulo
oInsightEntry:cPayload := ::oJsonPayload:toJson()
oInsightEntry:cDtProcess := FWTIMESTAMP(5)
oInsightEntry:cVersaoProcess := ::oInsightConfig:cVersao
// Calcula o campo key (I21_KEY) - Opcional
If ::oInsightConfig:lCalcKey
oInsightEntry:cKey := ::GetKey()
EndIf
// Calcula o campo key (I21_FILTER) - Opcional
If ::oInsightConfig:lCalcFilter
oInsightEntry:cFilter := ::GetFilter()
EndIf
// Retorna as datas referente aos campos I21_DTDE e I21_DTATE - Opcional
oInsightEntry:dDataDe := ::GetDateFrom()
oInsightEntry:dDataAte := ::GetDateTo()
// Insere a linha da I21 na tabela
oInsightEntry:Insert(lReprocess)
oInsightMessage:UpdateProc("Processamneto de insight finalizado", .T., ::oInsightConfig:cVersao)
lProcessOk := .T.
Catch oException
lProcessOk := .F.
// Caso exista alguma excecao no processamento, informa na tabela I19 o erro de processamento
oInsightMessage:UpdateProc("Processamneto de insight finalizado com erro: " + oException:description, .F., ::oInsightConfig:cVersao)
Throw oException
Finally
FreeObj(oInsightEntry)
EndTry
Return lProcessOk
Method GetKey() As Character Class PermissionAlertsProcess
// Retorna um valor caracter que pode ser utilizado para pesquisar o registro por SQL na tabela I21 campo I21_KEY
Local cKey As Character
cKey := ::oJsonPayload["key"]
Return cKey
Method GetFilter() As Character Class PermissionAlertsProcess
// Retorna um valor caracter que pode ser utilizado para filtrar o registro por SQL na tabela I21 campo I21_FILTER
Local cFilter As Character
cFilter := ::oJsonPayload["key"] + ::oJsonPayload["filter"]
Return cFilter
Method GetDateFrom() As Date Class PermissionAlertsProcess
// Retorna um valor do tipo data que pode ser utilizado para pesquisar o registro por SQL na tabela I21 campo I21_DTDE
Return dDataBase
Method GetDateTo() As Date Class PermissionAlertsProcess
// Retorna um valor do tipo data que pode ser utilizado para pesquisar o registro por SQL na tabela I21 campo I21_DTATE
Return StoD(::oJsonPayload["dataAte"])
|
05. Front-End
06. Pipelines Carol
...