<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Pedro Paulo Silva</title>
    <description>The latest articles on DEV Community by Pedro Paulo Silva (@pedropms).</description>
    <link>https://dev.to/pedropms</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F626241%2F290934d7-5f99-49f8-8db9-afb74aa4b57b.jpeg</url>
      <title>DEV Community: Pedro Paulo Silva</title>
      <link>https://dev.to/pedropms</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/pedropms"/>
    <language>en</language>
    <item>
      <title>Observabilidade 101 - Entendendo o que acontece no seu sistema</title>
      <dc:creator>Pedro Paulo Silva</dc:creator>
      <pubDate>Tue, 09 May 2023 22:08:20 +0000</pubDate>
      <link>https://dev.to/pedropms/observabilidade-101-entendendo-o-que-acontece-no-seu-sistema-23hg</link>
      <guid>https://dev.to/pedropms/observabilidade-101-entendendo-o-que-acontece-no-seu-sistema-23hg</guid>
      <description>&lt;h1&gt;
  
  
  Observabilidade
&lt;/h1&gt;

&lt;p&gt;As aplicações, por muito tempo, eram construídas de maneira centralizada, os famosos monólitos, entretanto, ao longo dos últimos anos, a área de tecnologia vem mudando bastante. &lt;/p&gt;

&lt;p&gt;As aplicações usam cada vez mais ferramentas e abordagens distribuídas, como Containers, Kubernetes, Microservices e Serverless, por exemplo. Essas tecnologias proporcionam diversas vantagens, a escalabilidade sendo uma das mais relevantes. Porém, introduziram complexidade adicional, fazendo com que as falhas sejam mais difíceis de prever, detectar e solucionar problemas.&lt;/p&gt;

&lt;p&gt;Buscando resolver esse problema surge, na Engenharia de Software, o conceito de Observabilidade, buscando fornecer um nível de introspecção e ajudar as pessoas a raciocinar sobre os estados internos de seus sistemas.&lt;/p&gt;

&lt;p&gt;Observabilidade é a habilidade de entender o que está acontecendo dentro do seu sistema com base em suas saídas. Isso significa que você deve saber explicar qualquer estado em que seu sistema possa entrar. Por exemplo: estado de falha, estado de lentidão etc. Busca alcançar uma melhor compreensão de como o software está operando. &lt;/p&gt;

&lt;h2&gt;
  
  
  Pilares da Observabilidade
&lt;/h2&gt;

&lt;p&gt;Para tentar alcançar o maior entendimento do que está acontecendo no seu sistema, existem 3 principais pilares que, por si só, não fazem um sistema observável, mas relacionando eles se tem um entendimento muito bom dos processos do seu sistema.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8atbbc1ky8ifl9umtyj6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8atbbc1ky8ifl9umtyj6.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Logs
&lt;/h3&gt;

&lt;p&gt;Os logs são registros imutáveis que possuem data/hora de eventos que ocorrem em um sistema, eles fornecem contexto sobre o que está acontecendo no sistema e podem ser utilizados para identificar problemas e rastrear sua origem.&lt;/p&gt;

&lt;p&gt;Podemos considerar então que as mensagens de logs representam os vários eventos que ocorrem nos sistemas, podendo ser informativos ou até mesmo registrar um problema que aconteceu em seu sistema.&lt;/p&gt;

&lt;h3&gt;
  
  
  Métricas
&lt;/h3&gt;

&lt;p&gt;Quando pensamos em métricas para arquitetura de microservices, devemos conhecer o método RED. Esse método define as três principais métricas que devemos medir em microservices. São as métricas básicas que recebemos por padrão nas principais soluções de APM do mercado. As métricas RED são:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RATE&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Número de requisições por segundo que seu serviço está atendendo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ERROR&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Número de requisições com falha por segundo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DURATION&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Tempo médio que o serviço gasta para processar cada requisição.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tracing
&lt;/h3&gt;

&lt;p&gt;Rastreamento distribuído (ou Distributed tracing) é um conjunto de técnicas, padrões e práticas que tem como principal objetivo mostrar o fluxo por onde passou uma requisição, se ela foi atendida e quanto tempo levou para a requisição ser atendida.&lt;/p&gt;

