---
title: Serviço de histórico
tags: Análise Cloud
---
# Serviço de histórico
A ideia é criar um serviço para persistr o histórico de todos os campos, unindo os campos standards e os personalizados.
Uma request quando chega no heimdall é gerado um id pra ela para podermos identifica-la em qualquer ponto, esse id é passado para as requests internas que fazemos tbm. Sendo assim podemos utilizar esse id para unir os dados de históricos dos serviços standards e do btb.
Basicamente cada serviço fica responsavel por fazer a diff de seus dados e enviar ao serviço de histórico passando o request id que gerou essas diffs, o serviço de histórico por sua vez une todas as diffs que chegarem para a mesma request id.
## Base de dados
``` sql
CREATE TABLE revision (
id uuid NOT NULL,
request_id uuid NOT NULL,
"date" timestamptz NOT NULL,
user_id uuid NOT NULL,
user_name varchar(255) NOT NULL,
system_version varchar(64) NOT NULL,
history_type varchar(20) NOT NULL,
origin varchar(20) NOT NULL,
"version" int4 NULL,
updated_at timestamptz NOT NULL,
created_at timestamptz NOT NULL,
external_id varchar(255) NULL,
PRIMARY KEY (id)
);
CREATE TABLE entity_state (
id uuid NOT NULL,
"version" int4 NULL,
external_id varchar NULL,
revision_id uuid NOT NULL,
previous_entity_state_id uuid NULL,
sequence_record_changing int4 NOT NULL,
service varchar(20) NOT NULL,
event_type varchar(20) NOT NULL,
entity varchar(100) NOT NULL,
record_id uuid NOT NULL,
record_text_identifier varchar(255) NOT NULL,
state jsonb NOT NULL,
parent_id uuid NULL,
parent_name varchar(100) NULL,
updated_at timestamptz NOT NULL,
created_at timestamptz NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (previous_entity_state_id) REFERENCES entity_state(id)
ON UPDATE RESTRICT
ON DELETE RESTRICT,
FOREIGN KEY (revision_id) REFERENCES revision(id)
ON UPDATE RESTRICT
ON DELETE RESTRICT
);
CREATE TABLE history_comment (
id uuid NOT NULL,
"comment" varchar(4000) NOT NULL,
record_id uuid NOT NULL,
"version" int4 NULL,
updated_at timestamptz NOT NULL,
created_at timestamptz NOT NULL,
external_id varchar(255) NULL,
service varchar(20) NOT NULL,
entity varchar(80) NOT NULL,
revision_id uuid NOT NULL,
deleted bool NOT NULL DEFAULT false,
PRIMARY KEY (id),
FOREIGN KEY (revision_id) REFERENCES revision(id)
);
CREATE TABLE history_system_event (
id uuid NOT NULL,
revision_id uuid NOT NULL,
event varchar(80) NULL,
event_type varchar(40) NOT NULL,
event_args jsonb,
message varchar(255),
record_id uuid NOT NULL,
service varchar(20) NOT NULL,
entity varchar(80) NOT NULL,
"version" int4 NULL,
updated_at timestamptz NOT NULL,
created_at timestamptz NOT NULL,
external_id varchar(255) NULL,
PRIMARY KEY (id),
FOREIGN KEY (revision_id) REFERENCES revision(id)
ON UPDATE RESTRICT
ON DELETE RESTRICT
);
```
## API
### Fluxo
```mermaid
sequenceDiagram
participant Heimdall
participant Router
participant Customer
participant BTB
participant Mensageria
participant Historic
Heimdall->>Router: Adiciona request id
Router->>Customer: Chama serviço standard
Customer->>Customer: Recebe dados standards, gera o diff deles e persiste no banco local
Customer->>Mensageria: Envia mensagem com o id do registro de histórico que deve ser consultado
Router->>BTB: Chama o btb
BTB->>BTB: Recebe dados personalizados, gera o diff deles e persiste no banco local
BTB->>Mensageria: Envia mensagem com o id do registro de histórico que deve ser consultado
Historic->>Mensageria: Consulta mensagns a serem processadas
Historic->>Customer: Consulta registro de histórico com o id passado na mensagem
Historic->>Historic: Persiste o registro de histórico cos campos standards
Historic->>BTB: Consulta registro de histórico com o id passado na mensagem
Historic->>Historic: Atualiza o registro de histórico dos campos standards fazendo merge com os campos customizados
```
### Post de histórico
*/histories/{service}/{entity}/*
```jsonql=
{
"revision": {
"requestId": "",
"date": "",
"userId": "",
"userName": "",
"systemVersion": "",
"historyType": "",
"origin": "",
"entityStaties": [{
"externalId": "",
"revisionId": "",
"previousEntityStateId": "",
"sequenceRecordChanging": "",
"eventType": "",
"recordId": "",
"recordTextIdentifier": "",
"state": {},
"parentId": "",
"parentName": "",
}]
}
```
Ao receber esses dados deve ser verificado se ja existe uma revisão para o registro, caso não exista deve ser persistido os registros, caso contrário deve ser apenas mergeado o state unindo os dados.
Para verificar se um registro existe deve ser utilizado as seguinte informações:
* requestId
* service
* entity
* recordId
### Post de comentários
Comentários geram uma revisão própria e são vinculados à uma entidade através de seu Id
*/comments/{service}/{entity}/{recordId}*
```jsonql=
{
"historyComment": {
"comment": "Este é um exemplo de comentário de oportunidade."
}
}
```
### Get
Lista todos os acontecimentos relacionados à um entidade específica, estes acontecimentos são:
- Auditorias
- Comentários
- Eventos de Sistema
*/histories/{service}/{entity}/{recordId}*
```jsonql=
{
"items": [
{
"user": {
"id": "27801f26-9bef-4bc1-b5bc-ee922499dd59",
"name": "Administrador"
},
"date": "2019-01-11T20:14:23.503Z",
"historyType": "AUDIT"
}
],
"count": 1,
"firstRow": 0,
"page": 0,
"pageSize":1
}
```
## Audit
A proposta é alterar a lib existente [audit](https://gitlab.wssim.com.br/cloud/audit) hoje para que ao invés de persistir os registros essa lib deve gerar as mensagens com as diffs para que o serviço de histórico consuma e persista.
Além disso parte do que essa lib faz hoje o serviço de histórico que irá fornecer tirando essas responsabilidades da lib, sendo elas:
* End point de comentários (que hoje fica em [Histories](https://gitlab.wssim.com.br/cloud/audit#gerando-coment%C3%A1rios))
* End point de pesquisa ([Search](https://gitlab.wssim.com.br/cloud/audit#filtros))
### End-points para accesso do histórico
Fica como responsabilidade do audit expor end-point que seja possivel configurar (via desenvolvimento) e expor para acesso do usuario os registros do histório
### Sync
Para registros que venham de mobile o histórico deve ser gerado a partir da sync. Para esses casos o id da sync deve ser utilizado como request id ja que os serviços são sincronizados na mesma request.
Comentários podem ser criados no mobile e sincronizados normalmente.
A sync deve ser feita a partir do serviço da entidade, ou seja, vai ser um proxy para o histórico. Isso para poder ser aplicado os fitros corretos de sincronização.
## Serviços standards
Os serviços deverão implementar a lib audit que fará a auditoria e enviará os dados para o serviço de histórico.
Alem de servirem como proxy para manipular comentários e consultar os resgistros de histórico.
### Telas
As telas ficam por responsabilidade de cada serviço implementar e exibir os registros de histórico da melhor forma para o contexto de cada funcionalidade.
Atualmente existe um componente responsavel por fazer isso. Esse componente deve ser alterado para possibilitar a exibição de campos personalizados.
Hoje esse componente somente internacionaliza os nomes dos campos conforme passado para ele, ele deve passar a verificar se é um campo que standard e nesse caso internacionalizar, caso contrario assumir o label passado para ele.
### Serviços com histórico ja implementados
Será nescessário replicar todos os registros. Como as entidades são basicamente a mesma não deve ser um problema porém deve-se tomar cuidado para migrar a qual serviço pertence o registro.
## BTB
No primeiro momento o BTB vai gerar apenas histórico do data lake de entidade standards, ou seja, não será gerado histórico de alteração de metada dados e nem histórico de entidades customs.
Para isso o btb irá enviar as alterações de data lake utilizando o serviço e nome da entidade standard.
O BTB irá utilizar uma lib nossa pra fazer a diff do JSON, após isso iremos converter o resultado retornado dessa lib na estrutura esperada pelo Javers e persistir. A partir desse ponto segue o mesmo fluxo que serviços standards, ou seja, gera uma mensagem para o serviço centralizador consumir.