<?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: Yury Cavalcante</title>
    <description>The latest articles on DEV Community by Yury Cavalcante (@cavalcanteyury).</description>
    <link>https://dev.to/cavalcanteyury</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%2F1134852%2Faab3b2c7-18e2-4461-9a10-3088c1a2ba9a.jpg</url>
      <title>DEV Community: Yury Cavalcante</title>
      <link>https://dev.to/cavalcanteyury</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/cavalcanteyury"/>
    <language>en</language>
    <item>
      <title>Reescrevendo Legados #01</title>
      <dc:creator>Yury Cavalcante</dc:creator>
      <pubDate>Sat, 24 Jan 2026 23:10:48 +0000</pubDate>
      <link>https://dev.to/cavalcanteyury/reescrevendo-legados-01-1fm3</link>
      <guid>https://dev.to/cavalcanteyury/reescrevendo-legados-01-1fm3</guid>
      <description>&lt;h2&gt;
  
  
  Contexto
&lt;/h2&gt;

&lt;p&gt;Na iugu, temos um processo rigoroso de cadastro e KYC (Know Your Customer) para todos os nossos clientes. Este processo é fundamental para a conformidade e segurança, e envolve a verificação de diversos documentos. É justamente nesse contexto que notamos um envio excessivo de comunicações, identificado por dois fatores principais: nosso serviço de e-mail teve o número de envios mensais extrapolado muito antes do esperado, e nossos clientes estavam relatando o recebimento de lembretes repetidos.&lt;/p&gt;

&lt;p&gt;Dados os dois fatores, o mais lógico seria analisar todos os processos responsáveis pelo envio de e-mails do nosso monolito, e isso nos levou a um worker no sistema que verificava todas as contas dos clientes com documentos pendentes.&lt;/p&gt;

&lt;p&gt;Separarei os tópicos do artigo pelos problemas identificados no worker:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Query ineficiente na busca de contas com documentos pendentes.&lt;/li&gt;
&lt;li&gt;Falta de granularidade nos processos para cada conta encontrada.&lt;/li&gt;
&lt;li&gt;Ausência de observabilidade.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;É importante ressaltar que o Claude Code (no meu caso, é o que utilizo) poderia varrer o sistema para encontrar todos esses problemas identificados, inclusive em mais de um worker, mas é crucial trabalhar em conjunto com a inteligência artificial. Acredito que, apesar da assistência da IA, quem detém o contexto, a lógica e as decisões de design importantes é o programador. Então, não deixe de acompanhar de perto as decisões tomadas pelo seu agente, questioná-las e ir além.&lt;/p&gt;

&lt;h2&gt;
  
  
  Query ineficiente na busca de contas com documentos pendentes.
&lt;/h2&gt;

&lt;p&gt;A query original:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;customers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Customer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;with_verification_request&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:customer_attributes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'customer_attributes.key = "verification_due_date"'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'customer_attributes.value &amp;lt; ?'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;days&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_now&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;references&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:customer_attributes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ao otimizar a query, já conseguiríamos um resultado mais performático. Para aqueles que não estão acostumados com Rails, podemos "traduzir" a sintaxe do Rails para SQL puro com o método built-in do Rails chamado &lt;code&gt;.to_sql&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;customers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;customers&lt;/span&gt;
&lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;customer_attributes&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;customer_attributes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;customers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;customer_attributes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'verification_due_date'&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;customer_attributes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="k"&gt;CURRENT_DATE&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;INTERVAL&lt;/span&gt; &lt;span class="s1"&gt;'10 days'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Identificação dos problemas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;includes&lt;/code&gt; carrega todos os dados de &lt;code&gt;customer_attributes&lt;/code&gt; na memória&lt;/li&gt;
&lt;li&gt;Falta de filtros essenciais na query (status, customers não verificados)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Esses são os problemas essencialmente ligados à query. No entanto, em seguida, temos o bloco de código que traz redundância e lentidão devido à forma como a query foi construída.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;customers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="k"&gt;next&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;verified?&lt;/span&gt;
  &lt;span class="c1"&gt;# processamento&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;find_each&lt;/code&gt; carrega objetos Customer completos (todas as colunas)&lt;/li&gt;