&lt;p&gt;Vamos imaginar que esse usuário está enfrentando uma lentidão para receber a resposta de sua requisição. Sem usar distributed tracing (por exemplo, olhando os logs isolados de cada microservice) ficará difícil identificar rapidamente onde está ocorrendo o gargalo, onde podem ocorrer erros etc.&lt;/p&gt;

&lt;p&gt;Com muitos serviços envolvidos em apenas uma única requisição, é difícil também você reportar as equipes responsáveis por esses componentes sem saber identificar o problema, gerando lentidão na resolução do problema.&lt;/p&gt;

&lt;p&gt;Exemplo de tracing no New Relic:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2gbg3n67uk1jfp3cvi1k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2gbg3n67uk1jfp3cvi1k.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Ferramentas de Observabilidade
&lt;/h2&gt;

&lt;p&gt;Existem diversas ferramentas para lidar com cada pilar da observabilidade, umas fazem melhor uma coisa, outras tem melhor desempenho, etc. Você deve avaliar qual se encaixa melhor para o seu cenário e combiná-las.&lt;/p&gt;

&lt;p&gt;A seguir listei algumas das ferramentas de observabilidade mais utilizadas no mercado&lt;/p&gt;

&lt;p&gt;New Relic - &lt;a href="https://newrelic.com/" rel="noopener noreferrer"&gt;https://newrelic.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Grafana - &lt;a href="https://grafana.com/" rel="noopener noreferrer"&gt;https://grafana.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Prometheus - &lt;a href="https://prometheus.io/" rel="noopener noreferrer"&gt;https://prometheus.io/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Data Dog - &lt;a href="https://www.datadoghq.com/" rel="noopener noreferrer"&gt;https://www.datadoghq.com/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Esses são os conceitos básicos sobre observabilidade, seguem alguns links caso queira se aprofundar nesse assunto de extrema importância.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O que é observabilidade? - &lt;a href="https://www.opservices.com.br/o-que-e-observabilidade/" rel="noopener noreferrer"&gt;https://www.opservices.com.br/o-que-e-observabilidade/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;8 dicas de como implementar uma boa estratégia de observabilidade - &lt;a href="https://www.opservices.com.br/como-implementar-uma-boa-estrategia-de-observabilidade/" rel="noopener noreferrer"&gt;https://www.opservices.com.br/como-implementar-uma-boa-estrategia-de-observabilidade/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Qual a diferença entre monitoramento e observabilidade? - &lt;a href="https://www.opservices.com.br/diferenca-entre-monitoramento-e-observabilidade/" rel="noopener noreferrer"&gt;https://www.opservices.com.br/diferenca-entre-monitoramento-e-observabilidade/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>braziliandevs</category>
      <category>beginners</category>
      <category>architecture</category>
      <category>monitoring</category>
    </item>
    <item>
      <title>Múltiplas validações com o Laravel Pipeline</title>
      <dc:creator>Pedro Paulo Silva</dc:creator>
      <pubDate>Mon, 07 Mar 2022 21:54:48 +0000</pubDate>
      <link>https://dev.to/pedropms/multiplas-validacoes-com-o-laravel-pipeline-3oib</link>
      <guid>https://dev.to/pedropms/multiplas-validacoes-com-o-laravel-pipeline-3oib</guid>
      <description>&lt;p&gt;É quase certo que você já esteve na situação de ter que validar um objeto através de diversas condições. Nessas situações o comum é ir adicionando &lt;em&gt;if's&lt;/em&gt;, cada um validando uma condição específica. E não há nada de errado nisso, é uma maneira prática e você resolveu seu problema inicial.&lt;/p&gt;

&lt;p&gt;Contudo, com o passar do tempo mais condições vão aparecendo e o que eram 3 &lt;em&gt;if's&lt;/em&gt; agora são 15 e seu código começa a ficar muito complexo (se você usa alguma ferramenta para inspecionar o código como o &lt;em&gt;PHP Mess Detector&lt;/em&gt;, ele literalmente irá reclamar do seu código dizendo que está complexo demais).&lt;/p&gt;

