2406
Owned by Sergio Labres
just a moment ago
1 min read
Analytics
Key | Summary | Documentation | |
---|---|---|---|
Erro de RemoteDB ao tentar salvar um consulta personalizada no Person | 1.Menu 2.Objetivo 3.Alteração | ||
. | |||
. | |||
. | |||
. | |||
. | |||
. | |||
. | |||
. | |||
TESTE | |||
Inconsistência » Comportamento indevido ao trabalhar com Nested Dataset na arquitetura TMS | 1.Menu 2.Objetivo 3.Alteração
| ||
. | |||
. | |||
. | |||
1.Menu VsRel - Gerador de relatórios 2.Objetivo 3.Alteração | |||
Criação de Cluster Kubernetes Gerenciado para o Ambiente Dev | . | ||
. | |||
. | |||
. | |||
. | |||
. | |||
RevTelas - Aplicação das novas telas no projeto Agro3c - Parte 4 | . | ||
. | |||
. | |||
. | |||
. | |||
Relatório de Direitos de Acesso listando informações de módulos não filtrados. | 1.Menu 2.Objetivo 3.Alteração | ||
. | |||
. | |||
. | |||
Plugins - Correção do plugin Ficha Cadastral Cliente (TURIM) | 1.Menu Orion → Plugin Ficha Cadastral → Personalizações 2.Objetivo Criar 3 novas branchs do projeto Ficha Cadastral, incluindo as personalizações feitas apenas em arquivos locais no cliente 3.Alteração Na branchs tiveram que ser corrigido alguns SQL que estavam com coalesce que eram aceitos no banco firebird, mas no oracle gerava erro: -- Exemplo de um caso -- Antes COALESCE(CONTAMOVATIVECON.A6HAPLANT, '') AS CULTIVADO, COALESCE(CONTAMOVATIVECON.A6PRODANUALSC, '') AS PRODUTIVIDADE, COALESCE(CONTAMOVATIVECON.A5FATBRUTOANUAL, '') AS VALOR -- Depois COALESCE(CONTAMOVATIVECON.A6HAPLANT, '') AS CULTIVADO, COALESCE(CONTAMOVATIVECON.A6PRODANUALSC, '') AS PRODUTIVIDADE, COALESCE(CONTAMOVATIVECON.A5FATBRUTOANUAL, '') AS VALOR Como o projeto foi migrado do 0 para o Linux, tivemos que adicionar vários endpoints que retornavam o stacktrace para saber o que está dando de errado dentro dos plugins, logo foi adicionado o seguinte código: // Apenas um trecho de uma exception mais genérica que o código pegava // Pegando o stacktrace inserindo em uma string e jogando para o navegador a resposta } catch (Exception e) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); e.printStackTrace(pw); String stackTrace = sw.toString(); throw new Exception("Erro desconhecido ao gerar relatório: " + caminho + "\n" + stackTrace, e); Além de sql, teve que ser alterado algumas formas de caminhos, que são fixas dentro do projeto, como o cliente mudou de servidor de Windows para Linux teve que ser feitas algumas mudanças nesse sentido. // Antes report = "/reports/ficha_cadastral/FichaCadastral.jasper"; // Depois report = "/opt/Orion/webapps/ficha_cadastralothers/WEB-INF/classes/reports/ficha_cadastral/FichaCadastral.jasper"; Foi realizado também a mudanças das imagens dentro do template jasper, pois em todos os templates as imagens estavam com diretórios fixos do servidor Windows do cliente, sendo assim os arquivos .jrxml e .jasper tiveram que ser alterados. A parte do bower_components também não estava sendo extraída dentro do servidor Linux, pelo fato de não estar com o npm instalado, então foi inserido todo o bower_components dentro do próprio .war, sendo que o bower_components foi gerado na minha máquina, para evitar de instalar npm no cliente. Uma das mudanças também foi a mudança de forma de buscar arquivos pois o getResourceAsStream não estava funcionando como esperado, e logo foi trocado para o FileInputStream. // Essa parte do código também estava completamente errada, pois quando um arquivo não é encontrado ele gera um erro // E dessa forma que estava ele validava se era null // Lembrando que esse in se refere ao FileInputStream if (in == null) { throw new Exception("Arquivo do relatorio nao encontrado: " + caminho); } Houve também mudanças no sentido do objdc6 para o ojdbc8, e também a inclusão da nova lib que libera os plugins para se conectarem a https. Essas mudanças foram genericas e aplicadas em ambas as branchs, agora o que geralmente mudava de uma branch para a outra era os templates .jasper, e todos os arquivos que geravam de alguma forma o path que ela iria ser extraida dentro do sistema (Todos os arquivos estão descritos na Descrição) | ||
. | |||
Como definido na tarefa estão sendo enviados e-mails para o Admin e RH, porém pela urgência e característica da demanda esta tarefa será dividida em duas partes. Essa primeira parte está sendo enviado o email para os destinatários desejados, na segunda parte será criada uma página HTML definido um novo layout de envio de e-mails, visto que a biblioteca usada no Consignado precisa que seja criada uma página HTML para envio de e-mail. Neste momento está sendo usada uma página genérica para Admin e RH a segunda parte da tarefa comtempla criar páginas HTML distintas para cada destinatário. | |||
. | |||
. | |||
. | |||
. | |||
1.Menu 2.Objetivo 3.Alteração
| |||
. | |||
1.Menu 2.Objetivo 3.Alteração | |||
. | |||
. | |||
. | |||
IA - Acompanhar e auxiliar desenvolvimento das requisições do Analytics para o serviço de Insights | . | ||
Foi criado a branch - TECD-2376Getting issue details... STATUS diretamente pela IDE. O método do backend estava com problemas de escopo na variavel. | |||
App H1 Fintech - Melhorar lógica para encontrar a chave PIX sendo ela válida como CPF e telefone | . | ||
. | |||
Mensagem de retorno no login do Orion em caso de falha de comunicação com o Viasell |
Aprimorar a rotina de reset do serviço ResetServiceImpl do sistema Orion para garantir que, em caso de falha de comunicação com os serviços da Viasell, seja exibida uma mensagem informativa ao usuário.
2.1. Refatoração do Método realizaReset
private Reset realizaReset(String series, String mac) { String clientSeries = formatSeries(series); try { return makeRequestWithExceptionHandling(url, clientSeries, mac); } catch (Exception e) { logger.error("Erro na primeira tentativa:", e); return makeRequestWithExceptionHandling(url2, clientSeries, mac); } } private String formatSeries(String series) { if (NumberUtil.isInteger(series)) { return String.valueOf(Integer.parseInt(series)); } return series; } private Reset makeRequestWithExceptionHandling(String url, String series, String mac) { try { return restTemplate.getForObject(url, Reset.class, series, mac); } catch (ResourceAccessException | HttpClientErrorException | HttpServerErrorException e) { throw e; } catch (Exception e) { logger.error("Erro na segunda tentativa:", e); throw e; } } 2.2. Adição do Método handleValidationAndResponse
public ResetSerieMacTOResponse handleValidationAndResponse(SerieMacTO to) { try { reset(); boolean isValid = valid(); logger.info("Orion liberado"); return createResponse(isValid, "Orion liberado"); } catch (Exception e) { return handleException(e); } } 2.3. Métodos de Tratamento de Exceções e Criação de Respostas
private ResetSerieMacTOResponse createResponse(boolean hasSuccess, String message) { return ResetSerieMacTOResponse.builder() .hasSuccess(hasSuccess) .message(message) .build(); } private ResetSerieMacTOResponse handleException(Exception e) { ResetExceptionHandler resetExceptionHandler = new ResetExceptionHandler(e); String logMessage = resetExceptionHandler.getLogMessage(); logger.error(logMessage + ": " + e.getMessage()); return createResponse(false, logMessage); } 2.4. Introdução da Classe ResetExceptionHandler
public class ResetExceptionHandler { private final Exception exception; public ResetExceptionHandler(Exception exception) { this.exception = exception; } public String getLogMessage() { if (exception instanceof HttpClientErrorException) { return "Erro de comunicação com o cliente HTTP"; } else if (exception instanceof HttpServerErrorException) { return "Erro de comunicação com o servidor HTTP"; } else if (exception instanceof ResourceAccessException) { return "Erro de acesso ao recurso"; } else if (exception instanceof IllegalArgumentException) { return "Argumento inválido fornecido"; } else if (exception instanceof IllegalStateException) { return "Estado inválido encontrado"; } else if (exception instanceof ResetException) { return "Erro no reset"; } else { return "Erro geral"; } } } 2.5. Padronização da Resposta com a Classe ResetSerieMacTOResponse
@Data @Builder public class ResetSerieMacTOResponse { private Boolean hasSuccess; private String message; } 2.6. Ajuste no Controller para Utilizar a Resposta Padronizada
@PostMapping public ResetSerieMacTOResponse save(@RequestBody SerieMacTO to) { configuracaoService.save(Configuracao.builder().chave(ConfiguracaoChave.SERIE).valor("\"" + to.getSerie() + "\"").build()); configuracaoService.save(Configuracao.builder().chave(ConfiguracaoChave.MAC).valor("\"" + to.getMac() + "\"").build()); return resetService.handleValidationAndResponse(to); } Estas alterações visam melhorar a clareza e a especificidade na detecção de erros, fornecer feedback útil ao usuário final, e assegurar que o processo de reset seja robusto e de fácil manutenção, além de padronizar a resposta da API. | ||
Necessário corrigir os endpoints de criação e alteração de convenios na Fintech, também foram pedidos ajustes nas variaveis do Filt para enviar valores com 0 a esquerda. | |||
. | |||
. | |||
. | |||
. | |||
. | |||
Implementar serviço de monitoramento e controle de acessos a API | . | ||
. | |||
. | |||
. | |||
Atualização e compilação dos projetos do agro (continuação da TECD-2140) | . | ||
RevTelas - Aplicação das novas telas no projeto Agro3c - Parte 2 | . | ||
. | |||
Alteração do código beneficiário no momento do cadastro do convenio, pois a conta é cadastrada antes do convenio. Tarefa finalizada porém alguma contas Sicredi sofrerão ajustes manuais e serão validadas. | |||
. | |||
Implementar um aplicativo para realizar o papel de producer de filas da OCI (OCI Queues) | Informações do projetoObjetivoFornecer uma interface entre receber uma mensagem Json via Rest e armazenar ela em uma OCI Queue. Esse aplicativo é um produtor de mensagens em uma Queue. Parametros necessáriosConfigurar no application.properties: oci.config.path= oci.config.endpoint= oci.config.queue-ocid= O path é o caminho onde o arquivo config está armazenado (arquivo semelhante ao do resource .oci/config). Endpoint e queue-ocid são informações que são obtidas na criação das queues. Métodos a serem utilizados/ e /pingsão métodos GET servem só para teste se a API subiu. /api/sendmétodo POST cujo valor do body será armazenado como mensagem na Queue. AtençãoComo trata-se de um recurso da OCI atentar-se com um uso de chave privada com direitos de acesso de usuário como serviço para execução. | ||
1.Menu 2.Objetivo 3.Alteração | |||
Modificação no metodo que gera a remessa na api da Fintech. | |||
. | |||
VsIA Api - Confeir as versoes do OpenAI considerando as versões compatíveis com o langchain | 1.Menu VsIA Api → OpenAI 2.Objetivo Verificar versão da OpenIA 3.Alteração Anteriormente nas versões do langchain tínhamos que fazer um combinado entre a versão do langchain com a versão da OpenIA para que as bibliotecas pudessem funcionar corretamente em conjunto. Mas parece que dentro dessas novas versões do langchain o próprio langchain criou um pacote nele mesmo para fazer a gestão das versões e chamadas com a OpenIA. >> langchain==0.2.5 >> langchain-openai==0.1.9 No caso ao baixar através do pip install langchain ele já puxara a latest da openai juntamente com ele, ou seja não precisa de implementações e grande pesquisa para funcionar. | ||
1.Menu VsAPI → Langchain → Prompt 2.Objetivo Verificar qual a estratégia de prompt está sendo mais utilizada nesse momento, considerando a latest do langchain 3.Alteração Anteriormente o prompt era gerado de uma forma bem manual, aonde através de uma string formatada era possível colocar algumas variáveis que mais para frente seriam preenchidas pelo langchain, exemplo: context, chat_history e input. E logo após isso chamávamos o PromptTemplate e indicavamos de forma manual quais foram as variáveis adicionadas e qual a variável de prompt utilizada. Forma que era utilizada: prompt_template = "Prompt: " + prompt + """ Context: {context} Chat History: {chat_history} User Input: {question}""" FINAL_PROMPT = PromptTemplate( input_variables=["context", "question", "chat_history"], template=prompt_template ) Atualmente o PromptTemplate já foi descontinuado, mas ainda há algumas semelhanças, pois usamos um método que seria o ChatPromptTemplate, mas nesse método ele já reconhece naturalmente todas as variáveis setadas automaticamente. # https://api.python.langchain.com/en/latest/prompts/langchain_core.prompts.chat.ChatPromptTemplate.html real_prompt = ChatPromptTemplate.from_messages([ ("system", f"{prompt}"), MessagesPlaceholder("chat_history"), ("assistant", "{context}"), ("human", "{input}") ]) Além disso, nessa nova forma, nós conseguimos configurar de onde está vindo cada uma das mensagens, ou seja, o contexto vem sempre do “assistant”, o prompt vem sempre do “system” e o “human” que vai perguntar alguma coisa entra como a última interação. Esse modelo de prompt é muito mais completo pelo fato que pode ser adicionada infinitas varáveis e diversas interações até a última ação, a qual seria a do próprio cliente, além de tudo isso o “chat_history” não entra categorizado nem como “assistant” e nem como “system” ele próprio faz esse controle. Além desse novo prompt é importante que ressaltar que agora temos um prompt que tem a função de auxiliar o retriever para gerar perguntas e respostas para ele mesmo.
E vendo através das documentações é possível construir um prompt, ou também podemos utilizar alguns que o próprio langhcian disponibiliza. def get_history_aware_retriever(llm: ChatOpenAI, vector: ElasticsearchStore): # Conforme as documentações do langhcain https://smith.langchain.com/hub/langchain-ai/chat-langchain-rephrase chat_prompt = hub.pull("langchain-ai/chat-langchain-rephrase") history_aware_retriever = create_history_aware_retriever( llm, vector.as_retriever(), chat_prompt ) return history_aware_retriever | |||
1.Menu VsApi → Elasticserach → Vetorização de contextos 2.Objetivo Verificar as documentações e usar também a comunidade para verificar o que devemos implementar no nosso projeto com base nas vetorizações de contextos 3.Documentação Se entrarmos das documentações do ElasticVectorSearch https://api.python.langchain.com/en/latest/vectorstores/langchain_community.vectorstores.elastic_vector_search.ElasticVectorSearch.html é possível ver de cara uma mensagem de decaprated: Ele foi migrado para a ElasticsearchStore, aonde ficou muito mais completo agora, pois faz parte de um projeto langchain_elasticsearch invés de langchain_community. Sendo adicionado diversas funcionalidades como strategy, vector_query_field, query_field, distance_strategy. Mas de longe a melhor melhoria foi escolher a estratégia. Qual estratégia escolher? ApproxRetrievalStrategy (padrão) - Ela usa o algoritmo HNSW para realizar uma pesquisa aproximada do vizinho mais próximo. Esta é a estratégia mais rápida e eficiente em termos de memória. ExactRetrievalStrategy - Esta estratégia é usada para realizar uma pesquisa de força bruta / vizinho mais próximo exato via script_score (É uma funcionalidade do Elasticsearch que permite modificar a pontuação (score) de documentos durante uma pesquisa, usando um script personalizado. O script pode usar qualquer campo do documento para calcular a nova pontuação. Isso é útil quando você deseja personalizar a relevância de seus resultados de pesquisa com base em critérios específicos do seu aplicativo) SparseRetrievalStrategy - Esta estratégia é usada para realizar uma pesquisa de vetor esparsa via text_expansion (refere a técnicas usadas para expandir uma consulta de pesquisa com sinônimos, termos relacionados ou variações de um termo para melhorar a precisão e a abrangência dos resultados da pesquisa). Mas algumas coisas mudaram no sentido de busca de documentos, por padrão o ElasticsearchStore não da mais opção de colocar quantos números de documentos você deseja buscar, ou até mesmo o score que os documentos teriam que ter para aparecer dentro das buscas de indices, isso é feito automaticamente, mas se caso for necessário é possível utilizar o SelfQueryRetriever, que se trata de um auxiliador nesse sentido, mas nos meus testes não achei necessidade para usar o tal método. O próprio langchain não aconselha utilizar essa parte, resposta do próprio langchain.
Criação da POC: elastic_vector_search = ElasticsearchStore( es_connection=es_client, index_name=index, embedding=embedding ) llm = ChatOpenAI(openai_api_key=openai_api_key, temperature=0.5) chat_prompt = hub.pull("langchain-ai/chat-langchain-rephrase") history_aware_retriever = create_history_aware_retriever( llm, elastic_vector_search.as_retriever(), chat_prompt ) | |||
VsIA Api - Verificar como pode ser resolvido LangChainDeprecationWarning | 1.Menu VsApi → Novas implementações considerando langchain 0.2.5 2.Objetivo Verificar todas as partes que estavam com o deprecated e transferir para as novas versões 3.Alteração Para executar o projeto antigo do VsApi ele já dava 3 erros de decrepeciado logo de cara o qual são os: 1. LangChainDeprecationWarning: The class `OpenAIEmbeddings` was deprecated in LangChain 0.0.9 and will be removed in 0.3.0. An updated version of the class exists in the langchain-openai package and should be used instead. To use it run `pip install -U langchain-openai` and import as `from langchain_openai import OpenAIEmbeddings`. ✅ 2.LangChainPendingDeprecationWarning: The class `ElasticVectorSearch` will be deprecated in a future version. Use Use ElasticsearchStore class in langchain-elasticsearch package instead. ✅ 3. UserWarning: ElasticVectorSearch will be removed in a future release. SeeElasticsearch integration docs on how to upgrade. ✅ 3.1 - Para instanciar um vector do Elastic sempre é necessário anexar uma estratégia de embedidgs que ele irá executar para analisar as documentações e responder conforme elas, e no nosso caso sempre era passado a OpenAIEmbeddings porém faz um bom tempo que o langchain os seus pacotes, agora temos langchain_openai, langchain_elasticsearch, langchain_community… E por isso foi alterado a lógica do Embedding, aonde ele faz parte de um pacote especifico da OpenAI, a sua implementação no geral não foi alterado e até deu suporte a passar a chave da openai_api_key como parâmetro (aonde antes não era possível). from langchain_openai import OpenAIEmbeddings # Por default usa o modelo de embedding: text-embedding-ada-002 # Por default o tamanho da chunck é 1000 (O qual é usado hoje nas estratégias de embedding) embedding = OpenAIEmbeddings(openai_api_key=openai_api_key) # ... 3.2 e 3.3 - O mesmo aconteceu com o ElasticVectorSearch, ele saiu do pacote inicial do elastic, aonde antes uma única lib do elastic dava suporte a toda estrutura, e agora é divida em submódulos, no geral essa refatoração teve mudanças em seus principais métodos e estrategias, mas ainda mantém sua função principal como vector. from langchain_elasticsearch import ElasticsearchStore import elasticsearch # Outra coisa que foi alterada nesse sentido foi que agora instanciamos uma conexão do elasticsearch de forma convencional # E só depois passamos para o vetor como parametro # Anteriormente o próprio vetor cuidava da conexão es_client= elasticsearch.Elasticsearch( hosts=elastic_full_url ) # Aqui em si ele mantém a mesma lógica no geral, recebendo um index de contexto, estratégia de embedding # Mas o seu uso mudou muito daqui para frente # https://api.python.langchain.com/en/latest/vectorstores/langchain_community.vectorstores.elasticsearch.ElasticsearchStore.html # Por padrão utiliza a estratégia ApproxRetrievalStrategy # Mas pode ser alterada para ExactRetrievalStrategy, ApproxRetrievalStrategy, or SparseRetrievalStrategy. elastic_vector_search = ElasticsearchStore( es_connection=es_client, index_name=index, embedding=embedding ) E uma principal mudança no ElasticserachStore, foi que agora após instanciar ele é possível fazer os embeddings utilizando ele mesmo através do método add_documents}}ou {{aadd_documents, aonde a única diferença entre eles é que um trabalha de forma síncrona e outro de forma assíncrona. Após essa implementação do langchain podemos utilizar o ElasticsearchStore para auxiliar na criação dos embeddings facilmente. Aqui está um exemplo aonde peguei um arquivo de texto e fiz o embedding em um índice específico utilizando as novas documentações. from langchain_text_splitters import CharacterTextSplitter import elasticsearch from langchain_openai import OpenAIEmbeddings from langchain_elasticsearch import ElasticsearchStore with open("windows.txt", encoding="utf-8") as f: windows_manual = f.read() text_splitter = CharacterTextSplitter( separator="\n\n", chunk_size=1000, chunk_overlap=200, length_function=len, is_separator_regex=False, ) metadatas = [{"document": "windows.pdf"}] docs = text_splitter.create_documents([windows_manual], metadatas=metadatas) es_client = elasticsearch.Elasticsearch( hosts=elastic ) embedding = OpenAIEmbeddings(openai_api_key=openai_api_key) elastic_vector_search = ElasticsearchStore( es_connection=es_client, index_name=index, embedding=embedding ) elastic_vector_search.add_documents(docs) # Em poucas linhas uma estratégia de embedding muito útil | ||
VsIA Api - Criar sistema de memória interno dentro do langchain com elasticsearch | 1.Menu VsIA Api → Histórico de Mensagens 2.Objetivo Criar um fork de uma biblioteca que já faz integração com histórico de chats com langchain e elasticsearch 3.Alteração Nesse sentido foi verficado que a biblioteca do elasticsearch atendia parcialmente nossas demandas, logo foi realizada uma adptação e refatoração do código deles para conseguir servir a nossa demanda. O langchain possui o método ElasticsearchChatMessageHistory que se trata de uma classe que faz a criação de uma conexão com o elasticsearch e além disso é possível adicionar mensagens e visualizar as mensagens no histórico. Mas para o nosso uso nós precisávamos conseguir odernar as mensagens, além disso limitar a quantidade delas. Por isso foi criado realizado as modicações no ElasticsearchChatMessageHistory e agora ele é o VsApiChatMessageHistory. Métodos: def teste(): # Para instaciar o método preciamos inserir algumas informações # Nesse caso temos que colocar a url, username, password do servidor do elastic # E também temos que passar o index (Indice que irá armazenar o histórico) # e o session_id (que se trata da memoria do usuario naquela especifica sessão/chat) history = VsApiChatMessageHistory( es_url=url, es_user=username, es_password=password, index=index, session_id=session_id ) # Também podemos adicionar uma mensagem humana, que no caso seria o input do usuario history.add_human_message("Olá me chamo Lucca") # E também podemos adicionar uma mensagem de IA, que seria a resposta do bot history.add_ia_message("Olá Lucca, como posso te ajudar?") # Através desse método conseguimos descrever se queremos a ordem das mensagens de forma # crescente ou decrescente, e também podemos limitar a quantidade de mensagens que queremos # deve ser usar desc para ordem decrescente e asc para ordem crescente last_four_messages = history.messagesLimitedBy('desc', 4) # E temos um método que retorna as mensagens de forma alternada # Dessa forma sempre teremos human, ia, human, ia, human, ia... order_messages = history.alternate_messages(last_four_messages) | ||
. | |||
Dados obtidos com sucesso via api Tecnospeed. | |||
. | |||
. | |||
. | |||
. | |||
Dados nao localizados sendo necessário executar requisições na api da tecnospeed para preenchimento do código de barra e nosso numero impressão. | |||
. | |||
1.Menu VsAPI → Segurança 2.Objetivo Alterar parte de segurança da API 3.Alteração Foi retirado todo e qualquer tipo de autenticação que havia dentro da api | |||
. | |||
. | |||
. | |||
. | |||
Fintech - Subir nova versão do apk Android e iOS com a nova versão do extrato | . | ||
. | |||
Novo controle de cache para dicionário de dados e redução de consumo de API's do server | 1.Menu 2.Objetivo 3.Alteração | ||
Rotina Fluxo de Caixa não carrega adequadamente os filtros salvos | . | ||
Orion - Estudar forma de manter retrocompatibilidade entre banco H2 e MySQL | 1.Menu Orion → Banco de Dados 2.Objetivo Verificar se é possível deixar os dois bancos funcionando ao mesmo tempo 3.Alteração A solução para permitir que o Orion funcione com H2 ou MySQL envolve a configuração de uma flag que determine qual banco de dados será utilizado, detalhe que essa funcionalidade já foi utilizada para migrar os logs para o MySQL. Pelos estudos não vai precisar manter em .war diferentes, pelo fato de que não vamos ter informações fixas dentro do código-fonte do Orion, ele vai buscar as informações direto das variáveis de ambiente do sistema para verificar qual banco deverá usar. A principal dificuldade encontrada está nos repositórios e serviços que possuem SQL fixos. Para resolver isso, é necessário adaptar o código para que seja mais genérico, ou então, utilizar a API do Hibernate para evitar SQL nativo. Em casos onde o SQL nativo for inevitável, podemos parametrizar o banco de dados utilizado, exemplo: @Query(value = "SELECT * FROM ${tableName} WHERE id = :id", nativeQuery = true) Optional<Entity> findById(@Param("tableName") String tableName, @Param("id") Long id); Agora a análise de forma separada # Model Os models no projeto Orion representam as entidades do banco de dados. Como o Spring Data JPA abstrai grande parte das diferenças entre bancos de dados, o impacto nos models é mínimo, independentemente de você usar H2 ou MySQL. # Repository Os repositories são responsáveis por interagir com o banco de dados. A maioria das operações de CRUD são diretamente suportadas pelo Spring Data JPA, independentemente do banco subjacente. No entanto, desafios podem surgir ao usar queries SQL nativas, que podem diferenciar entre H2 e MySQL. # Controller Os controllers no Spring Boot geralmente não são afetados pelo tipo de banco de dados utilizado, uma vez que eles lidam principalmente com a lógica e encaminham solicitações para os serviços e repositórios. | ||
1.Menu Orion → Banco de Dados 2.Objetivo Criar feature que grava os logs do Orion no banco MySQL 3.Alteração O Orion utiliza o log4j2 para geração de logs, e todos os apontamentos e códigos estão sendo feitos para o banco h2, sendo tudo fixo nessa parte. Logo o que teve que ser feito foi a refatoração do log4j2.xml para um formato que consiga atender tanto os logs no h2 como no mysql, ai entra as peculiaridades de cada banco em si. Dessa forma teve que criar dois métodos o getDatabase e o getDatabaseLogs, pelo fato dos logs ter a possibilidade de funcionar no banco MySQL além do H2. <ConnectionFactory class="br.com.viasoft.orion.security.LogFactory" method="getDatabaseConnectionLogs" /> Um fato importante a se destacar que o Orion vai utilizar MySQL se ele encontrar as seguintes variáveis de ambiente
Após ele encontrar as variáveis ele vai tentar fazer um test-connection, caso encontre sucesso vai utilizar o MySQL para armazenar os logs, caso contrário vai utilizar o banco H2 para tudo. // Exemplo da iniciação da base Connection conn = LogFactory.getDatabaseConnectionLogs(); StringBuilder sql = null; try { boolean isH2 = true; if (conn != null) { if (conn.getMetaData() != null) { if (conn.getMetaData().getDatabaseProductName() != null) { isH2 = !conn.getMetaData().getDatabaseProductName().equals("MySQL"); } } } logger.info("Iniciando com base: " + (isH2 ? "H2" : "MySQL")); sql = isH2 ? sqlBuildH2() : sqlBuildMySQL(); Houveram diversas mudanças dentro do código, mas cabe ressaltar que todas tiveram o requisito principal em deixar os dois bancos funcionando ao mesmo tempo. Aqui é um guia descrito durante a tarefa para dar as instruções de como conectar os logs pelo MySQL no Orion, | |||
. | |||
. | |||
. | |||
Criar ambiente da Aplicação Satélite Construshow Portal do Cliente | . | ||
1.Menu Orion → Viadecisor (API Versão API Oficial) 2.Objetivo 3.Alteração 3.1 - 3.2 - 3.3 - 3.4 - | |||
Foram necessarias alteracoes na Fintech e no Filt. |