&lt;li&gt;Filtros aplicados em Ruby após carregar dados (&lt;code&gt;next unless customer.verified?&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Vamos destrinchar as soluções em forma de resposta aos problemas listados. Lembrando que estas são apenas algumas das possíveis abordagens dentro da situação.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solução para o carregamento excessivo de dados com includes&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;Podemos trocar o uso de includes por joins porque:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Não carrega associações desnecessárias.&lt;/li&gt;
&lt;li&gt;Apenas filtra os registros.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Isso reduz o uso de memória significativamente.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solução para a falta de filtros essenciais na query&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;Podemos mover todas as condições do código para filtros na nossa query:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;verified: true - antes era customer.verified? em Ruby.&lt;/li&gt;
&lt;li&gt;status: [...] - para garantir apenas clientes pré-aprovados.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;E, ao tentar utilizar os índices existentes no banco para as tabelas customers e customer_attributes.&lt;/p&gt;

&lt;p&gt;Agora temos uma query um pouco maior em linhas de código, porém mais eficiente (traz apenas as contas que deveríamos atuar).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resultado&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;customer_ids&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Customer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;with_verification_request&lt;/span&gt;
                       &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;joins&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:customer_attributes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                       &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'customer_attributes.key = "verification_due_date"'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                       &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'customer_attributes.value &amp;lt; ?'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;days&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_now&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                       &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;verified: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                       &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;status: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'approved'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'active'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'processing'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
                       &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'NOT EXISTS(
                         SELECT 1 FROM customer_attributes ca
                         WHERE ca.customer_id = customers.id
                         AND ca.key = "disabled_subaccount"
                         AND customers.parent_id IS NOT NULL
                       )'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                       &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pluck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'customers.id'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Essa é a query final, com algumas observações:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Estamos buscando e selecionando apenas os IDs dos clientes com pluck('customers.id'). Agora, a variável que vamos iterar é apenas um &lt;em&gt;array&lt;/em&gt; de IDs: customer_ids.&lt;/li&gt;
&lt;li&gt;Na iugu, um cliente pode ter subcontas associadas a ele. Por isso, temos uma subquery para excluir clientes com subcontas desabilitadas.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Comparando o tamanho dos dois &lt;em&gt;arrays&lt;/em&gt; que deveríamos iterar:&lt;/p&gt;

&lt;p&gt;Query velha (com &lt;code&gt;customers&lt;/code&gt; sendo carregados em memória):&lt;br&gt;
&lt;a href="https://media2.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%2Fattvv24p2fkf073obxgu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fattvv24p2fkf073obxgu.png" alt=" " width="510" height="80"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Query nova (apenas os &lt;code&gt;ids&lt;/code&gt;):&lt;br&gt;
&lt;a href="https://media2.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%2Fgpo6sw0gy0j0voa8mlzz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fgpo6sw0gy0j0voa8mlzz.png" alt=" " width="570" height="74"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Na data de escrita deste artigo, temos um array aproximadamente 7,5 vezes menor que o antigo, e cada um desses itens agora é um dado muito mais simples: um ID.&lt;/p&gt;
&lt;h2&gt;
  
  
  Falta de granularidade nos processos para cada conta encontrada
&lt;/h2&gt;

&lt;p&gt;O problema aqui era que, se uma exceção ocorresse durante o processamento de uma conta, toda a task falhava e era reiniciada pelo Sidekiq. Na reinicialização, a query era executada novamente, retornando as mesmas contas, incluindo aquela que havia falhado, causando um loop de reinicializações. Enquanto isso, clientes que já haviam sido processados com sucesso recebiam e-mails repetidos.&lt;/p&gt;

&lt;p&gt;A ideia aqui foi bem simples: quebrar o processamento em unidades menores e independentes.&lt;/p&gt;