&lt;p&gt;Para diminuir essa complexidade de um trecho de código, podemos aplicar um pattern chamado &lt;em&gt;Pipeline Pattern&lt;/em&gt;. &lt;br&gt;Resumidamente esse pattern cria uma "linha de montagem" com várias etapas sequenciais e passa seu objeto através dessas etapas, retornando o resultado ao final. Essa "linha de montagem" pode, por exemplo, manipular seu objeto, adicionando, atualizando ou removendo atributos. E também pode realizar validações nesse objeto, que é o que faremos aqui.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ivtu7wx1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/10iglpel8ucjlexjbywn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ivtu7wx1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/10iglpel8ucjlexjbywn.png" alt="Diagrama Pipeline" width="800" height="169"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;No Laravel temos uma implementação desse pattern (&lt;em&gt;Illuminate\Pipeline\Pipeline&lt;/em&gt;) e é ela que vamos usar hoje para refactor o trecho de código a seguir.&lt;/p&gt;

&lt;h1&gt;
  
  
  Exemplo
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5TRH5Mrk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kemfcell9n9als5wrbx3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5TRH5Mrk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kemfcell9n9als5wrbx3.png" alt="Exemplo" width="800" height="570"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h1&gt;
  
  
  Refatoração
&lt;/h1&gt;

&lt;p&gt;Primeiramente vamos criar 3 classes para fazer as validações isoladamente.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Mrl6mGV---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r3saqe982bamaav0m3xo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Mrl6mGV---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r3saqe982bamaav0m3xo.png" alt="Validar Email" width="800" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ng2PtA0S--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kbxuqfsmdrf8s9cz5x6w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ng2PtA0S--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kbxuqfsmdrf8s9cz5x6w.png" alt="Validar Idade" width="800" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tdglIY9Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/odjl2oc4t2xb9tr8p7ni.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tdglIY9Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/odjl2oc4t2xb9tr8p7ni.png" alt="Validar Cpf" width="800" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;E agora vamos usar a implementação da Pipeline que existe Laravel.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9EtovHGD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/grs7ecab53h1bmh0wvvd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9EtovHGD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/grs7ecab53h1bmh0wvvd.png" alt="Refatoração" width="800" height="515"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dessa forma o objeto &lt;code&gt;$usuario&lt;/code&gt; irá passar por todas as validações e ao final será retornado.&lt;/p&gt;

&lt;p&gt;Você pode, também, reaproveitar as validações já existentes e organizá-las de outras formas, criando outras validações, por exemplo, uma que só valide os meios de contato do usuário. Como abaixo:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XTbL-BT5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5s8w99m8zt39dnec11ry.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XTbL-BT5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5s8w99m8zt39dnec11ry.png" alt="Image description" width="800" height="444"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusão
&lt;/h1&gt;

&lt;p&gt;Como podemos ver, com o uso desse pattern as reponsabilidades de cada validação ficam separadas e muito melhor organizadas. Assim permitindo que a adição, exclusão e manutenção das validações seja feita de maneira muito mais fácil.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>Gerenciando Tarefas Agendadas do Laravel no Banco de Dados</title>
      <dc:creator>Pedro Paulo Silva</dc:creator>
      <pubDate>Fri, 18 Jun 2021 20:55:04 +0000</pubDate>
      <link>https://dev.to/pedropms/gerenciando-tarefas-agendadas-do-laravel-no-banco-de-dados-1l2n</link>
      <guid>https://dev.to/pedropms/gerenciando-tarefas-agendadas-do-laravel-no-banco-de-dados-1l2n</guid>
      <description>&lt;p&gt;Tarefas agendadas são uma ótima maneira de executar processos repetitivos de maneira automatizada em nossos projetos, basta definir as tarefas e escolher os momentos em que elas serão executadas e pronto, pode deixar o resto do trabalho com o &lt;a href="https://en.wikipedia.org/wiki/Cron" rel="noopener noreferrer"&gt;cron&lt;/a&gt; do servidor.&lt;/p&gt;

&lt;p&gt;Geralmente essa definição dos momentos em que as tarefas irão rodar fica dentro do projeto e acaba sendo suficiente em muitos casos, porém, essa maneira de gerenciamento acaba sendo um empecílio quando se precisa alterar o horário em que as tarefas serão executadas. Gerenciando dessa maneira, será necessário uma alteração no arquivo, e uma nova &lt;em&gt;release&lt;/em&gt; do projeto para as alterações terem efeito. Isso também restringe que o ajuste no horário da tarefa seja feito somente por um desenvolvedor.&lt;/p&gt;

