Back-End

30 mai, 2016

Biblioteca de migração Clojure SQL

Publicidade

Normalmente é recomendado, se você está desenvolvendo um aplicativo que usa um banco de dados, que você gerencie as alterações no esquema da referida base de dados usando algum tipo de sistema de migração. Felizmente, vários desenvolvedores intrépidos na comunidade Clojure têm intensificado suas próprias soluções para esse problema – e todas acabam sendo muito semelhantes. Continue lendo para ter uma visão geral de suas opções e para descobrir qual é a certa para você.

Afinal, o que é uma biblioteca de migração? Bibliotecas de migração de armazenamento de dados modernas tendem a ter algumas tarefas:

  • Gerenciar uma lista de migrações, cada uma com fases up e down.
  • Manter algum conhecimento do estado atual do banco de dados.
  • Oferecer a capacidade de mudar o estado do banco de dados para frente ou para trás em qualquer migração da cadeia, utilizando as fases up ou down conforme apropriado.

As quatro bibliotecas de migração mais ativas em Clojure são difíceis de distinguir, mas a melhor maneira de fazer isso é examinar quais as diferenças existentes entre elas. Para efeitos de comparação, eu vou ficar apenas com as migrações JDBC. As possibilidades são que, se você usar um armazenamento de dados mais esotérico do que isso, não terá o luxo de escolher. As bibliotecas que veremos são:

(Eu queria ver a Lobos também, mas o projeto parece estar morto). Outra biblioteca com a qual você pode se deparar é a Joplin, que parece estar em boas condições de funcionamento, mas é construída diretamente em cima do Ragtime, e não oferece muita diferenciação para o caso de uso básico, que nós vamos cobrir.

Gerenciando a lista de migrações

Todas essas bibliotecas adotam a mesma estratégia geral: escolha um diretório para colocar as migrações, e crie os arquivos de migração no diretório. Escrever o SQL up e down é deixado para o usuário.

Para Ragtime, o arquivo pode ser um par de arquivos .up.sql e .down.sql (no formato SQL) ou um único arquivo EDN que define as migrações para cima e para baixo no seguinte formato:

{:up   ["CREATE TABLE foo (name VARCHAR(100))"
        "INSERT INTO foo VALUES ('alice'), ('bob')"]
 :down ["DROP TABLE foo"]}

Migratus é semelhante, mas só suporta o esquema de .up.sql/.down.sql.

Drift faz mais ou menos a mesma coisa, exceto que cada migração é um arquivo clojure contendo as funções up e down, que são esperadas para fazer o trabalho de verdade. Isso é útil se você usar uma biblioteca SQL que é capaz de coisas como criar e alterar tabelas, mas pode acabar com você usando strings por meio do core.jdbc, de qualquer maneira.

Arquivos de migração Clj-sql-up são arquivos Clojure que exportam as funções up e down. No entanto, é esperado m vetores de strings SQL puras, como no formato EDN do Ragtime:

(defn up []
  ["CREATE TABLE foo (name VARCHAR(100))"
        "INSERT INTO foo VALUES ('alice'), ('bob')"])

(defn down []
  ["DROP TABLE foo"])

Lembrando o estado da migração atual

Ragtime JDBC cria e utiliza uma tabela ragtime_migrations em seu banco de dados para manter um registro das migrações sendo aplicadas. Da mesma forma com Migratus e Clj-sql-up, usa tabelas chamadas schema_migrations e clj_sql_migrations, respectivamente.

Drift pulou esse problema, em vez de deixar para você persistir o id da migração atual com a configuração que você deu a ele. No entanto, o repositório GitHub inclui instruções para fazer o descrito acima.

Todas essas bibliotecas usarão um timestamp no formato yyyyMMddHHmmss como o identificador de migração padrão, embora o Drift deixe você configurar sua própria função de gerador.

Executando migrações

Na maioria dos projetos, você não vai usar a API do Clojure para executar essas migrações – você provavelmente vai usar o Boot ou o plugin Leiningen para isso. Então, vamos examinar o estado deles.

Ragtime oferece um bom suporte para ambos – uma solução oficial semi-DIY para o Leiningen, e para o Boot, boot-ragtime. Eu usei o último e posso garantir que ele dá conta do trabalho. No entanto, ele não fornece uma maneira fácil de voltar a um estado particular, apenas uma forma de migrar totalmente ou reverter um de cada vez. A versão de Boot também permite listar futuras migrações e gerar arquivos SQL puros.

Migratus tem um plugin Leiningen cheio de recursos com suporte para essas duas funções, bem como a geração de arquivos de migração, e execução de migrações up ou down e para um estado arbitrário, e a redefinição do banco de dados.

Drift tem um plugin Leiningen que simplesmente migra para o número de migração que você passar (como padrão, o último). lein migrate -version 0 desfaz todas as migrações.

Clj-sql-up tem um plugin Leiningen básico que lida com a aplicação, rolando para trás e gerando migrações.

Aqui estão os detalhes dos vários plugins em forma de tabela:

ragtime lein ragtime boot migratus drift clj-sql-up
Aplicar todas as migrações até a atual X X X X X
Reverter para a última migração X X X X
Cria um arquivo de migração puro X X X X
Listar as migrações não aplicadas X
Migrar para a migração arbitrária # X X
Resetar o estado do banco de dados (limpar os dados) X X

Conclusão

Todas essas bibliotecas são boas escolhas. A principal diferença é o formato dos arquivos de migração, então você deve usar a que melhor se adapta às suas necessidades (a menos que seu projeto use boot, então use Ragtime).

***

Adam Bard faz parte do time de colunistas internacionais do iMasters. A tradução do artigo é feita pela redação iMasters, com autorização do autor, e você pode acompanhar o artigo em inglês no link: https://adambard.com/blog/clojure-migration-libraries/