&lt;p&gt;Ao invés de processar tudo em um único loop, decidimos adicionar um worker para performar a operação necessária para cada uma das contas dentro do array de IDs. Essa abordagem traz vantagens como:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Isolamento de falhas&lt;/strong&gt;: Se o processamento de uma conta específica falhar, apenas o worker responsável por ela será afetado, e não a task inteira. Os demais workers continuarão a processar suas respectivas contas sem interrupção.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Retry independente&lt;/strong&gt;: O Sidekiq pode re-tentar apenas o worker que falhou, sem a necessidade de reprocessar todo o lote de clientes. Isso economiza recursos e evita o envio repetido de comunicações para clientes já processados.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fomos disso:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomersPendingVerificationTask&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Sidekiq&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Worker&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;perform&lt;/span&gt;
    &lt;span class="n"&gt;accounts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="c1"&gt;# Antiga query onerosa&lt;/span&gt;

    &lt;span class="n"&gt;accounts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="k"&gt;next&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_verified?&lt;/span&gt;
      &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Cmd&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Account&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Documents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt; &lt;span class="c1"&gt;# Processo onde era possível acontecer uma exceção&lt;/span&gt;
      &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:all_documents_valid&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;          &lt;span class="no"&gt;AccountNotificationMailerWorker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;perform_async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:pending_documents&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# Disparo do e-mail&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="o"&gt;...&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para isso:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomersPendingVerificationTask&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Sidekiq&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Worker&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;perform&lt;/span&gt;
    &lt;span class="n"&gt;customer_ids&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="c1"&gt;# Query otimizada...&lt;/span&gt;

    &lt;span class="n"&gt;customer_ids&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="no"&gt;CustomerPendingVerificationWorker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;perform_async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O código do Worker criado agora possui o processamento necessário para verificar os documentos do cliente.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomerPendingVerificationWorker&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Sidekiq&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Worker&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;perform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;customer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Customer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;id: &lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;present?&lt;/span&gt;

    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Services&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Customer&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;VerificationChecker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;

    &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:verification_complete&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="no"&gt;NotificationMailerWorker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;perform_async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:pending_verification&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E isso por si só, matou o problema dos múltiplos disparos repetidos, e também o gasto desnecessário com comunicações extras que estava fora do radar.&lt;/p&gt;

&lt;p&gt;Um bônus adicionado aqui foi monitoria, coloquei TaskLogs para: registrar execução e identificar ínicio e final do processo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomersPendingVerificationTask&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Sidekiq&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Worker&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;perform&lt;/span&gt;
    &lt;span class="n"&gt;start_task&lt;/span&gt;

    &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="c1"&gt;# Query e chamada do worker&lt;/span&gt;

    &lt;span class="n"&gt;finish_task&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="kp"&gt;private&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;start_task&lt;/span&gt;
    &lt;span class="no"&gt;TaskLog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start_batch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="ss"&gt;task_name: &lt;/span&gt;&lt;span class="s1"&gt;'CustomersPendingVerificationTask'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;batch_id: &lt;/span&gt;&lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;target_type: &lt;/span&gt;&lt;span class="s2"&gt;"Customer"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;finish_task&lt;/span&gt;
    &lt;span class="no"&gt;TaskLog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;finish_batch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="ss"&gt;task_name: &lt;/span&gt;&lt;span class="s1"&gt;'CustomersPendingVerificationTask'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;batch_id: &lt;/span&gt;&lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;target_type: &lt;/span&gt;&lt;span class="s2"&gt;"Customer"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com isso finalizo com a ideia de que, uma pequena refatoração em dois arquivo pode salvar uma boa grana e dor de cabeça com base de clientes.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>ruby</category>
      <category>rails</category>
      <category>refactoring</category>
    </item>
    <item>
      <title>Ideia</title>
      <dc:creator>Yury Cavalcante</dc:creator>
      <pubDate>Thu, 18 Apr 2024 23:09:11 +0000</pubDate>
      <link>https://dev.to/cavalcanteyury/ideia-17gm</link>
      <guid>https://dev.to/cavalcanteyury/ideia-17gm</guid>
      <description>&lt;p&gt;Ideia&lt;/p&gt;

&lt;p&gt;Uma plataforma que possua comunidades. Em essência, uma comunidade é um&lt;br&gt;
conglomerado de contas que praticam um X esporte/prática em N endereços.&lt;br&gt;
Usuários vão utilizar para achar comunidadese no que adentrararem numa comunidade Y,&lt;br&gt;
será criada uma Conta para o usuário que representa a participação do Usuário na Comunidade Y.&lt;br&gt;
Comunidades são criadas por uma Conta de um Usuário, que podem escolher aceitar ou não a Conta que está tentando adentrar.&lt;br&gt;
A Conta criadora de uma comunidade possui um "cargo" de dono da comunidade, enquanto os participantes terão cargo de "Membro"&lt;/p&gt;

