One place for hosting & domains

      Adicionar

      Como adicionar espaço de swap no Ubuntu 20.04


      Introdução

      Um das maneiras de se proteger contra erros de memória insuficiente em aplicativos é através da adição de um espaço de swap ao seu servidor. Neste guia, falaremos sobre como adicionar um arquivo swap a um servidor Ubuntu 20.04.

      Aviso: embora o swap seja geralmente recomendado para sistemas que utilizam discos rígidos tradicionais, o uso do swap em SSDs pode causar problemas de degradação de hardware ao longo do tempo. Por este motivo, não recomendamos a habilitação do swap na DigitalOcean ou em qualquer outro provedor que utilize armazenamento SSD.

      O que é o Swap?

      O Swap é uma parcela do armazenamento do disco rígido que foi reservada para o sistema operacional com o objetivo de armazenar temporariamente dados que ele não consegue mais reter na RAM. Isso permite que você aumente a quantidade de informações que seu servidor consegue manter em sua memória de trabalho, com algumas advertências. O espaço de swap no disco rígido será usado principalmente quando já não houver espaço suficiente em RAM para manter os dados do aplicativo em uso.

      As informações gravadas no disco ficarão significativamente mais lentas do que as informações mantidas em RAM, mas o sistema operacional preferirá manter os dados do aplicativo em memória e usar o swap para os dados mais antigos. De maneira geral, ter espaço de swap como uma alternativa para quando a RAM do seu sistema estiver esgotada pode ser uma boa estratégia de segurança contra exceções de memória insuficiente nos sistemas com armazenamento disponível que não seja SSD.

      Passo 1 – Verificando o Sistema em Relação às Informações de Swap (troca)

      Antes de começarmos, podemos verificar se o sistema já tem algum espaço de swap (troca) disponível. É possível ter vários arquivos de swap ou partições de swap, mas geralmente um deve ser o suficiente.

      Podemos descobrir se o sistema tem algum swap configurado digitando:

      Se você não receber nenhum resultado, isso significa que seu sistema não tem espaço de swap disponível atualmente.

      Você pode verificar se não existe um swap ativo usando o utilitário free:

      Output

      total used free shared buff/cache available Mem: 981Mi 122Mi 647Mi 0.0Ki 211Mi 714Mi Swap: 0B 0B 0B

      Como você pode ver na linha Swap do resultado, nenhum swap está ativo no sistema.

      Passo 2 – Verificando o Espaço Disponível na Partição do Disco Rígido

      Antes de criarmos nosso arquivo de swap, verificaremos o uso atual do disco para garantir que temos espaço suficiente. Faça isso digitando:

      Output

      Filesystem Size Used Avail Use% Mounted on udev 474M 0 474M 0% /dev tmpfs 99M 932K 98M 1% /run /dev/vda1 25G 1.4G 23G 7% / tmpfs 491M 0 491M 0% /dev/shm tmpfs 5.0M 0 5.0M 0% /run/lock tmpfs 491M 0 491M 0% /sys/fs/cgroup /dev/vda15 105M 3.9M 101M 4% /boot/efi /dev/loop0 55M 55M 0 100% /snap/core18/1705 /dev/loop1 69M 69M 0 100% /snap/lxd/14804 /dev/loop2 28M 28M 0 100% /snap/snapd/7264 tmpfs 99M 0 99M 0% /run/user/1000

      O dispositivo com / na coluna Mounted on é o nosso disco neste caso. Temos bastante espaço disponível neste exemplo (apenas 1,4 GB usado). Seu uso provavelmente será diferente.

      Apesar da divergência de opiniões quanto ao tamanho adequado de um espaço de swap, isso realmente dependerá de suas preferências pessoais e das exigências da sua aplicação. Geralmente, um espaço igual ou duas vezes o tamanho do espaço da RAM no seu sistema é um bom ponto de partida. Outra boa regra de ouro é que qualquer coisa acima de 4 GB de swap é provavelmente desnecessária se você somente estiver usando-o como uma alternativa para a RAM.

      Passo 3 – Criando um Arquivo de Swap

      Agora que sabemos qual é o espaço disponível em nosso disco rígido, podemos criar um arquivo de swap no nosso sistema de arquivos. Alocaremos um arquivo do tamanho que queremos que o swap tenha chamado de swapfile em nosso diretório raiz (/).

      A melhor maneira de criar um arquivo de swap é com o programa fallocate. Este comando cria instantaneamente um arquivo do tamanho especificado.

      Uma vez que o servidor no nosso exemplo tem 1 GB de RAM, criaremos um arquivo de 1 GB neste guia. Ajuste isso para atender às necessidades do seu próprio servidor:

      • sudo fallocate -l 1G /swapfile

      Podemos verificar se a quantidade correta de espaço foi reservada digitando:

      • -rw-r--r-- 1 root root 1.0G Apr 25 11:14 /swapfile

      Nosso arquivo foi criado com a quantidade correta do espaço reservado.

      Passo 4 – Habilitando o Arquivo de Swap

      Agora que temos um arquivo do tamanho correto disponível, precisamos realmente transformar isso em espaço de swap.

      Primeiro, precisamos bloquear as permissões do arquivo para que apenas os usuários com privilégios root possam ler o conteúdo. Isso impede que os usuários normais possam acessar o arquivo, o que teria implicações de segurança significativas.

      Torne o arquivo acessível somente para root digitando:

      Verifique a alteração de permissões digitando:

      Output

      -rw------- 1 root root 1.0G Apr 25 11:14 /swapfile

      Como você pode ver, apenas o usuário root tem os sinalizadores de leitura e gravação habilitados.

      Podemos agora marcar o arquivo como espaço de swap digitando:

      Output

      Setting up swapspace version 1, size = 1024 MiB (1073737728 bytes) no label, UUID=6e965805-2ab9-450f-aed6-577e74089dbf

      Após marcar o arquivo, podemos habilitar o arquivo de swap, permitindo que nosso sistema comece a utilizá-lo:

      Verifique se o swap está disponível digitando:

      Output

      NAME TYPE SIZE USED PRIO /swapfile file 1024M 0B -2

      Podemos verificar a saída do utilitário free novamente para corroborar nossos resultados:

      Output

      total used free shared buff/cache available Mem: 981Mi 123Mi 644Mi 0.0Ki 213Mi 714Mi Swap: 1.0Gi 0B 1.0Gi

      Nosso swap foi configurado com sucesso e nosso sistema operacional começará a usá-lo conforme necessário.

      Passo 5 – Tornando o Arquivo de Swap Permanente

      Nossas alterações recentes habilitaram o arquivo de swap para a sessão atual. No entanto, se reiniciarmos, o servidor não manterá as configurações de swap automaticamente. Podemos alterar isso adicionando o arquivo de swap ao nosso arquivo /etc/fstab.

      Faça um backup do arquivo /etc/fstab para o caso de algo dar errado:

      • sudo cp /etc/fstab /etc/fstab.bak

      Adicione a informação do arquivo de swap no final do seu arquivo /etc/fstab digitando:

      • echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

      Em seguida, avaliaremos algumas configurações que podemos atualizar para ajustar nosso espaço de swap.

      Passo 6 – Ajustando as Configurações de Swap

      Há algumas opções que você pode configurar que terão um impacto no desempenho do seu sistema quando estiver lidando com o swap.

      Ajustando a propriedade Swappiness

      O parâmetro swappiness configura a frequência com que o seu sistema transfere dados da RAM para o espaço de swap. Esse é um valor entre 0 e 100 que representa uma porcentagem.

      Com valores próximos de zero, o kernel não irá transferir dados para o disco a menos que seja absolutamente necessário. Lembre-se, as interações com o arquivo de swap são “dispendiosas”, no sentido de que demoram mais que as interações com a RAM e podem causar uma redução significativa no desempenho. Dizer ao sistema para não depender tanto do swap irá geralmente tornar o seu sistema mais rápido.

      Valores que estão mais próximos de 100 irão tentar colocar mais dados no swap em um esforço para manter mais espaço da RAM livre. Dependendo do perfil de memória de seus aplicativos ou do motivo pelo qual você está usando o seu servidor, isso pode ser melhor em alguns casos.

      Podemos ver o valor atual do parâmetro swappiness digitando:

      • cat /proc/sys/vm/swappiness

      Output

      60

      Para um desktop, um valor de swappiness de 60 não é um valor ruim. Para um servidor, você pode deixá-lo mais próximo de 0.

      Podemos definir o parâmetro swappiness para um valor diferente usando o comando sysctl.

      Por exemplo, para definir o valor do parâmetro swappiness em 10, poderíamos digitar:

      • sudo sysctl vm.swappiness=10

      Output

      vm.swappiness = 10

      Este valor persistirá até a próxima reinicialização. Podemos definir este valor automaticamente na reinicialização, adicionando a linha no nosso arquivo /etc/sysctl.conf:

      • sudo nano /etc/sysctl.conf

      No final, você pode adicionar:

      /etc/sysctl.conf

      vm.swappiness=10
      

      Salve e feche o arquivo quando você terminar.

      Ajustando a Configuração da Pressão por Cache

      Outro valor relacionado que você pode querer modificar é o vfs_cache_pressure. Este ajuste configura o quanto o sistema escolherá para as informações cache dos objetos inode e dentry em detrimento de outros dados.

      Basicamente, tratam-se de dados de acesso sobre o sistema de arquivos. De maneira geral, isso é difícil de consultar e, com frequência, muito solicitado. Assim, é algo muito bom que o seu sistema armazene dados em cache. Você pode ver o valor atual questionando o sistema de arquivos proc novamente:

      • cat /proc/sys/vm/vfs_cache_pressure

      Output

      100

      Uma vez que ele está atualmente configurado, o nosso sistema remove as informações de inode do cache muito rapidamente. Podemos definir isso em um valor mais conservador como 50, digitando:

      • sudo sysctl vm.vfs_cache_pressure=50

      Output

      vm.vfs_cache_pressure = 50

      Novamente, isso é apenas válido para a nossa sessão atual. Podemos alterar esse valor, adicionando-o ao nosso arquivo de configuração como fizemos com a nossa configuração do parâmetro swappiness:

      • sudo nano /etc/sysctl.conf

      No final, adicione a linha que especifica o seu novo valor:

      /etc/sysctl.conf

      vm.vfs_cache_pressure=50
      

      Salve e feche o arquivo quando você terminar.

      Conclusão

      Seguir as etapas deste guia lhe dará algum espaço para respirar em casos que de outra forma conduziriam a exceções de falta de memória. O espaço de swap pode ser incrivelmente útil para evitar alguns desses problemas comuns.

      Se você está encontrando erros de OOM (out of memory – falta de memória), ou se você descobrir que o seu sistema não consegue usar os aplicativos de que você precisa, a melhor solução é otimizar as configurações do seu aplicativo ou atualizar o seu servidor.



      Source link

      Como adicionar o teste de unidade ao seu projeto Django


      O autor selecionou a Open Internet/Free Speech Fund para receber uma doação como parte do programa Write for DOnations.

      Introdução

      É quase impossível desenvolver sites que funcionem perfeitamente na primeira vez, sem erro algum. Por este motivo, você deve testar seu aplicativo Web em busca de erros e trabalhar neles proativamente. Para melhorar a eficiência dos testes, é comum dividir os testes em unidades que testam funcionalidades específicas de um aplicativo Web. Esta prática é conhecida como teste de unidade. Esta prática facilita a detecção de erros, pois os testes focam em partes menores (unidades) do seu projeto, independentemente das outras.

      O teste de um site pode ser uma tarefa complexa de se realizar, pois um site é composto de várias camadas lógicas, como o processamento de solicitações HTTP, validação do formulário e renderização de modelos. No entanto, o Django fornece um conjunto de ferramentas que simplifica o teste de seu aplicativo Web. No Django, o melhor método de escrever os testes é através do uso do módulo unittest do Python, embora seja possível utilizar outros frameworks de teste.

      Neste tutorial, você configurará um conjunto de testes em seu projeto Django e escreverá os testes de unidade para os modelos e visualizações em seu aplicativo. Você executará esses testes, analisará os resultados e aprenderá como encontrar as causas das falhas dos testes.

      Pré-requisitos

      Antes de começar este tutorial será necessário:

      Passo 1 — Adicionando um conjunto de testes para seu aplicativo Django

      Um conjunto de teste é uma coleção de todos os casos de teste em todos os aplicativos em seu projeto. Para que seja possível que o utilitário de testes do Django descubra os casos de teste que você possui, escreva os casos de teste em scripts cujos nomes comecem com test. Neste passo você criará a estrutura do diretório e os arquivos para seu conjunto de testes e criará um caso de teste vazio nele.

      Se você seguiu o a série de tutoriais de desenvolvimento do Django, você terá consigo um aplicativo Django chamado blogsite.

      Vamos criar uma pasta para armazenar todos os nossos scripts de testes. Primeiro, ative o ambiente virtual:

      • cd ~/my_blog_app
      • . env/bin/activate

      Em seguida, vá até o diretório do aplicativo chamado blogsite. Esta é a pasta que contém os arquivos models.py e views.py. Crie nela uma nova pasta chamada tests:

      • cd ~/my_blog_app/blog/blogsite
      • mkdir tests

      Depois disso, você transformará esta pasta em um pacote Python. Por este motivo, adicione um arquivo __init__.py:

      • cd ~/my_blog_app/blog/blogsite/tests
      • touch __init__.py

      Agora, você adicionará um arquivo para testar seus modelos e outro arquivo para testar suas visualizações:

      • touch test_models.py
      • touch test_views.py

      Por fim, você criará um caso de teste vazio em test_models.py. Você precisará importar a classe Django TestCase e torná-la uma superclasse de sua própria classe de caso de teste. Mais à frente, você adicionará métodos para este caso de teste para testar a lógica em seus modelos. Abra o arquivo test_models.py​​​:

      Agora, adicione o código a seguir ao arquivo:

      ~/my_blog_app/blog/blogsite/tests/test_models.py

      from django.test import TestCase
      
      class ModelsTestCase(TestCase):
          pass
      

      Você adicionou um conjunto de testes ao aplicativo blogsite. Em seguida, você preencherá os detalhes do modelo do caso de teste vazio criado aqui.

      Passo 2 — Testando o código Python

      Neste passo você testará a lógica do código escrito no arquivo models.py. Você estará testando especificamente o método save do modelo Post para garantir que ele crie o campo de dados dinâmico correto do título de uma postagem quando ela for chamada.

      Vamos começar analisando o código que você já tem em seu arquivo models.py para o método save do modelo Post:

      • cd ~/my_blog_app/blog/blogsite
      • nano models.py

      Você verá o seguinte:

      ~/my_blog_app/blog/blogsite/models.py

      class Post(models.Model):
          ...
          def save(self, *args, **kwargs):
              if not self.slug:
                  self.slug = slugify(self.title)
              super(Post, self).save(*args, **kwargs)
          ...
      

      Como podemos ver, ele verifica se a postagem que está prestes a ser salva possui algum valor do campo de dados dinâmico. Se não tiver, ele chama o slugify para criar um valor do campo de dados dinâmico. Esta é lógica que queremos para testar e garantir que os campos de dados dinâmicos sejam criados ao salvar uma postagem.

      Feche o arquivo.

      Para testar isso, volte para o test_models.py:

      Em seguida, atualize-o para o seguinte, adicionando as partes destacadas:

      ~/my_blog_app/blog/blogsite/tests/test_models.py

      from django.test import TestCase
      from django.template.defaultfilters import slugify
      from blogsite.models import Post
      
      
      class ModelsTestCase(TestCase):
          def test_post_has_slug(self):
              """Posts are given slugs correctly when saving"""
              post = Post.objects.create(title="My first post")
      
              post.author = "John Doe"
              post.save()
              self.assertEqual(post.slug, slugify(post.title))
      

      Este novo método test_post_has_slug cria uma nova postagem com o título "My first post" e, em seguida, fornece um autor à postagem e a salva. Após isso, use o método assertEqual do módulo unittest do Python para verificar se o campo de dados dinâmico para a postagem está correto. O método assertEqual verifica se os dois argumentos passados a ele são iguais aos argumentos determinados pelo operador "==". Caso não sejam iguais, o método gera um erro.

      Salve e saia do test_models.py​​​.

      Este é um exemplo do que pode ser testado. Quanto mais lógica você adicionar ao seu projeto, mais conteúdo haverá para testar. É aconselhável que você crie mais testes caso adicione mais lógica ao método save ou crie novos métodos para o modelo Post. Você pode adicioná-los ao método test_post_has_slug ou criar novos métodos de teste, mas os nomes devem começar com test.

      Você criou um caso de teste para o modelo Post com êxito, onde você definiu que os campos de dados dinâmicos foram criados corretamente após salvar. No próximo passo você escreverá um caso de teste para testar as visualizações.

      Passo 3 — Utilizando o cliente de teste do Django

      Neste passo, você escreverá um caso de teste que testa uma visualização utilizando o cliente de testes do Django. O test client é uma classe Python que age como um navegador Web fictício. Ele permite que você teste suas visualizações e interaja com seu aplicativo Django da mesma forma que um usuário faria. Você pode acessar o cliente de teste referindo-se ao self.client em seus métodos de teste. Por exemplo, vamos criar um caso de teste em test_views.py. Primeiro, abra o arquivo test_views.py​​​:

      Depois, adicione o seguinte:

      ~/my_blog_app/blog/blogsite/tests/test_views.py

      from django.test import TestCase
      
      
      class ViewsTestCase(TestCase):
          def test_index_loads_properly(self):
              """The index page loads properly"""
              response = self.client.get('your_server_ip:8000')
              self.assertEqual(response.status_code, 200)
      

      O ViewsTestCase contém um método test_index_loads_properly que utiliza o cliente de teste do Django para visitar a página inicial do site (http://your_server_ip:8000, onde o your_server_ip é o endereço IP do servidor que você está utilizando). Em seguida, o método de teste verifica se a resposta tem um código de status 200, o que significa que a página respondeu sem erros. Pelo resultado do teste, podemos concluir que quando os usuários visitarem a página, ela responderá sem erros também.

      Além do código de status, você pode ler sobre outras propriedades da resposta do cliente de teste que você confere na página de respostas de testes da documentação do Django.

      Neste passo, você criou um caso de teste para conferir se a renderização da visualização da página inicial funciona sem erros. Agora, existem dois casos de teste em seu conjunto. No próximo passo, você os executará para ver os resultados.

      Passo 4 — Executando seus testes

      Agora que você terminou de desenvolver um conjunto de testes para o projeto, é hora de executá-los e ver os resultados. Para executar os testes, vá para a pasta blog (que contém o arquivo manage.py do aplicativo):

      Em seguida, execute-os com:

      Você verá um resultado parecido com o seguinte em seu terminal:

      Output

      Creating test database for alias 'default'... System check identified no issues (0 silenced). .. ---------------------------------------------------------------------- Ran 2 tests in 0.007s OK Destroying test database for alias 'default'...

      Neste resultado, existem dois pontos .., cada um dos quais representa um caso de teste aprovado. Agora, você modificará o test_views.py para acionar uma falha no teste. Primeiro, abra o arquivo com:

      Em seguida, altere o código destacado para:

      ~/my_blog_app/blog/blogsite/tests/test_views.py

      from django.test import TestCase
      
      
      class ViewsTestCase(TestCase):
          def test_index_loads_properly(self):
              """The index page loads properly"""
              response = self.client.get('your_server_ip:8000')
              self.assertEqual(response.status_code, 404)
      

      Aqui, você alterou o código de status de 200 para 404. Agora, execute o teste novamente do diretório com o manage.py:

      Você verá o seguinte resultado:

      Output

      Creating test database for alias 'default'... System check identified no issues (0 silenced). .F ====================================================================== FAIL: test_index_loads_properly (blogsite.tests.test_views.ViewsTestCase) The index page loads properly ---------------------------------------------------------------------- Traceback (most recent call last): File "~/my_blog_app/blog/blogsite/tests/test_views.py", line 8, in test_index_loads_properly self.assertEqual(response.status_code, 404) AssertionError: 200 != 404 ---------------------------------------------------------------------- Ran 2 tests in 0.007s FAILED (failures=1) Destroying test database for alias 'default'...

      Veja que existe uma mensagem de erro informando o script, o caso de teste e o método que falhou. Ele também diz a causa da falha, o código de status diferente de 404 neste caso, com a mensagem AssertionError: 200 ! = 404. O AssertionError é criado na linha de código destacada no arquivo test_views.py:

      ~/my_blog_app/blog/blogsite/tests/test_views.py

      from django.test import TestCase
      
      
      class ViewsTestCase(TestCase):
          def test_index_loads_properly(self):
              """The index page loads properly"""
              response = self.client.get('your_server_ip:8000')
              self.assertEqual(response.status_code, 404)
      

      Ele informa a você que a afirmação é falsa, ou seja, o código de status da resposta (200) não era o esperado (404). Antes da mensagem de falha, vemos que os dois pontos .. foram modificados para . F, que diz que o primeiro caso de teste foi aprovado enquanto o segundo falhou.

      Conclusão

      Neste tutorial, você criou um conjunto de testes em seu projeto Django, adicionou casos de teste para testar o modelo e a lógica de visualização. Também aprendeu como executar testes e analisou o resultado deles. Como um próximo passo, você pode criar novos scripts de teste para código Python que não sejam do models.py e do views.py.

      Em seguida, temos alguns artigos que podem ser úteis ao desenvolver e testar sites com o Django:

      Você também pode verificar nossa página de tópicos relacionados ao Django para obter mais tutoriais e projetos.



      Source link

      Como adicionar o Sidekiq e o Redis a um aplicativo Ruby on Rails


      Introdução

      Ao desenvolver um aplicativo Ruby on Rails, você pode se deparar com tarefas de aplicativos que devem ser executadas de maneira assíncrona. O processamento de dados, envio de e-mails em lote, ou a interação com APIs externas são todos exemplos de trabalho que podem ser feitos de maneira assíncrona com o background jobs. O uso de jobs em segundo plano pode melhorar o desempenho de seu aplicativo, descarregando tarefas potencialmente demoradas em uma fila de processamento em segundo plano, liberando o ciclo de solicitação/resposta original.

      O Sidekiq é uma das frameworks mais amplamente utilizadas em jobs de segundo plano que você pode implementar em um aplicativo Rails. Ele é apoiado pelo Redis, um armazenamento de valores-chave dentro da memória conhecido pela sua flexibilidade e desempenho. O Sidekiq utiliza o Redis como um armazenamento de gerenciamento de tarefas para processar milhares de tarefas por segundo.

      Neste tutorial, você adicionará o Redis e o Sidekiq a um aplicativo existente do Rails. Você criará um conjunto de classes e métodos de trabalho do Sidekiq para lidar com:

      • Um upload em lote de informações de tubarões ameaçados de extinção para o banco de dados do aplicativo de um arquivo CSV no repositório de projeto.
      • A remoção desses dados.

      Quando terminar, terá um aplicativo de demonstração que utilizará trabalhadores e trabalhos para processar tarefas de maneira assíncrona. Esta será uma boa base para que você adicione trabalhadores e trabalhos ao seu próprio aplicativo, usando este tutorial como um ponto de partida.

      Pré-requisitos

      Para seguir este tutorial, você vai precisar do seguinte:

      Passo 1 — Clonando o projeto e instalando dependências

      Nosso primeiro passo será clonar o repositório de rails-bootstrap da conta do GitHub da Comunidade da DigitalOcean. Esse repositório inclui o código da configuração descrita em Como adicionar o Bootstrap em um aplicativo Ruby on Rails, que explica como adicionar o Bootstrap a um projeto Rails 5 existente.

      Clone o repositório em um diretório chamado rails-sidekiq:

      • git clone https://github.com/do-community/rails-bootstrap.git rails-sidekiq

      Navegue até o diretório rails-sidekiq:

      Para trabalhar com o código, primeiro será necessário instalar as dependências do projeto, que estão listadas em seu Gemfile. Você também precisará adicionar o sidekiq gem ao projeto para trabalhar com o Sidekiq e o Redis.

      Abra o Gemfile do projeto para editá-lo usando o nano ou seu editor favorito:

      Adicione a gem em qualquer lugar das dependências principais do projeto (acima das dependências de desenvolvimento):

      ~/rails-sidekiq/Gemfile

      . . .
      # Reduces boot times through caching; required in config/boot.rb
      gem 'bootsnap', '>= 1.1.0', require: false
      gem 'sidekiq', '~>6.0.0'
      
      group :development, :test do
      . . .
      

      Salve e feche o arquivo quando terminar de adicionar o gem.

      Use o seguinte comando para instalar os gems:

      Você verá na saída que o redis gem também está instalado como um requisito para o sidekiq.

      Em seguida, você instalará suas dependências do Yarn. Como esse projeto Rails 5 foi modificado para atender ativos com o webpack, as dependências de JavaScript dele são gerenciadas agora pelo Yarn. Isso significa que é necessário instalar e verificar as dependências listadas no arquivo do projeto package.json.

      Execute o yarn install para instalar essas dependências:

      Em seguida, execute seu banco de dados de migrações:

      Assim que suas migrações terminarem, teste o aplicativo para garantir que ele esteja funcionando como esperado. Caso esteja trabalhando localmente, inicie seu servidor no contexto do seu pacote local com o seguinte comando:

      Caso esteja trabalhando em um servidor de desenvolvimento, inicie o aplicativo com:

      • bundle exec rails s --binding=your_server_ip

      Navegue até o localhost:3000 ou http://your_server_ip:3000. Você verá a seguinte página inicial:

      Página inicial do aplicativo

      Para criar um novo tubarão, clique no botão Get Shark Info, que levará você até a rota sharks/index:

      Rota do Índice de Tubarões

      Para verificar se o aplicativo está funcionando, podemos adicionar algumas informações de demonstração a ele. Clique em New Shark. Será solicitado que coloque um nome de usuário (sammy) e senha (shark), graças às configurações de autenticação do projeto.

      Na página New Shark, digite “Great White” no campo Name e “Scary” no campo Facts.

      Criar Tubarão

      Clique no botão Create Shark para criar o tubarão. Assim que ver que seu tubarão foi criado, encerre o servidor com CTRL+C.

      Você instalou as dependências necessárias para seu projeto e testou sua funcionalidade. Em seguida, você pode fazer algumas alterações no aplicativo Rails para trabalhar com seus recursos de tubarões ameaçados de extinção.

      Passo 2 — Gerando um controlador para recursos de tubarões ameaçados de extinção

      Para trabalhar com nossos recursos de tubarões ameaçados de extinção, adicionaremos um novo modelo ao aplicativo e um controlador que controlará como as informações sobre tubarões ameaçados de extinção serão apresentadas aos usuários. Nosso objetivo final é tornar possível que os usuários enviem um lote grande de informações sobre tubarões ameaçados de extinção sem bloquear a funcionalidade geral do nosso aplicativo e excluírem essas informações quando não precisarem mais delas.

      Primeiro, vamos criar um modelo Endangered para nossos tubarões ameaçados de extinção. Vamos incluir um campo string em nossa tabela de banco de dados para o nome do tubarão e outro campo string para as categorias da União Internacional para a Conservação da Natureza (IUCN), que determina o grau em que cada tubarão está em risco.

      Por fim, nossa estrutura de modelo corresponderá às colunas do arquivo CSV que usaremos para criar nosso upload do lote. Este arquivo está localizado no diretório db e você pode verificar seu conteúdo com o seguinte comando:

      O arquivo contém uma lista de 73 tubarões ameaçados de extinção e seus status de IUCN – vu para vulneráveis, en para ameaçados de extinção e cr para criticamente ameaçados de extinção.

      Nosso modelo Endangered se correlacionará com esses dados, permitindo-nos criar novas instâncias de Endangered a partir deste arquivo CSV. Crie o modelo com o seguinte comando:

      • rails generate model Endangered name:string iucn:string

      Em seguida, gere um controlador Endangered com uma ação index:

      • rails generate controller endangered index

      Isso nos dará um ponto de partida para desenvolver a funcionalidade do nosso aplicativo, embora também seja necessário adicionar métodos personalizados ao arquivo do controlador que o Rails gerou para nós.

      Abra aquele arquivo agora:

      • nano app/controllers/endangered_controller.rb

      O Rails nos forneceu um rascunho que podemos começar a preencher.

      Primeiro, vamos precisar determinar quais rotas precisamos trabalhar com nossos dados. Graças ao comando generate controller, temos um método index para começar. Isso se correlacionará a uma visualização do index, onde apresentaremos usuários com a opção de fazer o upload de tubarões ameaçados de extinção.

      No entanto, também queremos lidar com casos onde os usuários podem já ter feito upload dos tubarões; eles não precisarão de uma opção de upload neste caso. De algum modo precisaremos avaliar quantas instâncias da classe Endangered já existem, uma vez que mais de uma indica que o upload do lote já ocorreu.

      Vamos começar criando um método private set_endangered que capturará cada instância de nossa classe Endangered a partir do banco de dados. Adicione o código a seguir ao arquivo:

      ~/rails-sidekiq/app/controllers/endangered_controller.rb

      class EndangeredController < ApplicationController
        before_action :set_endangered, only: [:index, :data]
      
        def index
        end
      
        private
      
          def set_endangered
            @endangered = Endangered.all
          end
      
      end
      

      Note que o filtro before_action garantirá que o valor @endangered seja definido apenas para as rotas index e data, que serão as rotas onde lidaremos com os dados dos tubarões ameaçados de extinção.

      Em seguida, adicione o seguinte código ao método index para determinar a rota correta para usuários visitando esta parte do aplicativo:

      ~/rails-sidekiq/app/controllers/endangered_controller.rb

      class EndangeredController < ApplicationController
        before_action :set_endangered, only: [:index, :data]
      
        def index          
          if @endangered.length > 0
            redirect_to endangered_data_path
          else
            render 'index'
          end
        end
      . . .
      

      Caso não exista nenhuma instância de nossa classe Endangered, redirecionaremos os usuários para a rota data, onde podem visualizar informações sobre os tubarões que eles criaram. Caso contrário, eles visualizarão o index.

      Em seguida, abaixo do método index, adicione um método data, que se correlacionará a uma visualização do método data:

      ~/rails-sidekiq/app/controllers/endangered_controller.rb

      . . .
        def index          
          if @endangered.length > 0
            redirect_to endangered_data_path
          else
            render 'index'
          end
        end
      
        def data
        end
      . . .
      

      Em seguida, adicionaremos um método para lidar com o upload de dados propriamente dito. Vamos chamar este método de upload e chamaremos uma classe trabalhadora e um método Sidekiq para realizar o upload de dados do arquivo CSV. Criaremos a definição para essa classe trabalhadora, AddEndangeredWorker, no próximo passo.

      Por enquanto, adicione o seguinte código ao arquivo para fazer o trabalhador do Sidekiq realizar o upload:

      ~/rails-sidekiq/app/controllers/endangered_controller.rb

      . . .
        def data
        end
      
        def upload
          csv_file = File.join Rails.root, 'db', 'sharks.csv'   
          AddEndangeredWorker.perform_async(csv_file)
          redirect_to endangered_data_path, notice: 'Endangered sharks have been uploaded!'
        end
      . . .
      

      Ao chamar o método perform_async da classe AddEndangeredWorker usando o arquivo CSV como um argumento, este código garante que os dados do tubarão e o trabalho de upload sejam passados para o Redis. Os trabalhadores do Sidekiq que vamos configurar monitoram a fila de trabalho e reagirão quando novos trabalhos surgirem.

      Após chamar o perform_async, nosso método de upload redireciona para o caminho data, onde os usuários poderão ver os tubarões carregados.

      Em seguida, adicionaremos um método destroy para destruir os dados. Adicione o seguinte código abaixo do método do upload:

      ~/rails-sidekiq/app/controllers/endangered_controller.rb

      . . .
        def upload
          csv_file = File.join Rails.root, 'db', 'sharks.csv'   
          AddEndangeredWorker.perform_async(csv_file)
          redirect_to endangered_data_path, notice: 'Endangered sharks have been uploaded!'
        end
      
        def destroy
          RemoveEndangeredWorker.perform_async
          redirect_to root_path
        end
      . . .
      

      Da mesma forma que nosso método de upload, nosso método destroy inclui uma chamada do perform_async de uma classe RemoveEndangeredWorker — o outro trabalhador Sidekiq que vamos criar. Após chamar este método, ele redireciona os usuários para o caminho do aplicativo raiz.

      O arquivo final se parecerá com este:

      ~/rails-sidekiq/app/controllers/endangered_controller.rb

      class EndangeredController < ApplicationController
        before_action :set_endangered, only: [:index, :data]
      
        def index          
          if @endangered.length > 0
            redirect_to endangered_data_path
          else
            render 'index'
          end
        end
      
        def data
        end
      
        def upload
          csv_file = File.join Rails.root, 'db', 'sharks.csv'   
          AddEndangeredWorker.perform_async(csv_file)
          redirect_to endangered_data_path, notice: 'Endangered sharks have been uploaded!'
        end
      
        def destroy
          RemoveEndangeredWorker.perform_async
          redirect_to root_path
        end
      
        private
      
          def set_endangered
            @endangered = Endangered.all
          end
      
      end
      

      Salve e feche o arquivo quando você terminar a edição.

      Como passo final na consolidação das rotas do nosso aplicativo, vamos modificar o código em config/routes.rb, o arquivo onde ficam nossas declarações de rota.

      Abra aquele arquivo agora:

      O arquivo se parece com esse:

      ~/rails-sidekiq/config/routes.rb

      Rails.application.routes.draw do
        get 'endangered/index'
        get 'home/index'
        resources :sharks do
                resources :posts
        end
        root 'home#index'
        # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
      end
      

      Vamos precisar atualizar o arquivo para incluir as rotas que definimos em nosso controlador: data, upload e destroy. Nossa rota de data corresponderá a uma solicitação GET para recuperar os dados do tubarão, enquanto nossas rotas de upload e destroy mapearão as solicitações POST, que farão o upload e a destruição desses dados.

      Adicione o código a seguir ao arquivo para definir essas rotas:

      ~/rails-sidekiq/config/routes.rb

      Rails.application.routes.draw do
        get 'endangered/index'
        get 'endangered/data', to: 'endangered#data'
        post 'endangered/upload', to: 'endangered#upload'
        post 'endangered/destroy', to: 'endangered#destroy'
        get 'home/index'
        resources :sharks do
                resources :posts
        end
        root 'home#index'
        # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
      end
      

      Salve e feche o arquivo quando você terminar a edição.

      Com seu modelo e controlador Endangered em funcionamento, continue para definir suas classes de trabalhadores do Sidekiq.

      Passo 3 — Definindo os trabalhadores do Sidekiq

      Chamamos os métodos do perform_async nos trabalhadores do Sidekiq em nosso controlador, mas ainda precisamos criar os trabalhadores em si.

      Primeiro, crie um diretório workers para os trabalhadores:

      Abra um arquivo para o trabalhador AddEndangeredWorker:

      • nano app/workers/add_endangered_worker.rb

      Neste arquivo, adicionaremos códigos que nos permitirá trabalhar com os dados em nosso arquivo CSV. Primeiro, adicione códigos ao arquivo que criarão a classe, inclua a biblioteca Ruby CSV e certifique-se de que essa classe funcione como um trabalhador Sidekiq:

      ~/rails-sidekiq/app/workers/add_endangered_worker.rb

      class AddEndangeredWorker
        require 'csv'
        include Sidekiq::Worker
        sidekiq_options retry: false
      
      end
      

      Também incluiremos a opção retry: false para garantir que o Sidekiq não tente fazer o upload novamente em caso de falha.

      Em seguida, adicione o código para a função perform:

      ~/rails-sidekiq/app/workers/add_endangered_worker.rb

      class AddEndangeredWorker
        require 'csv'
        include Sidekiq::Worker
        sidekiq_options retry: false
      
        def perform(csv_file)
          CSV.foreach(csv_file, headers: true) do |shark|
          Endangered.create(name: shark[0], iucn: shark[1])
        end
       end
      
      end
      

      O método perform recebe argumentos do método perform_async definido no controlador, por este motivo, é importante que os valores do argumento estejam alinhados. Aqui, passamos a csv_file, a variável que definimos no controlador, e usamos o método foreach da biblioteca CSV para ler os valores no arquivo. Definir headers: true para este loop garante que a primeira linha do arquivo seja tratada como uma linha de cabeçalhos.

      Então, o bloco lê os valores do arquivo nas colunas que definimos para nosso modelo Endangered: name e iucn. Executar este loop criará instâncias Endangered para cada uma das entradas em nosso arquivo CSV.

      Assim que terminar a edição, salve e feche o arquivo.

      Em seguida, criaremos um trabalhador para lidar com a exclusão desses dados. Abra um arquivo para a classe RemoveEndangeredWorker:

      • nano app/workers/remove_endangered_worker.rb

      Adicione o código a seguir para definir a classe, e para garantir que ela utilize a biblioteca e as funções CSV como um trabalhador Sidekiq:

      ~/rails-sidekiq/app/workers/remove_endangered_worker.rb

      class RemoveEndangeredWorker
        include Sidekiq::Worker
        sidekiq_options retry: false
      
      end
      

      Em seguida, adicione um método perform para lidar com a destruição dos dados dos tubarões ameaçados de extinção:

      ~/rails-sidekiq/app/workers/remove_endangered_worker.rb

      class RemoveEndangeredWorker
        include Sidekiq::Worker
        sidekiq_options retry: false
      
        def perform
          Endangered.destroy_all
        end
      
      end
      

      O método perform chama a função destroy_all na classe Endangered, que removerá todas as instâncias da classe a partir do banco de dados.

      Salve e feche o arquivo quando você terminar a edição.

      Com seus trabalhadores em funcionamento, continue para a criação de um layout para suas visualizações de endangered e a criação de modelos para a visualização de seus index e data, de modo que os usuários possam fazer upload e visualizar tubarões ameaçados de extinção.

      Passo 4 — Adicionando layouts e modelos de visualização

      Para que os usuários aproveitem suas informações de tubarões ameaçados de extinção, precisaremos abordar duas coisas: o layout para as visualizações definidas em nosso controlador endangered e os modelos de visualização para as visualizações de index e de data.

      Atualmente, nosso aplicativo utiliza um layout em todo o aplicativo, localizado em app/views/layouts/application.html.erb, uma navegação parcial e um layout para visualizações de sharks. O layout do aplicativo verifica se há um bloco de conteúdo que nos permita carregar diferentes layouts com base em qual parte do aplicativo nosso usuário se encontra: para a home index, os usuários verão um layout, e para quaisquer visualizações relacionadas a tubarões individuais, eles verão outro layout.

      Podemos reaproveitar o layout sharks para nossas visualizações endangered, uma vez que este formato também funcionará para a apresentação de dados de tubarões em massa.

      Copie o arquivo de layout de sharks para criar um layout de endangered:

      • cp app/views/layouts/sharks.html.erb app/views/layouts/endangered.html.erb

      Em seguida, vamos trabalhar na criação dos modelos de visualização para nossas visualizações de index e de data.

      Abra o modelo index primeiro:

      • nano app/views/endangered/index.html.erb

      Exclua o código boilerplate e adicione o código a seguir, o qual dará informações gerais aos usuários sobre as categorias ameaçados de extinção e os apresentará com a opção de fazer o upload das informações sobre eles:

      ~/rails-sidekiq/app/views/endangered/index.html.erb

      <p id="notice"><%= notice %></p>
      
      <h1>Endangered Sharks</h1>
      
      <p>International Union for Conservation of Nature (ICUN) statuses: <b>vu:</b> Vulnerable, <b>en:</b> Endangered, <b>cr:</b> Critically Endangered </p>
      
      <br>
      
        <%= form_tag endangered_upload_path do %>
        <%= submit_tag "Import Endangered Sharks" %>
        <% end %>
      
        <br>
      
      <%= link_to 'New Shark', new_shark_path, :class => "btn btn-primary btn-sm" %> <%= link_to 'Home', home_index_path, :class => "btn btn-primary btn-sm" %>
      

      Uma form_tag torna o upload de dados possível, apontando uma ação posterior para a endangered_upload_path — a rota que definimos para nossos uploads. Um botão de enviar, criado com o submit_tag, solicita que os usuários façam o "Import Endangered Sharks​".

      Além deste código, incluímos algumas informações gerais sobre os códigos ICUN, de modo que os usuários possam interpretar os dados que eles verão.

      Salve e feche o arquivo quando você terminar a edição.

      Em seguida, abra um arquivo para a visualização de data:

      • nano app/views/endangered/data.html.erb

      Adicione o código a seguir, que adicionará uma tabela com os dados de tubarões ameaçados de extinção:

      ~/rails-sidekiq/app/views/endangered/data.html.erb

      <p id="notice"><%= notice %></p>
      
      <h1>Endangered Sharks</h1>
      
      <p>International Union for Conservation of Nature (ICUN) statuses: <b>vu:</b> Vulnerable, <b>en:</b> Endangered, <b>cr:</b> Critically Endangered </p>
      
      <div class="table-responsive">
      <table class="table table-striped table-dark">
        <thead>
          <tr>
            <th>Name</th>
            <th>IUCN Status</th>
            <th colspan="3"></th>
          </tr>
        </thead>
      
        <tbody>
          <% @endangered.each do |shark| %>
            <tr>
              <td><%= shark.name %></td>
              <td><%= shark.iucn %></td>
            </tr>
          <% end %>
        </tbody>
      </table>
      </div>
      
      <br>
      
        <%= form_tag endangered_destroy_path do %>
        <%= submit_tag "Delete Endangered Sharks" %>
        <% end %>
      
        <br>
      
      <%= link_to 'New Shark', new_shark_path, :class => "btn btn-primary btn-sm" %> <%= link_to 'Home', home_index_path, :class => "btn btn-primary btn-sm" %>
      

      Esse código inclui os códigos de status da ICUN novamente e uma tabela de Inicialização para os dados produzidos. Ao fazer loop através de nossa variável @endangered, produziremos o nome e o status de ICUN de cada tubarão para a tabela.

      Abaixo da tabela, temos outro conjunto de form_tags e de submit_tags que foram enviados para o caminho destroy, oferecendo aos usuários a opção "Delete Endangered Sharks".

      Salve e feche o arquivo quando você terminar a edição.

      A última modificação que vamos fazer às visualizações será feita na visualização de index associada ao nosso controlador home. Você deve se lembrar de que essa visualização está definida como a raiz do aplicativo em config/routes.rb.

      Abra este arquivo para edição:

      • nano app/views/home/index.html.erb

      Encontre a coluna na linha que afirma que Sharks are ancient​​​:

      ~/rails-sidekiq/app/views/home/index.html.erb

      . . .
              <div class="col-lg-6">
                  <h3>Sharks are ancient</h3>
                  <p>There is evidence to suggest that sharks lived up to 400 million years ago.
                  </p>
              </div>
          </div>
      </div>
      

      Adicione o código a seguir ao arquivo:

      ~/rails-sidekiq/app/views/home/index.html.erb

      . . .
              <div class="col-lg-6">
                  <h3>Sharks are ancient and SOME are in danger</h3>
                  <p>There is evidence to suggest that sharks lived up to 400 million years ago. Without our help, some could disappear soon.</p>
                  <p><%= button_to 'Which Sharks Are in Danger?', endangered_index_path, :method => :get,  :class => "btn btn-primary btn-sm"%>
                  </p>
              </div>
          </div>
      </div>
      

      Incluímos uma chamada de ação para os usuários aprenderem mais sobre os tubarões ameaçados de extinção, primeiramente compartilhando uma mensagem importante e, em seguida, adicionando um auxiliar button_to que envia uma solicitação GET para nossa rota de endangered index, dando acesso a essa parte do aplicativo. A partir daí, eles poderão fazer o upload e visualizar informações sobre tubarões ameaçados de extinção.

      Salve e feche o arquivo quando você terminar a edição.

      Com seu código funcionando, você está pronto para inicializar o aplicativo e fazer o upload de alguns tubarões!

      Passo 5 — Inicializando o Sidekiq e testando o aplicativo

      Antes de inicializar o aplicativo, precisaremos executar as migrações em nosso banco de dados e iniciar o Sidekiq para habilitar nossos trabalhadores. O Redis já deve estar em execução no servidor, mas podemos verificar isso para termos certeza. Com tudo isso funcionando, estaremos prontos para testar o aplicativo.

      Primeiro, verifique se o Redis está funcionando:

      Deverá ver um resultado como o seguinte:

      Output

      ● redis-server.service - Advanced key-value store Loaded: loaded (/lib/systemd/system/redis-server.service; enabled; vendor preset: enabled) Active: active (running) since Tue 2019-11-12 20:37:13 UTC; 1 weeks 0 days ago

      Em seguida, execute seu banco de dados de migrações:

      Agora, você pode iniciar o Sidekiq no contexto do seu pacote atual do projeto, usando o comando bundle exec sidekiq​​​:

      Você verá um resultado como este, indicando que o Sidekiq está pronto para processar trabalhos:

      Output

      m, `$b .ss, $$: .,d$ `$$P,d$P' .,md$P"' ,$$$$$b/md$$$P^' .d$$$$$$/$$$P' $$^' `"/$$$' ____ _ _ _ _ $: ,$$: / ___|(_) __| | ___| | _(_) __ _ `b :$$ ___ | |/ _` |/ _ |/ / |/ _` | $$: ___) | | (_| | __/ <| | (_| | $$ |____/|_|__,_|___|_|__|__, | .d$$ |_| 2019-11-19T21:43:00.540Z pid=17621 tid=gpiqiesdl INFO: Running in ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux] 2019-11-19T21:43:00.540Z pid=17621 tid=gpiqiesdl INFO: See LICENSE and the LGPL-3.0 for licensing details. 2019-11-19T21:43:00.540Z pid=17621 tid=gpiqiesdl INFO: Upgrade to Sidekiq Pro for more features and support: http://sidekiq.org 2019-11-19T21:43:00.540Z pid=17621 tid=gpiqiesdl INFO: Booting Sidekiq 6.0.3 with redis options {:id=>"Sidekiq-server-PID-17621", :url=>nil} 2019-11-19T21:43:00.543Z pid=17621 tid=gpiqiesdl INFO: Starting processing, hit Ctrl-C to stop

      Abra uma segunda janela de terminal, navegue para o diretório rails-sidekiq e inicialize seu servidor do aplicativo.

      Caso esteja executando o aplicativo localmente, use o seguinte comando:

      Caso esteja trabalhando com um servidor de desenvolvimento, execute o seguinte:

      • bundle exec rails s --binding=your_server_ip

      Navegue para o localhost:3000 ou http://your_server_ip:3000 no navegador. Você verá a seguinte página inicial:

      Página inicial do App Sidekiq

      Clique no botão Which Sharks Are in Danger? [Quais tubarões estão em perigo?] . Como não fez upload de nenhum tubarão ameaçado de extinção, isso levará você até a visualização de endangered index:

      Exibição do índice Endangered [Em perigo]

      Clique em Import Endangered Sharks para importar os tubarões. Você verá uma mensagem de status informando que os tubarões foram importados:

      Iniciar importação

      Você verá também o início da importação. Atualize sua página para ver a tabela inteira:

      Atualizar tabela

      Graças ao Sidekiq, o upload de nosso lote grande de tubarões em perigo foi bem-sucedido, sem bloquear o navegador ou interferir com outras funcionalidades do aplicativo.

      Clique no botão Home, no final da página, para voltar à página principal do aplicativo:

      Página inicial do App Sidekiq

      A partir daqui, clique em Which Sharks Are in Danger? novamente. Isso levará você diretamente para a visualização de data, uma vez que você já fez o upload dos tubarões.

      Para testar a funcionalidade de exclusão, clique no botão Delete Endangered Sharks​​​ abaixo da tabela. Você deve ser redirecionado para a página inicial do aplicativo novamente. Clicando em Which Sharks Are in Danger? uma última vez levará você de volta para a visualização do index, onde terá a opção de fazer o upload dos tubarões novamente:

      Exibição do índice Endangered [Em perigo]

      Seu aplicativo agora está funcionando com os trabalhadores Sidekiq, que estão prontos para processar trabalhos e garantir que os usuários tenham uma boa experiência ao trabalhar com seu aplicativo.

      Conclusão

      Agora, você tem um aplicativo Rails em funcionamento com o Sidekiq habilitado, o que permitirá que você descarregue operações dispendiosas em uma fila de trabalho gerenciada pelo Sidekiq e apoiada pelo Redis. Isso permitirá que você melhore a velocidade e a funcionalidade do seu site à medida que desenvolve.

      Caso queira aprender mais sobre o Sidekiq, os docs são um bom lugar para começar.

      Para aprender mais sobre o Redis, confira nossa biblioteca dos recursos do Redis. Você também pode aprender mais sobre a execução de um cluster gerenciado do Redis na DigitalOcean, conferindo a documentação do produto.



      Source link