&lt;p&gt;Para resolver esse problema, podemos gerenciar as tarefas agendadas no banco de dados, fazendo com que apenas a alteração de um registro já altere o funcionamento da tarefa.&lt;/p&gt;

&lt;p&gt;No Laravel temos o pacote: &lt;a href="https://github.com/robersonfaria/laravel-database-schedule" rel="noopener noreferrer"&gt;Laravel Database Schedule&lt;/a&gt;, que permite o gerenciamento das tarefas no banco de dados e ainda fornece uma interface para que a alteração das tarefas possa ser feita de maneira mais simples e por alguém sem tanto conhecimento de programação.&lt;/p&gt;

&lt;h1&gt;
  
  
  Instalação
&lt;/h1&gt;

&lt;p&gt;Para instalar a biblioteca vamos rodar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;composer require robersonfaria/laravel-database-schedule
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Após a instalação precisamos rodar as &lt;em&gt;migrations&lt;/em&gt; para criar as tabelas usadas pela biblioteca:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Por último, exportar o arquivo de configurações:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan vendor:publish --provider="RobersonFaria\DatabaseSchedule\DatabaseSchedulingServiceProvider" --tag="config"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No arquivo de configurações vamos alterar o &lt;strong&gt;restricted_access&lt;/strong&gt; para &lt;code&gt;false&lt;/code&gt; para o teste. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcwejpmkvkyb3y4kn6uif.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcwejpmkvkyb3y4kn6uif.png" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;OBS:&lt;/strong&gt; essa configuração deixa o dashboard de tarefas agendadas público, para restringir o acesso somente à usuários autorizados deixe a propriedade como &lt;code&gt;false&lt;/code&gt; e consulte a &lt;a href="https://github.com/robersonfaria/laravel-database-schedule#dashboard-authorization" rel="noopener noreferrer"&gt;documentação&lt;/a&gt; para definir quem poderá acessar.&lt;/p&gt;

&lt;h1&gt;
  
  
  Criando a Tarefa Agendada
&lt;/h1&gt;

&lt;p&gt;Para exemplo vamos criar uma tarefa rodando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan make:command NovoComando
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E configuramos o comando dessa maneira:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;protected $signature = 'comando:novo-comando';

protected $description = 'Novo comando teste';