&lt;h1&gt;
  
  
  ---------------------------------------
&lt;/h1&gt;

&lt;p&gt;Requerimentos obrigatórios para uma Comunidade existir&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nome da comunidade&lt;/li&gt;
&lt;li&gt;Ao menos um endereço&lt;/li&gt;
&lt;li&gt;Ao menos um usuário&lt;/li&gt;
&lt;li&gt;Ao menos uma prática informada&lt;/li&gt;
&lt;li&gt;Timeline com posts dos usuários&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Requerimentos opcionais&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Descrição&lt;/li&gt;
&lt;li&gt;Imagem de "perfil" da comunidade&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ideias de validações para uma comunidade legítima&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Endereço deve ser um local público&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  --------------------------------------
&lt;/h1&gt;

&lt;p&gt;Requerimentos obrigatórios para um Usuário existir&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nome&lt;/li&gt;
&lt;li&gt;Sobrenome&lt;/li&gt;
&lt;li&gt;E-mail&lt;/li&gt;
&lt;li&gt;CPF&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Requerimentos opcionais&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Endereço&lt;/li&gt;
&lt;li&gt;Ao menos uma prática informada&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ideias de validações para um Usuário legítimo&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Validação do CPF&lt;/li&gt;
&lt;li&gt;Validação do e-mail&lt;/li&gt;
&lt;li&gt;Validação do endereço&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  -------------------------------------
&lt;/h1&gt;

&lt;p&gt;Requerimentos obrigatórios para uma Conta existir&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cargo&lt;/li&gt;
&lt;li&gt;Permissões&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  -------------------------------------
&lt;/h1&gt;

&lt;p&gt;Requerimentos obrigatórios para uma Prática existir&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nome&lt;/li&gt;
&lt;li&gt;Categoria (E-sport, Esporte, Exercício, etc)&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  -------------------------------------
&lt;/h1&gt;

&lt;p&gt;O usuário se cadastra na plataforma&lt;br&gt;
O usuário com apenas informações obrigatórias terá acesso a comunidades com maior média de pessoas e práticas&lt;br&gt;
O usuário com informações opcionais (endereço e uma prática informada) terá acesso a comunidades perto do endereço e práticas cadastradas.&lt;/p&gt;

&lt;p&gt;O Usuário que criar uma Comunidade, terá uma Conta atrelada a Comunidade criada e sua Conta com cargo de Dono e permissões de Dono.&lt;br&gt;
O Usuário pode pedir para entrar uma Comunidade, caso permitido terá uma Conta atrelada a Comunidade e com cargo de Membro com permissões de Membro.&lt;br&gt;
O Usuário pode ter N Contas (Ou seja, participar de múltiplas comunidades)&lt;br&gt;
O Usuário pode interagir na timeline da Comunidade, bem semelhante ao Twitter. (necessário detalhar como será elaborado as mensagens dos usuários nessa timeline)&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Priority Queue em Ruby</title>
      <dc:creator>Yury Cavalcante</dc:creator>
      <pubDate>Thu, 04 Apr 2024 00:18:04 +0000</pubDate>
      <link>https://dev.to/cavalcanteyury/priority-queue-em-ruby-5b1g</link>
      <guid>https://dev.to/cavalcanteyury/priority-queue-em-ruby-5b1g</guid>
      <description>&lt;p&gt;Estive estudando o básico de estrutura de dados e algoritmos novamente durante &lt;a href="https://www.twitch.tv/dragaodeinkomodo"&gt;minhas streams&lt;/a&gt;, meus estudos acabaram casando com um &lt;a href="https://www.youtube.com/watch?v=4Gr4LozxccY"&gt;vídeo do Augusto Galego sobre otimizar uma solução de um desafio Leetcode&lt;/a&gt; utilizando a estrutura de dados Heap.&lt;/p&gt;

&lt;p&gt;No vídeo o Augusto resolve usando a própria lib nativa do Python. Em Ruby não existe Heap nativo, porém, existe &lt;a href="https://www.rubydoc.info/github/kanwei/algorithms/Containers/PriorityQueue"&gt;essa lib de algoritmos do Kanwei&lt;/a&gt;. Nela temos as estruturas abstratas e concretas: Priority Queues, Heap (min e max), Stack e etc.&lt;/p&gt;

&lt;p&gt;Decidi fazer minha implementação de Priority Queue usando Min Heap/Max Heap, mas antes de sairmos falando sobre a implementação vamos definir o que são essas estruturas que estamos tanto falando, Heap pra lá, Priority Queue pra cá...&lt;/p&gt;

&lt;p&gt;Ah, e todo esse processo foi gravado durante uma stream. Se te interessar está &lt;a href="https://www.twitch.tv/videos/2110835876"&gt;aqui&lt;/a&gt; os links.&lt;/p&gt;

&lt;h3&gt;
  
  
  Priority Queue
&lt;/h3&gt;

&lt;p&gt;Uma estrutura de dados abstrata. Quase idêntica ao conceito de Queues (FIFO), porém, a saída de um elemento da Priority Queue respeita uma prioridade contida em cada elemento da fila.&lt;/p&gt;

&lt;h3&gt;
  
  
  Heap
&lt;/h3&gt;

&lt;p&gt;A estrutura de dados que vamos utilizar na Priority Queue. Ela é uma árvore binária balanceada, e podemos representar ela com um array pra tornar as funções da fila possíveis. Dada a seguinte árvore binária:&lt;/p&gt;

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

&lt;p&gt;Representamos com o seguinte array:&lt;br&gt;
&lt;code&gt;[2, 10, 12, 122, 13, 100]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Nota-se que os números azuis na imagem é o index dos arrays.&lt;br&gt;
E a imagem também nos leva ao próximo tópico sobre Heaps...&lt;/p&gt;
&lt;h3&gt;
  
  
  Min/Max Heap
&lt;/h3&gt;

&lt;p&gt;Uma heap pode ordenar sua árvore do menor para o maior como na imagem do tópico acima, chamamos de Min Heap. Mas também pode ser possível ordená-la de forma crescente:&lt;/p&gt;

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

&lt;p&gt;Acima, o exemplo de uma Max Heap, que ficaria assim num array&lt;br&gt;
&lt;code&gt;[122, 13, 100, 2, 10, 12]&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Inserindo elementos na Heap
&lt;/h3&gt;

&lt;p&gt;Sempre que formos inserir um novo elemento na árvore (ou no array se preferir), temos que rebalancear a árvore caso necessário. Se inserirmos um elemento 6 (com prioridade 6), ela ficaria desbalanceada. O que nos leva a necessidade de compararmos o elemento pai do recém inserido, fazendo um processo chamado de &lt;strong&gt;bubble up&lt;/strong&gt; (ou &lt;strong&gt;sift up&lt;/strong&gt;, &lt;strong&gt;heap up&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Elemento pai maior? 

&lt;ul&gt;
&lt;li&gt;Sim? Trocamos de posição o elemento inserido com o pai. (Fazer esse passo até resposta negativa)&lt;/li&gt;
&lt;li&gt;Não? Finalizamos o processo, temos uma árvore balanceada pós push.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Removendo elementos da heap
&lt;/h3&gt;

&lt;p&gt;Quando removemos um item da heap, vamos rebalancear da mesma forma. Trocamos o elemento da raiz da Heap com o último elemento (index 0 com o último index do array), removemos o último elemento do array e então vamos para o processo de descer o elemento da raíz até o seu devido lugar na árvore chamado de &lt;strong&gt;bubble down&lt;/strong&gt; (ou &lt;strong&gt;sift down&lt;/strong&gt;, &lt;strong&gt;heap down&lt;/strong&gt;):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Elementos filhos esquerdo ou direito menor?

&lt;ul&gt;
&lt;li&gt;Sim? Priorizar o filho que tiver menor valor contido. Repetir esse passo até resposta negativa.&lt;/li&gt;
&lt;li&gt;Não? Processo finalizado e temos uma árvore balanceada.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;
  
  
  Implementação
&lt;/h1&gt;

&lt;p&gt;Esse com certeza não é o código mais performático de uma Priority Queue, estou compartilhadno e usando tanto este post quanto &lt;a href="https://www.twitch.tv/videos/2110835876"&gt;minha stream&lt;/a&gt; como forma de documentar o aprendizado. Pretendo melhorar o código e ele está disponível no repositório de estudos de algorimos no meu github. Isso obviamente não quer dizer que não estou sucinto a comentários sugerindo melhorias, todos são muito bem vindos! :)&lt;/p&gt;
&lt;h3&gt;
  
  
  Os elementos