public function handle(): int
{
    $this-&amp;gt;info('Comando rodando!');
    return 0;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Normalmente, agora seria o momento em que iríamos cadastrar esse comando que criamos, no &lt;code&gt;Kernel.php&lt;/code&gt; e configurariamos o horário para a tarefa rodar, mas usando o &lt;em&gt;database schedule&lt;/em&gt; não faremos isso.&lt;/p&gt;

&lt;h1&gt;
  
  
  Agendando a Tarefa no Banco de Dados
&lt;/h1&gt;

&lt;p&gt;Após iniciar o servidor com:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vamos acessar &lt;a href="http://localhost:8000/schedule" rel="noopener noreferrer"&gt;http://localhost:8000/schedule&lt;/a&gt; para entrar no dashboard.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5jii2yvghjx4ac5h8axr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5jii2yvghjx4ac5h8axr.png" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No formulário, vamos escolher o comando que queremos agendar, a expressão cron que vai definir quando ocorrerá a execução e marcar a opção de envio de email caso ocorra uma falha na execução, para isso também vamos definir um email.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdrj4uu7o3sqkifngzdva.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdrj4uu7o3sqkifngzdva.png" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Para entender todas as opções e parâmetros que podem ser configurados na tarefa agendada visite a &lt;a href="https://github.com/robersonfaria/laravel-database-schedule" rel="noopener noreferrer"&gt;documentação&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Após essa configuração podemos ver no dashboard nosso comando cadastrado.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8q96hr0hgv944hsj3paw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8q96hr0hgv944hsj3paw.png" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Executando as tarefas agendadas
&lt;/h1&gt;

&lt;p&gt;Para testar localmente vamos rodar o comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan schedule:run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E depois do comando rodar, se acessarmos o email cadastrado e a sessão de &lt;strong&gt;Histórico&lt;/strong&gt; no dashboard veremos o resutado.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F539au6dzj8rwz6cd5ht5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F539au6dzj8rwz6cd5ht5.png" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frk7ten4wx5lv7fn5o2ws.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frk7ten4wx5lv7fn5o2ws.png" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Caso ocorra algum erro, o email e histórico continuam sendo registrados.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjw5mvduyx1o0bf0k8lfw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjw5mvduyx1o0bf0k8lfw.png" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3xx6jeib9fr8ux4ogyws.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3xx6jeib9fr8ux4ogyws.png" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Referências
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://github.com/robersonfaria/laravel-database-schedule" rel="noopener noreferrer"&gt;https://github.com/robersonfaria/laravel-database-schedule&lt;/a&gt;&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>braziliandevs</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Melhorando a performance dos seus testes em PHP/Laravel</title>
      <dc:creator>Pedro Paulo Silva</dc:creator>
      <pubDate>Thu, 06 May 2021 21:49:29 +0000</pubDate>
      <link>https://dev.to/pedropms/melhorando-a-performance-dos-seus-testes-em-php-laravel-3kip</link>
      <guid>https://dev.to/pedropms/melhorando-a-performance-dos-seus-testes-em-php-laravel-3kip</guid>
      <description>&lt;h1&gt;
  
  
  O problema
&lt;/h1&gt;

&lt;p&gt;Você já se encontrou na situação em que tinha que fazer um &lt;em&gt;deploy&lt;/em&gt; ou subir sua atualização urgente e teve que ficar esperando os testes terminarem para finalizar &lt;em&gt;pipeline&lt;/em&gt;? Nessa hora qualquer minuto é uma eternidade. &lt;/p&gt;

&lt;p&gt;Eu estava enfrentando esse problema, meus testes demoravam cerca de 6 minutos para rodar e esse tempo seguia aumentando a cada nova &lt;em&gt;feature&lt;/em&gt; entregue.&lt;/p&gt;

&lt;h1&gt;
  
  
  A solução
&lt;/h1&gt;

&lt;p&gt;Para resolver isso encontrei o pacote &lt;a href="https://github.com/paratestphp/paratest" rel="noopener noreferrer"&gt;Paratest&lt;/a&gt;, basicamente, esse pacote adiciona suporte a testes paralelos ao PHPUnit, fazendo com que seus testes rodem simultaneamente.&lt;/p&gt;

&lt;h4&gt;
  
  
  Instalação
&lt;/h4&gt;

&lt;p&gt;Primeiro começamos instalando o pacote:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require &lt;span class="nt"&gt;--dev&lt;/span&gt; brianium/paratest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Após isso, sua aplicação já tem suporte aos testes em paralelo. 🥳&lt;/p&gt;

&lt;p&gt;Para começar a usar vamos rodar o comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vendor/bin/paratest &lt;span class="nt"&gt;-p4&lt;/span&gt; &lt;span class="nt"&gt;--runner&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;WrapperRunner
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  Opções usadas:
&lt;/h5&gt;

&lt;blockquote&gt;
&lt;p&gt;-p4&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A opção &lt;code&gt;-p&lt;/code&gt; é referente ao número de processos simultâneos que irão rodar os testes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;--runner=WrapperRunner&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Por padrão, o PHPUnit inicia um novo processo para cada arquivo de testes que irá rodar, utilizando o &lt;code&gt;--runner=WrapperRunner&lt;/code&gt; cada processo &lt;code&gt;-p&lt;/code&gt; irá iniciar apenas uma vez e manter tudo o que é preciso para rodar todos os arquivos de testes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Para saber todas as opções disponíveis e ter mais detalhes sobre as usadas aqui, acesse a &lt;a href="https://github.com/paratestphp/paratest" rel="noopener noreferrer"&gt;documentação&lt;/a&gt; do pacote.&lt;/p&gt;


&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Resultados
&lt;/h4&gt;

&lt;p&gt;Para efeitos de comparação vamos rodar modo sequencial, apenas com o PHPUnit e no modo paralelo, com o Paratest. Serão 646 testes com 75442 asserções, a maioria desses testes sendo de integração, com acesso ao banco de dados e outras dependências.&lt;/p&gt;

&lt;h5&gt;
  
  
  Testes Sequenciais:
&lt;/h5&gt;

&lt;p&gt;O tempo levado pelo PHPUnit para rodar todos esses testes foi de aproximadamente 5 minutos e 39 segundos. Agora, lembre-se da situação em que você está esperando a pipeline terminar para finalmente fazer um &lt;em&gt;deploy&lt;/em&gt;, esses quase 6 minutos se tornam uma eternidade.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx82hzvc6klhqb8ectg9f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx82hzvc6klhqb8ectg9f.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  Testes Paralelos:
&lt;/h5&gt;

&lt;p&gt;Já o tempo levado pelo Paratest foi de aproximadamente 1 minuto e 11 segundos. Um tempo muito melhor para você que está ansioso esperando.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqoq01jkggezu5shb0ulh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqoq01jkggezu5shb0ulh.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Nem tudo são flores 😓
&lt;/h1&gt;

&lt;p&gt;Quando estamos trabalhando com paralelismo um grande problema é controlar o acesso de cada processo aos recursos e dados do sistema, e nesse caso não é diferente. Em testes que devem acessar o banco de dados, modificar e consultar registros pode ocorrer de dois testes acessarem o mesmo dado simultaneamente causando possíveis &lt;em&gt;deadlocks&lt;/em&gt; no banco de dados e assim, também, um desses testes acabará falhando.&lt;/p&gt;

&lt;p&gt;Uma possível solução para esses casos é o isolamento de cada teste no acesso ao banco de dados. É possível fazer isso rodando os testes dentro de uma &lt;em&gt;transaction&lt;/em&gt; assim fazendo com que todos os registros modificados e/ou consultados estejam isolados e tudo que foi feito pelo teste é desconsiderado após seu término.&lt;/p&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;O Laravel disponibiliza a &lt;em&gt;Trait&lt;/em&gt; &lt;strong&gt;DatabaseTransactions&lt;/strong&gt;, com ela no seu &lt;strong&gt;TestCase&lt;/strong&gt; (classe na qual seus testes irão extender), seus testes irão por padrão rodar dentro de uma &lt;em&gt;transaction&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Caso use SQLServer, outra possível solução é habilitar a opção &lt;strong&gt;READ_COMMITTED_SNAPSHOT&lt;/strong&gt;, ela ajuda com esses casos de dados sendo acessados e modificados simultanemente. Para mais detalhes acesse: &lt;a href="https://www.mssqltips.com/sqlservertip/6368/sql-server-readcommittedsnapshot-database-option-and-read-commited-transaction-isolation-level/" rel="noopener noreferrer"&gt;https://www.mssqltips.com/sqlservertip/6368/sql-server-readcommittedsnapshot-database-option-and-read-commited-transaction-isolation-level/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Observação: no meu caso as duas opções foram usadas.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Conclusão
&lt;/h1&gt;

&lt;p&gt;Com a necessidade de cobrir sua aplicação com testes aumentando a cada dia, rapidamente você começa a se sentir incomodado com a demora na finalização dos testes. Para ajudar nesse ponto, a opção de rodar seus testes em paralelo é muito bem vinda, ela está aí para aumentar a performance e produtividade do seu time nos &lt;em&gt;deploys&lt;/em&gt; e no dia a dia.&lt;/p&gt;

&lt;p&gt;Se você ainda não usou, deveria dar uma chance e ver o tempo que você está perdendo &lt;em&gt;(literalmente rs)&lt;/em&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Fontes
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Paratest: &lt;a href="https://github.com/paratestphp/paratest" rel="noopener noreferrer"&gt;https://github.com/paratestphp/paratest&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Laravel Doc: &lt;a href="https://laravel.com/docs/8.x/testing#running-tests-in-parallel" rel="noopener noreferrer"&gt;https://laravel.com/docs/8.x/testing#running-tests-in-parallel&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>php</category>
      <category>laravel</category>
      <category>testing</category>
      <category>braziliandevs</category>
    </item>
  </channel>
</rss>