&lt;/h3&gt;

&lt;p&gt;Criei uma classe que representaria os elementos da Heap, e nele temos duas importantes coisas a se notar.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Element&lt;/span&gt;
  &lt;span class="nb"&gt;attr_accessor&lt;/span&gt; &lt;span class="ss"&gt;:data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:priority&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;priority&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="vi"&gt;@priority&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;priority&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;&amp;lt;&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elem&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@priority&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;elem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;priority&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;É possível inicializar um elemento com uma prioridade customizável, mas caso não é inicializada com a prioridade explícita, usaremos o próprio dado como prioridade. Isso vai nos ajudar na criação de uma Heap com inteiros por exemplo: um &lt;code&gt;Element.new(10)&lt;/code&gt; já define o elemento 10 com prioridade 10.&lt;/li&gt;
&lt;li&gt;Uma forte característica da Heap é que estaremos comparando o tempo todo os elementos (maior que, menor que). Criamos uma função que sobreescreve o spaceship operator (&lt;code&gt;&amp;lt;=&amp;gt;&lt;/code&gt;). O que ele faz é simples:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="c1"&gt;#  se a &amp;lt; b retorna -1&lt;/span&gt;
&lt;span class="c1"&gt;#  se a = b retorna 0&lt;/span&gt;
&lt;span class="c1"&gt;#  se a &amp;gt; b retorna return  1&lt;/span&gt;
&lt;span class="c1"&gt;#  se a e b não são comparáveis, retorna nil&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quando utilizarmos &lt;code&gt;element1 &amp;lt;=&amp;gt; element2&lt;/code&gt; ele vai nos retornar um desses 4 valores. Esse valor vai determinar a posição de um elemento após ser removido da fila, ou enfileirado. Isso vai nos ajudar na lógica de &lt;strong&gt;bubble up&lt;/strong&gt; ou &lt;strong&gt;bubble down&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  A Priority Queue
&lt;/h3&gt;

&lt;p&gt;Vamos por partes...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PriorityQueue&lt;/span&gt;
  &lt;span class="nb"&gt;attr_accessor&lt;/span&gt; &lt;span class="ss"&gt;:elements&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elements&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@elements&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;elements&lt;/span&gt;
    &lt;span class="vi"&gt;@compare&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;left_el&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right_el&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left_el&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;right_el&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;size&lt;/span&gt;
    &lt;span class="vi"&gt;@elements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E aqui é onde o spaceship operator entra em ação. A lambda utilizando o order com 1 negativo quer dizer que sempre que compararmos um valor menor com um maior, retornará true. Isso nos garante que ao compararmos o elemento com um pai por exemplo, ele vai retornar true caso precise trocar&lt;/p&gt;

&lt;h3&gt;
  
  
  Enfileirando...
&lt;/h3&gt;

&lt;p&gt;Ao enfileirar um elemento na Priority Queue, veremos se é necessário o processo de bubble up. A vantagem de traduzirmos a árvore binária para um array é que conseguimos computar facilmente o parente daquele elemento inserido. Existe a fórmula pronta pra conseguir o index do parente, do filho da esquerda e da direita. No caso de enfileiras vamos usar só a fórmula do parente.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;PARENT = (TARGET_EL_INDEX - 1) / 2&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# Insert new element into array&lt;/span&gt;
    &lt;span class="vi"&gt;@elements&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt;

    &lt;span class="c1"&gt;# Get the inserted element index&lt;/span&gt;
    &lt;span class="n"&gt;target_index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

    &lt;span class="c1"&gt;# Get the parent from the inserted index&lt;/span&gt;
    &lt;span class="n"&gt;parent_index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target_index&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;

    &lt;span class="c1"&gt;# Here, we use compare lambda to make sure we always swap the parent with the inserted element, to respect the min heap property (The child priority must be greater than parent's priority)&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="vi"&gt;@compare&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@elements&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;target_index&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="vi"&gt;@elements&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;parent_index&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
      &lt;span class="c1"&gt;# parent greater than child? swap it&lt;/span&gt;
      &lt;span class="n"&gt;swap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target_index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parent_index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="c1"&gt;# update the respective indexes if next @compare.call succeeds&lt;/span&gt;
      &lt;span class="n"&gt;target_index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;parent_index&lt;/span&gt;

      &lt;span class="n"&gt;parent_index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target_index&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nota-se que a order da PriorityQueue vai seguir a padrão (-1), ou seja, uma Min Heap.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pop, pop, pop
&lt;/h3&gt;

&lt;p&gt;Para o processo de bubble down, vamos usar as duas fórmulas pra encontrar o filho da esquerda e o filho da direita do elemento que precisa descer na árvore.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;LEFT_CHILD = 2 * (TARGET_EL_INDEX) + 1&lt;/code&gt;&lt;br&gt;
&lt;code&gt;RIGHT_CHILD = 2 * (TARGET_EL_INDEX) + 2&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pop&lt;/span&gt;
    &lt;span class="c1"&gt;# swap the binary tree root with the last element&lt;/span&gt;
    &lt;span class="n"&gt;swap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# remove last element from queue&lt;/span&gt;
    &lt;span class="vi"&gt;@elements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;

    &lt;span class="c1"&gt;# computations to reach the left/right child&lt;/span&gt;
    &lt;span class="n"&gt;target_index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;left_index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;target_index&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;right_index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;target_index&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;

    &lt;span class="c1"&gt;# here we start the bubbling up procedure and we dont stop until our childs elements is greater than its parents&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left_index&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="vi"&gt;@compare&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@elements&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;left_index&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="vi"&gt;@elements&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;target_index&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;right_index&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="vi"&gt;@elements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="vi"&gt;@compare&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@elements&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;right_index&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="vi"&gt;@elements&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;target_index&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
      &lt;span class="c1"&gt;# if right and left child holds the same priority, then we use the data contained into it to decide which is smaller&lt;/span&gt;
      &lt;span class="n"&gt;smallest_index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;right_index&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="vi"&gt;@elements&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;left_index&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;data&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="vi"&gt;@elements&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;right_index&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;data&lt;/span&gt;
                         &lt;span class="n"&gt;left_index&lt;/span&gt;
                       &lt;span class="k"&gt;else&lt;/span&gt;
                         &lt;span class="n"&gt;right_index&lt;/span&gt;
                       &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="c1"&gt;# we swap it boooyyy&lt;/span&gt;
      &lt;span class="n"&gt;swap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target_index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;smallest_index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="c1"&gt;# update indexes in case this was not the last swap we needed it&lt;/span&gt;
      &lt;span class="n"&gt;target_index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;smallest_index&lt;/span&gt;
      &lt;span class="n"&gt;left_index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;target_index&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
      &lt;span class="n"&gt;right_index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;target_index&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Amostras &amp;amp; conclusões
&lt;/h3&gt;

&lt;p&gt;Vamos lá...&lt;br&gt;
Criei um método inspect dentro da class PriorityQueue pra ficar fácil o debugging.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;inspect&lt;/span&gt;
    &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;el&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="vi"&gt;@elements&lt;/span&gt;
      &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;res&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E voilà:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;irb&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;min_heap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

&lt;span class="n"&gt;min_heap&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;min_heap&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;min_heap&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;min_heap&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;min_heap&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;min_heap&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;min_heap&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;pq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;PriorityQueue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min_heap&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;pq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;pq&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;pq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;pq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;pq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;pq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;pq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;pq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;pq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;pq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;pq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Na stream procurei fazer os testes e esse debugging usando excalidraw pra facilitar o entendimento dos resultados.&lt;/p&gt;

&lt;p&gt;Pretendo melhorar esse código, colocar novos métodos (por exemplo um pop que tem index como argumento). Se te interessar, pode ficar ligado no meu github e nas streams. Até mais ver. o/&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>leetcode</category>
      <category>learning</category>
      <category>algorithms</category>
    </item>
    <item>
      <title>É necessário voltar ao começo</title>
      <dc:creator>Yury Cavalcante</dc:creator>
      <pubDate>Wed, 03 Apr 2024 15:22:53 +0000</pubDate>
      <link>https://dev.to/cavalcanteyury/e-necessario-voltar-ao-comeco-gag</link>
      <guid>https://dev.to/cavalcanteyury/e-necessario-voltar-ao-comeco-gag</guid>
      <description>&lt;p&gt;&lt;em&gt;"[...] Que é necessário voltar ao começo&lt;br&gt;
Quando os caminhos se confundem, é necessário voltar ao começo&lt;br&gt;
Não sabe pra onde ir? Tem que voltar pro começo&lt;br&gt;
Pra não perder o rumo, não pode esquecer do começo&lt;br&gt;
Cê entende, que assim é verdadeiro? ...&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Apresentando
&lt;/h2&gt;

&lt;p&gt;Olá, espero que encontre esse texto num momento bom da sua vida. Sente-se comigo e vamos lá.&lt;/p&gt;

&lt;p&gt;Este é um post de contexto tech, mas eu tenho alguns adendos antes de prosseguir a parte técnica dele. Faz uma semana que me encontro desempregado e nos primeiros dias tive pensamentos suicidas algumas vezes. Pra pessoas próximas que acabaram tropeçando nisso aqui e continuam lendo: eu estou bem agora! Não se preocupem. O motivo (por inteiro) não foi o desemprego.&lt;/p&gt;

&lt;p&gt;Me encontrei sem significado em existir, e percebi que fui muito perverso em resumir minha existência no profissional, e desde então decidi recomeçar tudo. Quero encontrar o brilho nos meus olhos na área novamente e acho que, se você que é de  tecnologia e já questionou muitas vezes seu existir talvez seja interessante continuar aqui.&lt;/p&gt;

&lt;p&gt;Não pretendo ser prepotente, é uma escrita em forma de desabafo com uma continuidade em aprendizado. Então vamos lá. &lt;/p&gt;

&lt;p&gt;Prazer, Yury, vou estar estudando o que considero de faltante em minha carreira e vou compartilhar nos posts a seguir. Esse é o primeiro deles. Pensei em muitos projetos mirabolantes a serem feitos mas decidi por estudar ESTRUTURA DE DADOS e ALGORITMOS. Simplesmente porque sempre admirei pessoas que tinham essa base forte e bem enraizada. E eu quero me tornar uma dessas pessoas. Me admiro por muitos outros pontos e acho que esse deverá ser um deles no futuro!&lt;/p&gt;

&lt;h2&gt;
  
  
  Aprendendo a andar novamente
&lt;/h2&gt;

&lt;p&gt;Após meditar muito sobre o que fazer nos próximos dias, eu iniciei o estudo e ao mesmo tempo parei de utilizar VSCode como editor de código. Sempre tive vontade de adquirir eficiência e velocidade durante minhas sessões de coding e optei por Doom Emacs.&lt;/p&gt;

&lt;p&gt;Estive consumindo conteúdo sobre estrutura de dados, algoritmos,&lt;br&gt;
 programação competitiva e leetcodes. Acho que é a base que me falta. Tenho boas ideias de negócio e de system design, mas eu não consigo discutir os pormenores dessas implementações por falta de jargão e experiência em algoritmos. Então nessa primeira semana eu implementei em Ruby, algumas estruturas de dados tanto abstratas quanto concretas.&lt;/p&gt;

&lt;p&gt;Esse é o pontapé inicial dos textos semanais que quero fazer sobre o meu tempo desempregado e o que estarei aprendendo, os próximos terão mais discussões técnicas e decisões que tenho tomado em relação a elas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Até mais ver
&lt;/h2&gt;

&lt;p&gt;Agradeço primeiramente a mim por ter considerado escrever isso, e segundamente a todos que estão estimando pelo meu bem nessa caminhada.&lt;/p&gt;

&lt;p&gt;Os estudos dessa semana me fizeram me sentir muito bem, já sinto estar entendendo as coisas melhor, mesmo em pequena porcentagem. Então, se você se identificou minimamente até aqui, te digo: de vez em quando é necessário voltar ao começo, independente da onde estiver.&lt;/p&gt;

&lt;p&gt;E por último, não menos importante, para todos ao meu redor que zelam por mim: Vocês me movem. É o grande motivo d’eu estar escrevendo isso aqui e me reerguendo.&lt;/p&gt;

</description>
      <category>learning</category>
      <category>career</category>
      <category>ruby</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
