<?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: José Antonio</title>
    <description>The latest articles on DEV Community by José Antonio (@learningenuity).</description>
    <link>https://dev.to/learningenuity</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%2F1127165%2F81200222-0a4a-42fd-89ad-1955a409ea24.jpg</url>
      <title>DEV Community: José Antonio</title>
      <link>https://dev.to/learningenuity</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/learningenuity"/>
    <language>en</language>
    <item>
      <title>04 - Estudo de Microsserviços ingresso.x - O Catálogo</title>
      <dc:creator>José Antonio</dc:creator>
      <pubDate>Sat, 26 Aug 2023 20:47:27 +0000</pubDate>
      <link>https://dev.to/learningenuity/04-estudo-de-microsservicos-ingressosx-microsservico-de-catalogo-17ed</link>
      <guid>https://dev.to/learningenuity/04-estudo-de-microsservicos-ingressosx-microsservico-de-catalogo-17ed</guid>
      <description>&lt;h3&gt;
  
  
  🔓 Esse artigo é o quarto de uma sequência de estudo em andamento.
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/jtonynet/cine-ticket-study-microsservices" rel="noopener noreferrer"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bCohonYm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.shields.io/badge/Reposit%25C3%25B3rio%2520do%2520estudo-github-181717%3Fstyle%3Dfor-the-badge%26logo%3Dgithub%26logoColor%3Dwhite" alt="github" width="279" height="28"&gt;&lt;/a&gt; &lt;a href="https://www.linkedin.com/in/jos%C3%A9-r-99896a39/" rel="noopener noreferrer"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9kqbdgfO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.shields.io/badge/Acesse%2520o%2520meu-linkedin-0A66C2%3Fstyle%3Dfor-the-badge%26logo%3Dlinkedin%26logoColor%3Dwhite" alt="linkedin" width="224" height="28"&gt;&lt;/a&gt; &lt;a href="https://twitter.com/aromademirtilo" rel="noopener noreferrer"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9ylJcV2Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.shields.io/badge/Acesse%2520o%2520meu-twitter-1D9BF0%3Fstyle%3Dfor-the-badge%26logo%3Dtwitter%26logoColor%3Dwhite" alt="twitter" width="217" height="28"&gt;&lt;/a&gt; &lt;a href="https://www.instagram.com/learningenuity/" rel="noopener noreferrer"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hUb8NGUS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.shields.io/badge/Acesse%2520o%2520meu-Instagram-E4405F%3Fstyle%3Dfor-the-badge%26logo%3Dinstagram%26logoColor%3Dwhite" alt="Instagram" width="236" height="28"&gt;&lt;/a&gt; &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vICBHb9p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.shields.io/badge/STATUS-EM_DESENVOLVIMENTO-green%3Fstyle%3Dfor-the-badge" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vICBHb9p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.shields.io/badge/STATUS-EM_DESENVOLVIMENTO-green%3Fstyle%3Dfor-the-badge" alt="Badge Status" width="250" height="28"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Documento&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;Um documento é qualquer registro de informações, independentemente do formato ou suporte utilizado para registrá-las.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Fonte: &lt;a href="https://pt.wikipedia.org/wiki/Padroniza%C3%A7%C3%A3o" rel="noopener noreferrer"&gt;Wikipédia&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;O texto abaixo é referente à branch &lt;a href="https://github.com/jtonynet/cine-ticket-study-microsservices/tree/feature/initial-main-000" rel="noopener noreferrer"&gt;feature/initial-main-000&lt;/a&gt; do repositório de estudo. Ao final do artigo teremos desenvolvido até o ponto da branch &lt;a href="https://github.com/jtonynet/cine-ticket-study-microsservices/tree/feature/catalog-service-001" rel="noopener noreferrer"&gt;feature/catalog-service-001&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  📚 Diagramas, ADRs e Documentação
&lt;/h3&gt;

&lt;p&gt;Um bom inicio para microsserviços é um diagrama simples, um &lt;strong&gt;Diagrama de Fluxo de Processo&lt;/strong&gt;, onde podemos definir as ações e quais entidades do sistema elas afetam.&lt;/p&gt;

&lt;p&gt;Existem inúmeras ferramentas que permitem gerar diagramas, inclusive de maneira colaborativa, &lt;a href="https://miro.com/pt/" rel="noopener noreferrer"&gt;Miro Board&lt;/a&gt;, &lt;a href="https://app.diagrams.net/" rel="noopener noreferrer"&gt;Draw.io&lt;/a&gt; etc... mas a abordagem de arquivos &lt;code&gt;readme.md&lt;/code&gt; ricos (os quais falarei em outro artigo) permite que documentação sobre códigos fique próxima do programador, mesmo existindo  Wikis, GithubPages ou Coda do projeto. O &lt;a href="https://mermaid.js.org" rel="noopener noreferrer"&gt;Mermaid&lt;/a&gt; que gera diagramas a partir de código, posteriormente renderizados direto de arquivos markdown no GitHub, foi a escolha.&lt;/p&gt;

&lt;p&gt;Documentação próxima ao código "induz" (ou deveria "induzir") o desenvolvedor a mantê-la atualizada, isso poderia ser parte da sua &lt;a href="https://k21.global/br/blog/encerramento-do-sprint#:~:text=A%20Defini%C3%A7%C3%A3o%20de%20Pronto%20%C3%A9,parte%20do%20produto%20em%20desenvolvimento." rel="noopener noreferrer"&gt;Definição de Pronto&lt;/a&gt; pois: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Documentação é um dos principios de disponibilidade." - &lt;a href="https://en.wikipedia.org/wiki/Susan_Fowler" rel="noopener noreferrer"&gt;Susan Fowler&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--f2L8tHkC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://media3.giphy.com/media/l0IylOPCNkiqOgMyA/giphy.gif%3Fcid%3D6c09b952f2txpzao6sq8inl8o4kc3gljp9t15oe3o7zr578p%26ep%3Dv1_gifs_search%26rid%3Dgiphy.gif%26ct%3Dg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--f2L8tHkC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://media3.giphy.com/media/l0IylOPCNkiqOgMyA/giphy.gif%3Fcid%3D6c09b952f2txpzao6sq8inl8o4kc3gljp9t15oe3o7zr578p%26ep%3Dv1_gifs_search%26rid%3Dgiphy.gif%26ct%3Dg" width="480" height="304"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O problema da "sala de cinema" já é "velho conhecido" para aqueles que estudaram &lt;a href="https://www.amazon.com.br/UML-2-Uma-Abordagem-Pr%C3%A1tica/dp/8575226460" rel="noopener noreferrer"&gt;UML&lt;/a&gt;, mesmo que esse não seja seu caso, é simples compreender como as coisas se relacionam. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Nada é mais didático do que desenhar para comunicar." - &lt;a href="https://brunonardini.com.br/" rel="noopener noreferrer"&gt;Bruno Nardini&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&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%2Fshb7xmhiq9cnt0vulve8.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%2Fshb7xmhiq9cnt0vulve8.png" alt="Image description" width="800" height="340"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A partir da iteração desse fluxo, similar ao caso de uso, fica fácil entender que um &lt;code&gt;Employee User&lt;/code&gt; tem as responsabilidades de manutenção de nosso catálogo de &lt;code&gt;filmes&lt;/code&gt;, &lt;code&gt;salas de cinema&lt;/code&gt;, &lt;code&gt;Endereços&lt;/code&gt;, &lt;code&gt;sessões&lt;/code&gt;, &lt;code&gt;assentos&lt;/code&gt; e nosso produto de fato, o &lt;code&gt;ticket&lt;/code&gt;. Nada mais do que um assento de uma sala de cinema que está reservado para o horário &lt;code&gt;x&lt;/code&gt; de uma sessão.&lt;/p&gt;

&lt;p&gt;A partir da dinâmica representada pelo diagrama anterior e com algum conhecimento de base de dados relacionais avancei em  direção ao  &lt;strong&gt;Diagrama de Entidade-Relacionamento (ER)&lt;/strong&gt; abaixo:&lt;/p&gt;

&lt;p&gt;&lt;a id="diagrama_er"&gt;&lt;/a&gt;&lt;br&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%2F5qp2yd8jr68oyomdv2en.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%2F5qp2yd8jr68oyomdv2en.png" alt="Image description" width="800" height="2318"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Isso nos dá sólidas garantias de que todos os envolvidos compreendam o que será feito. Mas e quanto a como será feito? Quais as &lt;strong&gt;decisões&lt;/strong&gt; de arquitetura serão tomadas para que o projeto de prosseguimento? Para isso uma boa prática e definirmos essas decisões de arquitetura em outro documento e não em nosso readme rico. Vamos definir uma &lt;a href="https://adr.github.io/" rel="noopener noreferrer"&gt;ADR - Architectural Decision Records&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Deixo aqui o contexto com as principais decisões do documento, mas sugiro a você dar uma olhada no &lt;a href="https://github.com/jtonynet/cine-ticket-study-microsservices/blob/feature/catalog-service-001/packages/catalog-service/ADR.md" rel="noopener noreferrer"&gt;ADR completo no repositório.&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"&lt;em&gt;Estamos projetando um Microsserviço de Catálogo de ingressos de cinema. &lt;strong&gt;Decidimos&lt;/strong&gt; usar o framework &lt;a href="https://expressjs.com/" rel="noopener noreferrer"&gt;Express&lt;/a&gt; com &lt;a href="https://www.typescriptlang.org/" rel="noopener noreferrer"&gt;TypeScript&lt;/a&gt; para criar a API em arquitetura &lt;a href="https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller" rel="noopener noreferrer"&gt;MVC&lt;/a&gt;. Faremos testes de unidade e integração com &lt;a href="https://jestjs.io/pt-BR/" rel="noopener noreferrer"&gt;Jest&lt;/a&gt; e usaremos &lt;a href="https://eslint.org/" rel="noopener noreferrer"&gt;Eslint&lt;/a&gt; para linting. Adotaremos principios &lt;a href="https://en.wikipedia.org/wiki/SOLID" rel="noopener noreferrer"&gt;SOLID&lt;/a&gt; onde se aplicar. O ORM &lt;a href="https://sequelize.org/" rel="noopener noreferrer"&gt;Sequelize&lt;/a&gt; será usado para acessar o banco de dados &lt;a href="https://www.postgresql.org/" rel="noopener noreferrer"&gt;PostgreSQL&lt;/a&gt;. Utilizaremos &lt;a href="https://swagger.io/" rel="noopener noreferrer"&gt;Swagger&lt;/a&gt; para documentação da API. O desenvolvimento acontecerá em um &lt;a href="https://nx.dev/" rel="noopener noreferrer"&gt;Monorepo NX&lt;/a&gt;, permitindo a organização de múltiplos projetos em um único repositório. &lt;a href="https://docs.ceph.com/en/latest/radosgw/s3/" rel="noopener noreferrer"&gt;Ceph&lt;/a&gt; será usado  usado como storage local para os posters, simulando um Amazon S3. Não integraremos autenticação agora, mas consideramos &lt;a href="https://www.keycloak.org/" rel="noopener noreferrer"&gt;Keycloak&lt;/a&gt; no futuro. Cache &lt;a href="https://redis.io/" rel="noopener noreferrer"&gt;Redis&lt;/a&gt; está sendo considerado para o futuro&lt;/em&gt;"&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h3&gt;
  
  
  👷 Mãos à Obra ou Show-me the code
&lt;/h3&gt;

&lt;p&gt;Agora as coisas vão ficar um pouco mais sérias. Estou partindo do pressuposto de que o leitor possui alguma familiaridade com o &lt;code&gt;VSCode&lt;/code&gt; e o &lt;code&gt;terminal&lt;/code&gt;. Nosso ambiente é padronizado e o gerenciador de monorepos &lt;a href="https://nx.dev/" rel="noopener noreferrer"&gt;NX&lt;/a&gt; nos permite um conjunto de facilidades para criar e manter nossos &lt;code&gt;microsserviços&lt;/code&gt;, pacotes dentro de do seu diretorio &lt;code&gt;packages&lt;/code&gt;. Para utilizar esse poder, temos que possuir a última versão estável do &lt;a href="https://nodejs.org/en" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt; instalada e do gerenciador de Monorepos &lt;code&gt;NX&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://nodejs.org/pt-br/download/package-manager" rel="noopener noreferrer"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Q5U-T1Fn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.shields.io/badge/Instale%2520o%2520-Nodejs-339933%3Fstyle%3Dfor-the-badge%26logo%3Dnode.js%26logoColor%3Dwhite" alt="Node.js" width="182" height="28"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Logo após, instalar nosso gerenciador de Monorepo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://nx.dev/getting-started/installation#installing-nx-globally" rel="noopener noreferrer"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lLnhnXKZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.shields.io/badge/Instale%2520o%2520-NX-143055%3Fstyle%3Dfor-the-badge%26logo%3Dnx%26logoColor%3Dwhite" alt="NX" width="149" height="28"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pronto, com isso agora podemos finalmente por a "Mão na Massa" e codar algo que seja aderente as nossas guidelines.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XE_Q9ZVF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://media.tenor.com/r6zafkpW15oAAAAC/show-me-what-you-got-rick-and-morty.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XE_Q9ZVF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://media.tenor.com/r6zafkpW15oAAAAC/show-me-what-you-got-rick-and-morty.gif" width="498" height="278"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Navegue Até a raiz do projeto em seu terminal, para instalar suas dependencias. Digite o seguinte comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com isso, teremos as dependências do projeto disponíveis em nosso monorepo NX. Agora, podemos criar nosso primeiro microserviço. Como estamos em um ambiente JavaScript, o próprio gerenciador nos auxiliará nessa tarefa. Basta digitar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;nx generate @nrwl/express:app catalog-service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora sua pasta packages vai se parecer com a estrutura abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  &lt;span class="nv"&gt;$ &lt;/span&gt;tree
  &lt;span class="nb"&gt;.&lt;/span&gt;
  └── packages
  |    ├── catalog-service
  |    ├── catalog-service-e2e
  |    ├── cine-ticket-front-site
  |    └── cine-ticket-nginx
  &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O NX criou dois novos packages: &lt;code&gt;catalog-service&lt;/code&gt; já com um backend mínimo e &lt;code&gt;catalog-service-e2e&lt;/code&gt;, seus respectivos testes e2e. Mas como o projeto esta configurado para  typescript, o arquivo &lt;code&gt;packages/catalog-service/src/main.ts&lt;/code&gt; acusa erro na linha &lt;code&gt;13&lt;/code&gt; por conta das definições do typescript e pela declaração da variável &lt;code&gt;req&lt;/code&gt; que não esta sendo utilizada, basta substituir por &lt;code&gt;_&lt;/code&gt; que o código estará correto.&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%2Fmn1fk2rquyhmuohutu63.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%2Fmn1fk2rquyhmuohutu63.png" alt="Image description" width="650" height="80"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Agora rode o seguinte comando para testar seu "microsserviço mínimo":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;nx serve catalog-service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A saída deve ser similar a:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;chunk &lt;span class="o"&gt;(&lt;/span&gt;runtime: main&lt;span class="o"&gt;)&lt;/span&gt; main.js &lt;span class="o"&gt;(&lt;/span&gt;main&lt;span class="o"&gt;)&lt;/span&gt; 1.87 KiB &lt;span class="o"&gt;[&lt;/span&gt;entry] &lt;span class="o"&gt;[&lt;/span&gt;rendered]
webpack compiled successfully &lt;span class="o"&gt;(&lt;/span&gt;eb148a07024bd3a0&lt;span class="o"&gt;)&lt;/span&gt;
Debugger listening on ws://localhost:9229/75f60138-7e65-4fbb-95b9-23c6553bfdf8
For &lt;span class="nb"&gt;help&lt;/span&gt;, see: https://nodejs.org/en/docs/inspector

Listening at http://localhost:3333/api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Acesando a url que esta sendo servida, &lt;code&gt;Listening&lt;/code&gt;, no comando o seu browser deve ser algo parecido com isso:&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%2Fcqidk9dwhkkpb4eku8cf.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%2Fcqidk9dwhkkpb4eku8cf.png" alt="Image description" width="516" height="249"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Embora pareça estar tudo funcional, percebi que os arquivos transpilados que devem ser distribuídos, os &lt;code&gt;dist&lt;/code&gt;, estavam sendo gerados na raiz do projeto e gostaria que nesse momento eles fossem gerados dentro de seus respectivos &lt;code&gt;pacakges&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A solução foi simples, bastando acessar o arquivo &lt;code&gt;/packages/catalog-service/project.json&lt;/code&gt; e alterar o valor de &lt;code&gt;build.options.outputPath&lt;/code&gt; para &lt;code&gt;packages/catalog-service/dist&lt;/code&gt; e resolvido. Interrompa o processo do &lt;code&gt;catalog-service&lt;/code&gt; digitando &lt;code&gt;ctrl + c&lt;/code&gt; no terminal do seu &lt;code&gt;VSCode&lt;/code&gt;, remova a pasta &lt;code&gt;dist&lt;/code&gt; da raiz e rode o comando &lt;code&gt;$ nx serve catalog-service&lt;/code&gt; novamente. A pasta dist deve ser criada dentro do &lt;code&gt;catalog-service&lt;/code&gt; agora, o comportamento esperado.&lt;/p&gt;



&lt;h4&gt;
  
  
  💱 Trocando WebPack por ESbuild
&lt;/h4&gt;

&lt;p&gt;Por padrão, o NX usa o WebPack para gerar seus builds. No entanto, optei por uma abordagem mais moderna e adotei o &lt;a href="https://esbuild.github.io/" rel="noopener noreferrer"&gt;EsBuild&lt;/a&gt; para essa tarefa. Precisaremos instalar suas dependências e fazer algumas configurações adicionais. Na raiz do projeto, execute o seguinte comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; @nrwl/esbuild
&lt;span class="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; @nx/esbuild
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E então, devemos informar ao NX que o nosso pacote &lt;code&gt;catalog-microsservice&lt;/code&gt; deve agora utilizar as configurações do &lt;code&gt;esbuild&lt;/code&gt;. Você pode fazer isso com o seguinte comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;nx g @nx/esbuild:configuration catalog-service &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--main&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;packages/catalog-service/src/main.ts &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--tsConfig&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;packages/catalog-service/tsconfig.custom.json &lt;span class="nt"&gt;--skipValidation&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mas não é apenas isso; na verdade, serão necessários mais dois ajustes. Para isso, abra o arquivo &lt;code&gt;package.json&lt;/code&gt; que deve ter sido criado na raiz de &lt;code&gt;packages/catalog-microsservice&lt;/code&gt;. Ele deve se parecer com a estrutura vista abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@cine-ticket-microsservices/catalog-service"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0.0.1"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Abaixo do campo &lt;code&gt;"version": "0.0.1",&lt;/code&gt; coloque a seguinte entrada &lt;code&gt;"type": "module"&lt;/code&gt; no documento json informando ao Node.js que os arquivos JavaScript no projeto devem ser tratados como módulos ESM. Isso significa que podemos usar a sintaxe &lt;code&gt;import&lt;/code&gt; e &lt;code&gt;export&lt;/code&gt; para carregar módulos em vez da sintaxe require e module.exports usada em módulos CommonJS.&lt;/p&gt;

&lt;p&gt;Para finalizar, remova os comentários e as linhas desnecessárias do seu arquivo &lt;code&gt;packages/catalog-microsservice/main.ts&lt;/code&gt;. Isso inclui as linhas de &lt;code&gt;1&lt;/code&gt; a &lt;code&gt;5&lt;/code&gt;, o import de &lt;code&gt;path&lt;/code&gt; na linha &lt;code&gt;7&lt;/code&gt; e a linha &lt;code&gt;11&lt;/code&gt;, já que não faremos uso de &lt;code&gt;assets&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;packages&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;catalog&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;microsservice&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;

&lt;span class="mi"&gt;1&lt;/span&gt;    &lt;span class="cm"&gt;/**
2     * This is not a production server yet!
3     * This is only a minimal backend to get started.
4     */&lt;/span&gt;
&lt;span class="mi"&gt;5&lt;/span&gt;    
&lt;span class="mi"&gt;6&lt;/span&gt;    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;7&lt;/span&gt;    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;8&lt;/span&gt;    
&lt;span class="mi"&gt;9&lt;/span&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="mi"&gt;10&lt;/span&gt;   
&lt;span class="mi"&gt;11&lt;/span&gt;    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/assets&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;assets&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
&lt;span class="mi"&gt;12&lt;/span&gt;   
&lt;span class="mi"&gt;13&lt;/span&gt;    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&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;14&lt;/span&gt;      &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Welcome to catalog-microsservice!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="mi"&gt;15&lt;/span&gt;    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="mi"&gt;16&lt;/span&gt;   
&lt;span class="mi"&gt;17&lt;/span&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;3333&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;18&lt;/span&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&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;19&lt;/span&gt;      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Listening at http://localhost:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/api`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="mi"&gt;20&lt;/span&gt;    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="mi"&gt;21&lt;/span&gt;    &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pronto, mudamos nosso builder e tudo deve continuar como era antes.&lt;/p&gt;




&lt;h3&gt;
  
  
  🎲 Banco de Dados, Models e o Serviço a partir dai
&lt;/h3&gt;

&lt;p&gt;Temos um serviço mínimo rodando; é hora de começar a construir funcionalidades reais e robustas. Vamos dar vida às entidades e relações que mapeamos no Diagrama ER a partir do banco de dados. No terminal, na raiz do projeto, saia do prompt do &lt;code&gt;nx serve&lt;/code&gt; digitando &lt;code&gt;ctrl + c&lt;/code&gt; e digite os comandos para criar a pasta onde armazenaremos os dados de volume de nosso banco de dados&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;packages/catalog-service-db
&lt;span class="nb"&gt;mkdir &lt;/span&gt;packages/catalog-service-db/data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adicione as seguintes linhas no seu &lt;code&gt;docker-compose.yml&lt;/code&gt; visando criar o banco de dados Postgres que nosso microsservico Utilizará.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;docker-compose.yml&lt;/span&gt;

  &lt;span class="s"&gt;catalog-service-db&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres:latest&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;catalog-service-db&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;catalog_service_db&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;catalog_service_user&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;catalog_service_password&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5432:5432"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./packages/catalog-service-db/data:/var/lib/postgresql/data&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cine-ticket-network&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rode a partir da raiz um &lt;code&gt;docker compose up --build&lt;/code&gt; para subir e reconstruir as imagens de nossos serviços em conjunto com o Postgres, isso deve demorar um pouco. Note que ainda não configuramos o &lt;code&gt;catalog-service&lt;/code&gt; para subir junto, apenas o seu banco. &lt;/p&gt;

&lt;p&gt;Agora que temos um banco de dados, vamos criar a conexão e os modelos correspondentes aos nossos dados, conforme decidido no ADR. Abra um novo terminal e crie a pasta &lt;code&gt;/packages/catalog-service/src/models&lt;/code&gt; executando o seguinte comando em um novo terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;packages/catalog-service-db/src/models
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sua árvore de diretório deve ficar similar a:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  &lt;span class="nv"&gt;$ &lt;/span&gt;tree
  &lt;span class="nb"&gt;.&lt;/span&gt;
  └── packages
  |    ├── catalog-service
  |        ├── src
  |            ├── assets
  |            ├── models
  &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E então, instalaremos as dependências necessárias para criar nossos modelos. Em uma nova janela do terminal insira os comandos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;sequelize pg pg-hstore
npm &lt;span class="nb"&gt;install&lt;/span&gt; @types/sequelize &lt;span class="nt"&gt;--save-dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;sequelize&lt;/strong&gt;: ORM (Object-Relational Mapping) que você usará para interagir com o banco de dados.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;pg&lt;/strong&gt;: driver do PostgreSQL para o Node.js, permitindo que o Sequelize se conecte ao PostgreSQL.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;pg-hstore&lt;/strong&gt;: pacote que lida com o mapeamento de tipos de dados JSON para o PostgreSQL, usado pelo Sequelize.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;types/sequelize&lt;/strong&gt;: fornece definições de tipos TypeScript para a biblioteca Sequelize&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;✍️ &lt;strong&gt;Nota&lt;/strong&gt;:&lt;br&gt;
Tentei usar o sequelize-cli para automatizar a geração das models, mas ele ainda não oferece suporte ao TypeScript. Portanto, criei as models manualmente. Existe um pacote chamado &lt;a href="https://www.npmjs.com/package/sequelize-typescript" rel="noopener noreferrer"&gt;sequelize-typescript&lt;/a&gt;, mas como seu mantenedor não é a equipe oficial do Sequelize, não o utilizei.&lt;/p&gt;
&lt;/blockquote&gt;



&lt;h4&gt;
  
  
  🔌 Criando a conexao:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;packages/catalog-service/src/models/db.ts
code packages/catalog-service/src/models/db.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esses comandos criam e abrem no seu &lt;code&gt;VsCode&lt;/code&gt; o arquivo &lt;code&gt;packages/catalog-service/models/db.ts&lt;/code&gt; que vai conectar nossa &lt;code&gt;API&lt;/code&gt; ao banco, veja abaixo uma Implantação simples de conexão ao banco que você deve digitar no arquivo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;packages&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;catalog&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;models&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;

&lt;span class="mi"&gt;1&lt;/span&gt;   &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Sequelize&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sequelize&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;  
&lt;span class="mi"&gt;3&lt;/span&gt;   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="mi"&gt;4&lt;/span&gt;     &lt;span class="na"&gt;max&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;5&lt;/span&gt;     &lt;span class="na"&gt;min&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="mi"&gt;6&lt;/span&gt;     &lt;span class="na"&gt;acquire&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;130000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="mi"&gt;7&lt;/span&gt;     &lt;span class="na"&gt;idle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10000&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;9&lt;/span&gt;  
&lt;span class="mi"&gt;10&lt;/span&gt;   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sequelize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Sequelize&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;span class="mi"&gt;11&lt;/span&gt;     &lt;span class="na"&gt;dialect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;postgres&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="mi"&gt;12&lt;/span&gt;     &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;localhost&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="mi"&gt;13&lt;/span&gt;     &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;catalog_service_db&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="mi"&gt;14&lt;/span&gt;     &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;catalog_service_user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="mi"&gt;15&lt;/span&gt;     &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;catalog_service_password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="mi"&gt;16&lt;/span&gt;     &lt;span class="nx"&gt;pool&lt;/span&gt;
&lt;span class="mi"&gt;17&lt;/span&gt;   &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="mi"&gt;18&lt;/span&gt;  
&lt;span class="mi"&gt;19&lt;/span&gt;   &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;sequelize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;✍️ &lt;strong&gt;Nota&lt;/strong&gt;:&lt;br&gt;
Atenção especial entre as linhas &lt;code&gt;3&lt;/code&gt; a &lt;code&gt;8&lt;/code&gt;. Esse é um problema clássico para iniciantes e aborda uma das "Falácias" - a da "Composição" - que afirma: "se um componente individual funciona bem, todos eles funcionarão bem em conjunto". Sua aplicação não escala em conjunto com seu banco; é necessário que tenhamos um pool de conexões que evite gargalos. Já vi isso acontecer em uma aplicação na qual microserviços individuais eram bem otimizados, mas os gargalos frequentemente ocorriam devido a bloqueios no banco de dados central, limitando a escalabilidade horizontal.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Instanciamos com os parâmetros de conexão e exportamos o &lt;code&gt;sequelize&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Com isso efetivamente vinculamos o banco de dados incluído em nosso &lt;code&gt;docker-compose.yml&lt;/code&gt; ao projeto. Como software gerenciador de banco de dados, estou utilizando o DBeaver e sugiro sua instalação.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dbeaver.io/" rel="noopener noreferrer"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--v0ff9LVc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.shields.io/badge/Instale%2520o%2520-DBeaver-143055%3Fstyle%3Dfor-the-badge%26logo%3Ddbeaver%26logoColor%3Dwhite" alt="DBeaver" width="174" height="28"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Com o DBeaver instalado, crie uma nova conexão nele usando os mesmos dados de acesso usados em nosso arquivo &lt;code&gt;db.ts&lt;/code&gt; para verificar o banco, mesmo que não tenhamos as tabelas ainda:&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%2Fc3iad7k027dlz2t505wc.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%2Fc3iad7k027dlz2t505wc.png" alt="Image description" width="560" height="296"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Vamos agora criar nossa primeira entidade "filme", estando na raiz do projeto digite os seguintes comandos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;packages/catalog-service/src/models/film.ts
&lt;span class="nv"&gt;$ &lt;/span&gt;code packages/catalog-service/src/models/film.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Criamos e abrimos no nosso vscode a entidade filme, a qual digitaremos o seguinte código typescript baseado na entidade &lt;code&gt;film&lt;/code&gt; de nosso DER:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;packages&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;catalog&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;models&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;film&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;

&lt;span class="mi"&gt;1&lt;/span&gt;  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;DataTypes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Sequelize&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sequelize&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt; 
&lt;span class="mi"&gt;3&lt;/span&gt;  &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Film&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Model&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="mi"&gt;4&lt;/span&gt;    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;5&lt;/span&gt;    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;uuid&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;6&lt;/span&gt;    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;7&lt;/span&gt;    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;8&lt;/span&gt;    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;age_rating&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;9&lt;/span&gt;    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;subtitled&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;10&lt;/span&gt;   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;poster&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;11&lt;/span&gt; 
&lt;span class="mi"&gt;12&lt;/span&gt;   &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nf"&gt;associate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="mi"&gt;13&lt;/span&gt;   &lt;span class="c1"&gt;//static associate(models: any) {&lt;/span&gt;
&lt;span class="mi"&gt;14&lt;/span&gt;     &lt;span class="c1"&gt;// Define as associações aqui...&lt;/span&gt;
&lt;span class="mi"&gt;15&lt;/span&gt;   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="mi"&gt;16&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="mi"&gt;17&lt;/span&gt;
&lt;span class="mi"&gt;18&lt;/span&gt; &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sequelize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Sequelize&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;19&lt;/span&gt;   &lt;span class="nx"&gt;Film&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;span class="mi"&gt;20&lt;/span&gt;     &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="mi"&gt;21&lt;/span&gt;       &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DataTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;INTEGER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="mi"&gt;22&lt;/span&gt;       &lt;span class="na"&gt;autoIncrement&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="mi"&gt;23&lt;/span&gt;       &lt;span class="na"&gt;primaryKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="mi"&gt;24&lt;/span&gt;     &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="mi"&gt;25&lt;/span&gt;     &lt;span class="na"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="mi"&gt;26&lt;/span&gt;       &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DataTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;UUID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="mi"&gt;27&lt;/span&gt;       &lt;span class="na"&gt;allowNull&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="mi"&gt;28&lt;/span&gt;     &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="mi"&gt;29&lt;/span&gt;     &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="mi"&gt;30&lt;/span&gt;       &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DataTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;STRING&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="mi"&gt;31&lt;/span&gt;       &lt;span class="na"&gt;allowNull&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="mi"&gt;32&lt;/span&gt;     &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="mi"&gt;33&lt;/span&gt;     &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="mi"&gt;34&lt;/span&gt;       &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DataTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="mi"&gt;35&lt;/span&gt;       &lt;span class="na"&gt;allowNull&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="mi"&gt;36&lt;/span&gt;     &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="mi"&gt;37&lt;/span&gt;     &lt;span class="na"&gt;age_rating&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="mi"&gt;38&lt;/span&gt;       &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DataTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;INTEGER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="mi"&gt;39&lt;/span&gt;       &lt;span class="na"&gt;allowNull&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="mi"&gt;40&lt;/span&gt;     &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="mi"&gt;41&lt;/span&gt;     &lt;span class="na"&gt;subtitled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="mi"&gt;42&lt;/span&gt;       &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DataTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BOOLEAN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="mi"&gt;43&lt;/span&gt;       &lt;span class="na"&gt;allowNull&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="mi"&gt;44&lt;/span&gt;     &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="mi"&gt;45&lt;/span&gt;     &lt;span class="na"&gt;poster&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="mi"&gt;46&lt;/span&gt;       &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DataTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;STRING&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="mi"&gt;47&lt;/span&gt;       &lt;span class="na"&gt;allowNull&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="mi"&gt;48&lt;/span&gt;     &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="mi"&gt;49&lt;/span&gt;   &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="mi"&gt;50&lt;/span&gt;     &lt;span class="nx"&gt;sequelize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="mi"&gt;51&lt;/span&gt;     &lt;span class="na"&gt;modelName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Film&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="mi"&gt;52&lt;/span&gt;     &lt;span class="na"&gt;tableName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;film&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="mi"&gt;53&lt;/span&gt;   &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="mi"&gt;54&lt;/span&gt;
&lt;span class="mi"&gt;55&lt;/span&gt;   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Film&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;56&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="mi"&gt;57&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perceba que na linha &lt;code&gt;3&lt;/code&gt;, estendemos a classe &lt;code&gt;Model&lt;/code&gt; do &lt;code&gt;Sequelize&lt;/code&gt; ao definir nossa classe &lt;code&gt;Film&lt;/code&gt;. Estamos &lt;em&gt;"abertos para extensão e fechados para modificação"&lt;/em&gt;. Dentro do código de definição da classe, informamos que nossos atributos são públicos, seguidos pelo nome do atributo e pelo caractere de exclamação &lt;code&gt;!&lt;/code&gt;, indicando que não podem receber valores &lt;code&gt;null&lt;/code&gt; e nem &lt;code&gt;undefined&lt;/code&gt;, e também indica que os valores dos atributos serão definidos após a criação do objeto. Nessa classe, na linha &lt;code&gt;22&lt;/code&gt;, também são definidas as associações que &lt;code&gt;Film&lt;/code&gt; terá com outras entidades. Como ela é única no momento, nenhuma associação foi definida.&lt;/p&gt;

&lt;p&gt;A partir da linha &lt;code&gt;18&lt;/code&gt;, estamos exportando nossa entidade &lt;code&gt;Film&lt;/code&gt; e descrevendo os tipos referentes aos &lt;code&gt;DataTypes&lt;/code&gt; do &lt;code&gt;Sequelize&lt;/code&gt; a quais esses atributos pertencem.&lt;/p&gt;

&lt;p&gt;Retorne ao seu arquivo &lt;code&gt;packages/catalog-service/models/db.ts&lt;/code&gt; e adicione o import da nossa entidade &lt;code&gt;film&lt;/code&gt;. Em seguida, crie uma instância dela, passando o objeto &lt;code&gt;sequelize&lt;/code&gt;, como pode ser visto nas linhas &lt;code&gt;2&lt;/code&gt; e &lt;code&gt;22&lt;/code&gt; abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;packages&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;catalog&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;models&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;

&lt;span class="mi"&gt;1&lt;/span&gt;   &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Sequelize&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sequelize&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;   &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Film&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./film&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt; 
&lt;span class="mi"&gt;4&lt;/span&gt;   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="mi"&gt;5&lt;/span&gt;     &lt;span class="na"&gt;max&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="na"&gt;min&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="mi"&gt;7&lt;/span&gt;     &lt;span class="na"&gt;acquire&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;130000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="mi"&gt;8&lt;/span&gt;     &lt;span class="na"&gt;idle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10000&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;10&lt;/span&gt; 
&lt;span class="mi"&gt;11&lt;/span&gt;  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sequelize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Sequelize&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;span class="mi"&gt;12&lt;/span&gt;    &lt;span class="na"&gt;dialect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;postgres&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="mi"&gt;13&lt;/span&gt;    &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;localhost&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="mi"&gt;14&lt;/span&gt;    &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;catalog_service_db&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="mi"&gt;15&lt;/span&gt;    &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;catalog_service_user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="mi"&gt;16&lt;/span&gt;    &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;catalog_service_password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="mi"&gt;17&lt;/span&gt;    &lt;span class="nx"&gt;pool&lt;/span&gt;
&lt;span class="mi"&gt;18&lt;/span&gt;  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="mi"&gt;19&lt;/span&gt; 
&lt;span class="mi"&gt;20&lt;/span&gt;  &lt;span class="nc"&gt;Film&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sequelize&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="mi"&gt;21&lt;/span&gt; 
&lt;span class="mi"&gt;22&lt;/span&gt;  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;sequelize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;23&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com isso a entidade esta quase pronta para ser espelhada em nosso banco, para tanto um utltimo ajuste em nosso &lt;code&gt;packages\catalog-microsservice\src\main.ts&lt;/code&gt; sera necessario:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;packages&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;catalog&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;microsservice&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;

&lt;span class="mi"&gt;1&lt;/span&gt;   &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;   &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;sequelize&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./models/db&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt; 
&lt;span class="mi"&gt;4&lt;/span&gt;   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="mi"&gt;5&lt;/span&gt; 
&lt;span class="mi"&gt;6&lt;/span&gt;   &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&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;7&lt;/span&gt;     &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Welcome to catalog-microsservice!&lt;/span&gt;&lt;span class="dl"&gt;'&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;9&lt;/span&gt; 
&lt;span class="mi"&gt;10&lt;/span&gt;  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;3333&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;11&lt;/span&gt;  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&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;12&lt;/span&gt;    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Listening at http://localhost:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/api`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="mi"&gt;13&lt;/span&gt;  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="mi"&gt;14&lt;/span&gt;  &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="mi"&gt;15&lt;/span&gt; 
&lt;span class="mi"&gt;16&lt;/span&gt;  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;syncDB&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="mi"&gt;17&lt;/span&gt;    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;sequelize&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="mi"&gt;18&lt;/span&gt;    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Models synchronized with the database&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="mi"&gt;19&lt;/span&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="mi"&gt;20&lt;/span&gt; 
&lt;span class="mi"&gt;21&lt;/span&gt;  &lt;span class="nf"&gt;syncDB&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="mi"&gt;22&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fizemos o &lt;code&gt;import&lt;/code&gt; do &lt;code&gt;sequelize&lt;/code&gt; que acabamos de configurar na linha 2. Entre as linhas &lt;code&gt;16&lt;/code&gt; a &lt;code&gt;21&lt;/code&gt;, criamos uma função assíncrona com a finalidade de criar as tabelas definidas como entidades em nosso &lt;code&gt;packages/catalog-microsservices/src/models&lt;/code&gt;. Atualmente, apenas &lt;code&gt;film&lt;/code&gt; está ali.&lt;/p&gt;

&lt;p&gt;Insira o comando para iniciar nossa &lt;code&gt;API&lt;/code&gt; novamente, utilizando o comando &lt;code&gt;nx serve catalog-service&lt;/code&gt;. Devemos obter um resultado semelhante a este:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;nx serve catalog-service

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; nx run catalog-service:serve:development

&lt;span class="o"&gt;[&lt;/span&gt; watch &lt;span class="o"&gt;]&lt;/span&gt; build succeeded, watching &lt;span class="k"&gt;for &lt;/span&gt;changes...
Debugger listening on ws://localhost:9229/a5fe752f-36bd-469c-9361-24432ba30c1a
For &lt;span class="nb"&gt;help&lt;/span&gt;, see: https://nodejs.org/en/docs/inspector

Listening at http://localhost:3333/api
Executing &lt;span class="o"&gt;(&lt;/span&gt;default&lt;span class="o"&gt;)&lt;/span&gt;: SELECT table_name FROM information_schema.tables WHERE table_schema &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'public'&lt;/span&gt; AND table_name &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'film'&lt;/span&gt;
Executing &lt;span class="o"&gt;(&lt;/span&gt;default&lt;span class="o"&gt;)&lt;/span&gt;: CREATE TABLE IF NOT EXISTS &lt;span class="s2"&gt;"film"&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"id"&lt;/span&gt;  SERIAL , &lt;span class="s2"&gt;"uuid"&lt;/span&gt; UUID NOT NULL, &lt;span class="s2"&gt;"name"&lt;/span&gt; VARCHAR&lt;span class="o"&gt;(&lt;/span&gt;500&lt;span class="o"&gt;)&lt;/span&gt; NOT NULL, &lt;span class="s2"&gt;"description"&lt;/span&gt; TEXT NOT NULL, &lt;span class="s2"&gt;"age_rating"&lt;/span&gt; INTEGER NOT NULL, &lt;span class="s2"&gt;"subtitled"&lt;/span&gt; BOOLEAN NOT NULL, &lt;span class="s2"&gt;"poster"&lt;/span&gt; VARCHAR&lt;span class="o"&gt;(&lt;/span&gt;500&lt;span class="o"&gt;)&lt;/span&gt; NOT NULL, &lt;span class="s2"&gt;"createdAt"&lt;/span&gt; TIMESTAMP WITH TIME ZONE NOT NULL, &lt;span class="s2"&gt;"updatedAt"&lt;/span&gt; TIMESTAMP WITH TIME ZONE NOT NULL, PRIMARY KEY &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"id"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
Executing &lt;span class="o"&gt;(&lt;/span&gt;default&lt;span class="o"&gt;)&lt;/span&gt;: SELECT i.relname AS name, ix.indisprimary AS primary, ix.indisunique AS unique, ix.indkey AS indkey, array_agg&lt;span class="o"&gt;(&lt;/span&gt;a.attnum&lt;span class="o"&gt;)&lt;/span&gt; as column_indexes, array_agg&lt;span class="o"&gt;(&lt;/span&gt;a.attname&lt;span class="o"&gt;)&lt;/span&gt; AS column_names, pg_get_indexdef&lt;span class="o"&gt;(&lt;/span&gt;ix.indexrelid&lt;span class="o"&gt;)&lt;/span&gt; AS definition FROM pg_class t, pg_class i, pg_index ix, pg_attribute a WHERE t.oid &lt;span class="o"&gt;=&lt;/span&gt; ix.indrelid AND i.oid &lt;span class="o"&gt;=&lt;/span&gt; ix.indexrelid AND a.attrelid &lt;span class="o"&gt;=&lt;/span&gt; t.oid AND t.relkind &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'r'&lt;/span&gt; and t.relname &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'film'&lt;/span&gt; GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname&lt;span class="p"&gt;;&lt;/span&gt;
Models synchronized with the database

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso indica que seu modelo/entidade foi sincronizado com o banco que subimos com o &lt;code&gt;docker-compose up --build&lt;/code&gt; que fizemos no inicio do artigo, agora se revisitarmos o &lt;code&gt;DBeaver&lt;/code&gt; e atualizarmos sua visualização clicando &lt;code&gt;F5&lt;/code&gt; com nosso database selecionado, veremos a tabela criada por nosso ultimo comando.&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%2Fw3094l14naizf2kgxiem.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%2Fw3094l14naizf2kgxiem.png" alt="Image description" width="781" height="518"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Não deverá ser um fator complicador criar as outras entidades a partir do que já foi exposto aqui e utilizando o DER como guideline. Sugiro tentar mesmo sem os relacionamentos no momento para praticar e só depois olhar o gabarito em forma de lista abaixo:&lt;/p&gt;



&lt;p&gt;packages/catalog-service/src/models/room.ts&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
// Importe os módulos necessários do Sequelize
import { Model, DataTypes, Sequelize } from 'sequelize';

// Defina a entidade "Room"
class Room extends Model {
  public id!: number;
  public uuid!: string;
  public name!: string;
  public capacity!: number;

  // Defina as associações
  static associate(models: any) {
    // Uma sala pode ter várias sessões
    Room.hasMany(models.Session, { foreignKey: 'room_id' });

    // Uma sala pode ter apenas um endereço
    Room.belongsTo(models.Address, {
      foreignKey: 'address_id',
    });
  }
}

// Exporte a função que define a entidade e suas configurações
export default (sequelize: Sequelize) =&amp;gt; {
  Room.init({
    id: {
      type: DataTypes.INTEGER,
      autoIncrement: true,
      primaryKey: true,
    },
    uuid: {
      type: DataTypes.UUID,
      allowNull: false,
    },
    name: {
      type: DataTypes.STRING,
      allowNull: false,
    },
    capacity: {
      type: DataTypes.INTEGER,
      allowNull: false,
    },
  }, {
    sequelize,
    modelName: 'Room',
    tableName: 'room',
  });

  return Room;
};

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;packages/catalog-service/src/models/session.ts&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
// Importe os módulos necessários do Sequelize
import { Model, DataTypes, Sequelize } from 'sequelize';

// Defina a entidade "session"
class Session extends Model {
  public id!: number;
  public uuid!: string;
  public film_id!: number;
  public room_id!: number;
  public description!: string;
  public date!: Date;
  public start_time!: Date;
  public end_time!: Date;
  public time!: string;

  // Defina as associações
  static associate(models: any) {
    // Uma sessão pertence a um filme
    Session.belongsTo(models.Film, { foreignKey: 'film_id' });
    
    // Uma sessão ocorre em uma sala
    Session.belongsTo(models.Room, { foreignKey: 'room_id' });

    // Uma sessão pode ter vários tickets
    Session.hasMany(models.Ticket, { foreignKey: 'session_id' });
  }
}

// Exporte a função que define a entidade e suas configurações
export default (sequelize: Sequelize) =&amp;gt; {
  Session.init({
    id: {
      type: DataTypes.INTEGER,
      autoIncrement: true,
      primaryKey: true,
    },
    uuid: {
      type: DataTypes.UUID,
      allowNull: false,
    },
    film_id: {
      type: DataTypes.INTEGER,
      allowNull: false,
    },
    room_id: {
      type: DataTypes.INTEGER,
      allowNull: false,
    },
    description: {
      type: DataTypes.STRING,
      allowNull: true,
    },
    date: {
      type: DataTypes.DATEONLY,
      allowNull: false,
    },
    start_time: {
      type: DataTypes.TIME,
      allowNull: false,
    },
    end_time: {
      type: DataTypes.TIME,
      allowNull: false,
    },
    time: {
      type: DataTypes.STRING,
      allowNull: true,
    },
  }, {
    sequelize,
    modelName: 'Session',
    tableName: 'session',
  });

  return Session;
};

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;packages/catalog-service/src/models/seat.ts&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
import { DataTypes, Model, Sequelize } from 'sequelize';

class Seat extends Model {
  public id!: number;
  public uuid!: string;
  public room_id!: number;
  public code!: string;

  static associate(models: any) {
    Seat.belongsTo(models.Room, {
      foreignKey: 'room_id',
      as: 'room',
    });
    Seat.hasMany(models.Ticket, {
      foreignKey: 'seat_id',
      as: 'tickets',
    });
  }
}

export default (sequelize: Sequelize) =&amp;gt; {
  Seat.init(
    {
      id: {
        type: DataTypes.INTEGER,
        autoIncrement: true,
        primaryKey: true,
      },
      uuid: {
        type: DataTypes.UUID,
        allowNull: false,
      },
      room_id: {
        type: DataTypes.INTEGER,
        allowNull: false,
      },
      code: {
        type: DataTypes.STRING,
        allowNull: false,
      },
    },
    {
      sequelize,
      modelName: 'Seat',
      tableName: 'seat',
    }
  );

  return Seat;
};

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;packages/catalog-service/src/models/ticket.ts&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
import { DataTypes, Model, Sequelize } from 'sequelize';

class Ticket extends Model {
  public id!: number;
  public uuid!: string;
  public session_id!: number;
  public seat_id!: number;

  static associate(models: any) {
    Ticket.belongsTo(models.Session, {
      foreignKey: 'session_id',
      as: 'session',
    });
    Ticket.belongsTo(models.Seat, {
      foreignKey: 'seat_id',
      as: 'seat',
    });
  }
}

export default (sequelize: Sequelize) =&amp;gt; {
  Ticket.init(
    {
      id: {
        type: DataTypes.INTEGER,
        autoIncrement: true,
        primaryKey: true,
      },
      uuid: {
        type: DataTypes.UUID,
        allowNull: false,
      },
      session_id: {
        type: DataTypes.INTEGER,
        allowNull: false,
      },
      seat_id: {
        type: DataTypes.INTEGER,
        allowNull: false,
      },
    },
    {
      sequelize,
      modelName: 'Ticket',
      tableName: 'ticket',
    }
  );

  return Ticket;
};

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;packages/catalog-service/src/models/address.ts&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
import { DataTypes, Model, Sequelize } from 'sequelize';

class Address extends Model {
  public id!: number;
  public uuid!: string;
  public country!: string;
  public state!: string;
  public zip_code!: string;
  public telephone!: string;
  public description!: string;
  public postal_code!: string;
  public name!: string;

  static associate(models: any) {
    Address.belongsToMany(models.Room, {
      through: models.RoomAddress,
      foreignKey: 'address_id',
      as: 'rooms',
    });
    models.Room.belongsToMany(Address, {
      through: models.RoomAddress,
      foreignKey: 'room_id',
      as: 'addresses',
    });
  }
}

export default (sequelize: Sequelize) =&amp;gt; {
  Address.init(
    {
      id: {
        type: DataTypes.INTEGER,
        autoIncrement: true,
        primaryKey: true,
      },
      uuid: {
        type: DataTypes.UUID,
        allowNull: false,
      },
      country: {
        type: DataTypes.STRING,
        allowNull: false,
      },
      state: {
        type: DataTypes.STRING,
        allowNull: false,
      },
      zip_code: {
        type: DataTypes.STRING,
        allowNull: false,
      },
      telephone: {
        type: DataTypes.STRING,
        allowNull: false,
      },
      description: {
        type: DataTypes.STRING,
        allowNull: true,
      },
      postal_code: {
        type: DataTypes.STRING,
        allowNull: true,
      },
      name: {
        type: DataTypes.STRING,
        allowNull: true,
      },
    },
    {
      sequelize,
      modelName: 'Address',
      tableName: 'address',
    }
  );

  return Address;
};

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;packages/catalog-service/src/models/roomAddress.ts&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
import { DataTypes, Model, Sequelize } from 'sequelize';

class RoomAddress extends Model {
  public id!: number;
  public uuid!: string;
  public room_id!: number;
  public address_id!: number;

  static associate(models: any) {
    RoomAddress.belongsTo(models.Room, {
      foreignKey: 'room_id',
      as: 'room',
    });
    RoomAddress.belongsTo(models.Address, {
      foreignKey: 'address_id',
      as: 'address',
    });
  }
}

export default (sequelize: Sequelize) =&amp;gt; {
  RoomAddress.init(
    {
      id: {
        type: DataTypes.INTEGER,
        autoIncrement: true,
        primaryKey: true,
      },
      uuid: {
        type: DataTypes.UUID,
        allowNull: false,
      },
      room_id: {
        type: DataTypes.INTEGER,
        allowNull: false,
      },
      address_id: {
        type: DataTypes.INTEGER,
        allowNull: false,
      },
    },
    {
      sequelize,
      modelName: 'RoomAddress',
      tableName: 'roomAddress',
    }
  );

  return RoomAddress;
};

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Por fim, iremos criar as novas tabelas ao "injetar" a instancia do sequelize, que abstrai nossa conexao, nas instancias das models/entidades recem criadas no nosso packages/catalog-microsservice/db.ts&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Sequelize&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sequelize&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Film&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./film&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Session&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./session&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Room&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./room&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Seat&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./seat&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Ticket&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./ticket&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Address&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./address&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;RoomAddress&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./roomAddress&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;max&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="na"&gt;min&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="na"&gt;acquire&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;130000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;idle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10000&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sequelize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Sequelize&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;dialect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;postgres&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;localhost&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;catalog_service_db&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;catalog_service_user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;catalog_service_password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;pool&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nc"&gt;Film&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sequelize&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;Session&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sequelize&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;Room&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sequelize&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;Seat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sequelize&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;Ticket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sequelize&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sequelize&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;RoomAddress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sequelize&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;sequelize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Ao se criar essas models e criar o vínculo em nosso &lt;code&gt;packages/catalog-microsservice/src/models/db.ts&lt;/code&gt; e rodar novamemte o comando &lt;code&gt;$ nx serve catalog-service&lt;/code&gt; devemos ter a seguinte estrutura de tabelas criadas em nosso postgres:&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%2F17vvmxiydtr650ac1jnh.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%2F17vvmxiydtr650ac1jnh.png" alt="Image description" width="591" height="546"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🤓 Conclusão (por hora)
&lt;/h2&gt;

&lt;p&gt;Vimos a importância da criação de diagramas colaborativos para iniciar o projeto e demos uma olhada em um &lt;code&gt;ADR&lt;/code&gt; simples que definia nossas escolhas técnicas e arquiteturais.&lt;/p&gt;

&lt;p&gt;Em um projeto da vida real, a partir dessas documentações, expandiríamos nosso projeto em direção à criação de tarefas menores, &lt;code&gt;issues&lt;/code&gt; no &lt;code&gt;GitHub&lt;/code&gt; ou &lt;code&gt;tasks&lt;/code&gt; no &lt;code&gt;Jira&lt;/code&gt;, para que pudéssemos desenvolver. Mas aqui, por finalidade puramente didática, já colocamos a mão na massa para criar um projeto mínimo utilizando as facilidades do &lt;code&gt;NX&lt;/code&gt;. Criamos o microsserviço de catálogo, atualizamos o seu &lt;code&gt;builder&lt;/code&gt; e a partir daí criamos nosso banco, conexão e entidades.&lt;/p&gt;

&lt;p&gt;Não falamos ainda de testes, embora tenha a forte convicção de que devemos seguir a abordagem TDD (Test-Driven Development) neste projeto. Do meu ponto de vista, não há nenhuma lógica de negócio que valha a pena ser testada unitariamente no momento.&lt;/p&gt;




&lt;h2&gt;
  
  
  👣 Próximos passos
&lt;/h2&gt;

&lt;p&gt;Vamos continuar seguindo na produção do nosso catálogo. Agora, com as entidades já relacionadas, iremos construir rotas dentro do padrão &lt;a href="https://swagger.io/" rel="noopener noreferrer"&gt;Swagger&lt;/a&gt;, respeitando o &lt;a href="https://en.wikipedia.org/wiki/Representational_state_transfer" rel="noopener noreferrer"&gt;REST&lt;/a&gt;, e a partir daí criar uma suíte de testes que garantam as operações dos nossos endpoints.&lt;/p&gt;

&lt;p&gt;Continue por aqui, pois o projeto só tende a melhorar!&lt;/p&gt;




&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;👈 Anterior&lt;/th&gt;
&lt;th&gt;Próximo 👉&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://dev.to/learningenuity/03-estudo-de-microsservicos-ingressox-monorepo-e-docker-1l7g"&gt;Monorepo &amp;amp; Docker&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;[Em Breve] &lt;del&gt;REST e e2e&lt;/del&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>braziliandevs</category>
      <category>monorepo</category>
      <category>systemdesign</category>
      <category>microservices</category>
    </item>
    <item>
      <title>03 - Estudo de Microsserviços ingresso.x - Monorepo e Docker</title>
      <dc:creator>José Antonio</dc:creator>
      <pubDate>Sat, 26 Aug 2023 20:12:25 +0000</pubDate>
      <link>https://dev.to/learningenuity/03-estudo-de-microsservicos-ingressox-monorepo-e-docker-1l7g</link>
      <guid>https://dev.to/learningenuity/03-estudo-de-microsservicos-ingressox-monorepo-e-docker-1l7g</guid>
      <description>&lt;h3&gt;
  
  
  🔓 Esse artigo é o terceiro de uma sequência de estudo em andamento.
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/jtonynet/cine-ticket-study-microsservices" rel="noopener noreferrer"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bCohonYm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.shields.io/badge/Reposit%25C3%25B3rio%2520do%2520estudo-github-181717%3Fstyle%3Dfor-the-badge%26logo%3Dgithub%26logoColor%3Dwhite" alt="github" width="279" height="28"&gt;&lt;/a&gt; &lt;a href="https://www.linkedin.com/in/jos%C3%A9-r-99896a39/" rel="noopener noreferrer"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9kqbdgfO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.shields.io/badge/Acesse%2520o%2520meu-linkedin-0A66C2%3Fstyle%3Dfor-the-badge%26logo%3Dlinkedin%26logoColor%3Dwhite" alt="linkedin" width="224" height="28"&gt;&lt;/a&gt; &lt;a href="https://twitter.com/aromademirtilo" rel="noopener noreferrer"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9ylJcV2Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.shields.io/badge/Acesse%2520o%2520meu-twitter-1D9BF0%3Fstyle%3Dfor-the-badge%26logo%3Dtwitter%26logoColor%3Dwhite" alt="twitter" width="217" height="28"&gt;&lt;/a&gt; &lt;a href="https://www.instagram.com/learningenuity/" rel="noopener noreferrer"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hUb8NGUS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.shields.io/badge/Acesse%2520o%2520meu-Instagram-E4405F%3Fstyle%3Dfor-the-badge%26logo%3Dinstagram%26logoColor%3Dwhite" alt="Instagram" width="236" height="28"&gt;&lt;/a&gt; &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vICBHb9p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.shields.io/badge/STATUS-EM_DESENVOLVIMENTO-green%3Fstyle%3Dfor-the-badge" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vICBHb9p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.shields.io/badge/STATUS-EM_DESENVOLVIMENTO-green%3Fstyle%3Dfor-the-badge" alt="Badge Status" width="250" height="28"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Padronização&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;Padronização, normalização, normatização ou estandardização é o processo de desenvolvimento e implementação de normas técnicas. A padronização tem como objetivo definir especificações técnicas que auxiliem na maximização da compatibilidade, reprodutibilidade, segurança ou qualidade de determinado processo, produto ou serviço.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Fonte: &lt;a href="https://pt.wikipedia.org/wiki/Padroniza%C3%A7%C3%A3o" rel="noopener noreferrer"&gt;Wikipédia&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;O texto abaixo é referente à branch &lt;a href="https://github.com/jtonynet/cine-ticket-study-microsservices/tree/feature/initial-main-000" rel="noopener noreferrer"&gt;feature/initial-main-000&lt;/a&gt; do repositório de estudo.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧭 Orientação
&lt;/h2&gt;

&lt;p&gt;O desenvolvimento de software é cercado de ritos, formações inteiras são criadas com o objetivo de dar assertividade ao planejamento; passando pelo defasado "Waterfall" até o "&lt;a href="https://www.amazon.com.br/Desenvolvimento-%C3%A1gil-limpo-volta-origens/dp/8550815004" rel="noopener noreferrer"&gt;Desenvolvimento Ágil e Limpo&lt;/a&gt;". Os ritos iniciais devem criar linhas gerais de desenvolvimento, as guidelines.&lt;/p&gt;

&lt;p&gt;Cada microsserviço pode ser escrito de um jeito, torna-se tentador novos serviços serem criados com a "big next thing". Devs entusiasmados podem subestimar trade-offs para adotar tecnologias emergentes diferentes das linhas gerais. Damos a isso o nome de "dispersão técnica". Cultive esse entusiasmo, mas não permita que ele aumente desordenadamente sua dispersão técnica&lt;/p&gt;

&lt;p&gt;Não estou dizendo para criar softwares sempre com &lt;em&gt;${qualquer_tecnologia_antiga}&lt;/em&gt;. Mas devemos introduzir aos poucos novas tecnologias ao que foi previamente acordado nas guidelines. Elas levam a padronização o que reduz a dispersão técnica. Devemos ter foco.&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%2Flcjxmgyihljn95yevk33.gif" 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%2Flcjxmgyihljn95yevk33.gif" alt="Image description" width="498" height="280"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  💍 Um Para a Todos Dominar
&lt;/h2&gt;

&lt;p&gt;Em projetos é comum clonar e levantar um a um repositórios git para desenvolver. Isso pode ser uma dor de cabeça  multiplicada pelas tecnologias, versões e configurações.&lt;/p&gt;

&lt;p&gt;Ciclos de Desenvolvimento, Processos de Implantação e a Introdução e Descontinuação devem ser estáveis, padronizados. Isso leva a estabilidade, primeiro princípio da &lt;strong&gt;disponibilidade&lt;/strong&gt;. Rodar o projeto deveria ser tão simples quanto o possível, no nosso caso podemos instalar o &lt;code&gt;docker&lt;/code&gt; e o &lt;code&gt;docker compose&lt;/code&gt; responsável por levantar todas as imagens necessárias para rodar local  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.docker.com/engine/install/" rel="noopener noreferrer"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6eN1nqe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.shields.io/badge/Instale%2520o%2520-docker-2496ED%3Fstyle%3Dfor-the-badge%26logo%3Ddocker%26logoColor%3Dwhite" alt="Docker" width="184" height="28"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.docker.com/compose/install/" rel="noopener noreferrer"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4nnDBj7I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.shields.io/badge/Instale%2520o%2520-docker%2520compose-2496ED%3Fstyle%3Dfor-the-badge%26logo%3Ddocker%26logoColor%3Dwhite" alt="Docker" width="252" height="28"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Após o docker e o docker compose instalados encontre o arquivo &lt;code&gt;./packages/cine-ticket-front-site/.sample_env&lt;/code&gt; e crie uma copia dele com o nome de &lt;code&gt;.env&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Arquivos &lt;code&gt;.env&lt;/code&gt; devem estar no &lt;code&gt;gitignore&lt;/code&gt; e por segurança nunca são comitados nos repositórios de código, para que não existam vazamento de dados.&lt;/p&gt;

&lt;p&gt;então na raiz do projeto, digite o seguinte comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker compose up &lt;span class="nt"&gt;--build&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Deve demorar alguns minutos até que as imagens dos &lt;code&gt;dockerfiles&lt;/code&gt; sejam construídas. Ao término do processo, acesse o endereço &lt;code&gt;http://localhost:8080&lt;/code&gt; e teremos a página inicial, o front-end de nosso projeto:&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%2Fv8y3zxg1yl7htludahau.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%2Fv8y3zxg1yl7htludahau.png" alt="Image description" width="800" height="561"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Projeto inicial rodando local após docker instalado.&lt;/em&gt;&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%2F1go1v95yh3w3s9kk4wez.gif" 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%2F1go1v95yh3w3s9kk4wez.gif" alt="Image description" width="500" height="209"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Um repositório para todos dominar!&lt;/em&gt; Um gerenciador para auxiliar nessa tarefa. São nossas guidelines, nosso padrão de desenvolvimento. Analisemos a estrutura de pastas atual da raiz do projeto (tag v0.0.0):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  &lt;span class="nv"&gt;$ &lt;/span&gt;tree
  &lt;span class="nb"&gt;.&lt;/span&gt;
  ├── .vscode
  ├── docs
  |    ├── icons
  |    ├── logo.png
  |    └── project.png
  └── packages
  |    ├── cine-ticket-front-site
  |    └── cine-ticket-nginx
  ├── .dockerignore
  ├── .eslintignore
  ├── .eslintrc.json
  ├── .gitignore
  ├── .prettierignore
  ├── .prettierrc
  ├── docker-compose.yml
  ├── jest.config.ts
  ├── jest.preset.js
  ├── nx.json
  ├── package-lock.json
  ├── package.json
  ├── README.md
  └── tsconfig.base.json

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Trata-se de um monorepo que iremos evoluir, nele se concentrarão nossos microsserviços, imagens de infra e suporte como bancos, caches, storages, filas, etc...&lt;/p&gt;

&lt;p&gt;Observe dentro da pasta &lt;code&gt;packages&lt;/code&gt; os diretórios &lt;code&gt;cine-ticket-front-site&lt;/code&gt; e &lt;code&gt;cine-ticket-nginx&lt;/code&gt;, são as aplicações que estão servindo a página &lt;code&gt;localhost:8080&lt;/code&gt;. No mesmo nível de &lt;code&gt;packages&lt;/code&gt; encontra-se o arquivo &lt;code&gt;docker-compose.yml&lt;/code&gt;, que faz tudo acontecer, vamos esmiuçá-lo a seguir:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.7'&lt;/span&gt;
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;cine-ticket-nginx&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./packages/cine-ticket-nginx&lt;/span&gt;
      &lt;span class="na"&gt;dockerfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Dockerfile&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;8080:80&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cine-ticket-front-site&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cine-ticket-network&lt;/span&gt;

  &lt;span class="na"&gt;cine-ticket-front-site&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./packages/cine-ticket-front-site&lt;/span&gt;
      &lt;span class="na"&gt;dockerfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Dockerfile&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;3080:3000&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./packages/cine-ticket-front-site/src:/usr/src/app/src&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./packages/cine-ticket-front-site/dist:/usr/src/app/dist&lt;/span&gt;
    &lt;span class="na"&gt;env_file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./packages/cine-ticket-front-site/.env&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm run start:dev&lt;/span&gt;
    &lt;span class="na"&gt;tty&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cine-ticket-network&lt;/span&gt;

&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;cine-ticket-network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nosso &lt;code&gt;dockerfile.yml&lt;/code&gt; define os serviços de:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;cine-ticket-nginx:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;build:

&lt;ul&gt;
&lt;li&gt;context: constrói a imagem a partir do diretório &lt;code&gt;./packages/cine-ticket-nginx&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;dockerfile: Usa um arquivo &lt;code&gt;Dockerfile&lt;/code&gt; que se encontra no diretório do context para dar as instruções de como montar a &lt;code&gt;imagem&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ports: Mapeia as solicitações na porta &lt;code&gt;8080&lt;/code&gt; da máquina hospedeira para porta &lt;code&gt;80&lt;/code&gt; para da imagem&lt;/li&gt;
&lt;li&gt;depends_on: O serviço &lt;code&gt;cine-ticket-front-site&lt;/code&gt; precisa estar de Pé, "up and running" antes que esse serviço esteja funcional&lt;/li&gt;
&lt;li&gt;networks: Rede na qual esta imagem vai estar integrada, para que tenhamos comunicação adequada no que podemos chamar de "por debaixo do capô" deve ser na mesma rede de sua dependência&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;cine-ticket-front-site:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;build:

&lt;ul&gt;
&lt;li&gt;context: constrói o container a partir do diretório &lt;code&gt;./packages/cine-ticket-front-site&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;dockerfile: Usa um arquivo &lt;code&gt;Dockerfile&lt;/code&gt; que se encontra no diretório do context para dar as instruções de como montar o &lt;code&gt;contêiner&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ports: Mapeia as solicitações na porta &lt;code&gt;3080&lt;/code&gt; da máquina hospedeira para porta &lt;code&gt;3000&lt;/code&gt; do contêiner&lt;/li&gt;
&lt;li&gt;volumes:

&lt;ul&gt;
&lt;li&gt;Mapeia de maneira a sincronizar diretórios entre a máquina hospedeira e o contêiner &lt;code&gt;hospedeira:contêiner&lt;/code&gt;, útil para hot-reload (esse caso em especifico) e persistência de dados.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;./packages/cine-ticket-front-site/src:/usr/src/app/src&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;./packages/cine-ticket-front-site/dist:/usr/src/app/dist&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;env_file: Define arquivo para injetar variáveis de ambiente para o container.&lt;/li&gt;
&lt;li&gt;command: comando que será executado quando o contêiner for iniciado a partir da imagem Docker&lt;/li&gt;
&lt;li&gt;tty:  Permite que você veja a saída interativa e do container.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;networks: Rede&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;networks&lt;/strong&gt;: Define a rede &lt;code&gt;cine-ticket-network&lt;/code&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Outro arquivo interessante para nossa jornada é o &lt;code&gt;./packages/cine-ticket-nginx/conf/nginx.conf&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;events&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;worker_connections&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;##&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Default:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="err"&gt;http&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;server&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;listen&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="err"&gt;location&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;proxy_set_header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;X-Real-IP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;$remote_addr;&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;proxy_set_header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;X-Forwarded-For&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;$proxy_add_x_forwarded_for;&lt;/span&gt;&lt;span class="w"&gt;

      &lt;/span&gt;&lt;span class="err"&gt;proxy_pass&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;http://cine-ticket-front-site:&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;&lt;span class="w"&gt;

      &lt;/span&gt;&lt;span class="err"&gt;proxy_set_header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;$host;&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;proxy_set_header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;X-NginX-Proxy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;proxy_redirect&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;off;&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;proxy_set_header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;X-Real-IP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;$remote_addr;&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ele define nosso proxy reverso. Um intermediário, melhorando o desempenho e a segurança, encaminhando solicitações para o serviço &lt;code&gt;cine-ticket-front-site:3000&lt;/code&gt; e manipulando os cabeçalhos para a comunicação correta entre os componentes.&lt;/p&gt;

&lt;p&gt;vamos considerar para fins didáticos que apenas as requisições servidas pelo &lt;a href="https://www.nginx.com/" rel="noopener noreferrer"&gt;NGINX&lt;/a&gt; são públicas e o restante estão debaixo da rede &lt;code&gt;cine-ticket-network&lt;/code&gt;, nossa "nuvem local" que vai possuir microsserviços privados.&lt;/p&gt;




&lt;h2&gt;
  
  
  🤓 Conclusão (por hora)
&lt;/h2&gt;

&lt;p&gt;Vimos que padronização garante estabilidade reduzindo dispersão técnica, baixamos o docker e o docker compose e entendemos como as partes do nosso monorepo interagem entre si.&lt;/p&gt;

&lt;p&gt;Adotaremos como padrão de desenvolvimento muitos dos conceitos apresentados nesse artigo para nossos futuros microsserviços.&lt;/p&gt;

&lt;p&gt;Mantenha o entusiasmo mas reduza o quanto puder a dispersão técnica.&lt;/p&gt;

&lt;p&gt;Utilizamos &lt;strong&gt;Monorepo e Docker&lt;/strong&gt; para alcançar nossos  objetivos.&lt;/p&gt;




&lt;h2&gt;
  
  
  👣 Próximos passos
&lt;/h2&gt;

&lt;p&gt;Vamos finalmente iniciar a codar nosso primeiro Microsserviço de Catálogo, a partir de diagramas propostos e com guidelines claras e objetivas que apenas boas documentações garantem.&lt;/p&gt;

&lt;p&gt;Até breve.&lt;/p&gt;




&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;👈 Anterior&lt;/th&gt;
&lt;th&gt;Próximo 👉&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://dev.to/learningenuity/02-estudo-de-microsservicos-ingressosx-desafios-2f35"&gt;Alguns Desafios&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://dev.to/learningenuity/04-estudo-de-microsservicos-ingressosx-microsservico-de-catalogo-17ed"&gt;Microsserviço de Catálogo&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>braziliandevs</category>
      <category>monorepo</category>
      <category>systemdesign</category>
      <category>microservices</category>
    </item>
    <item>
      <title>02 - Estudo de Microsserviços ingresso.x - Desafios</title>
      <dc:creator>José Antonio</dc:creator>
      <pubDate>Mon, 14 Aug 2023 15:53:22 +0000</pubDate>
      <link>https://dev.to/learningenuity/02-estudo-de-microsservicos-ingressosx-desafios-2f35</link>
      <guid>https://dev.to/learningenuity/02-estudo-de-microsservicos-ingressosx-desafios-2f35</guid>
      <description>&lt;h3&gt;
  
  
  🔓 Esse artigo é o segundo de uma sequência de estudo em andamento.
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/jtonynet/cine-ticket-study-microsservices" rel="noopener noreferrer"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bCohonYm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.shields.io/badge/Reposit%25C3%25B3rio%2520do%2520estudo-github-181717%3Fstyle%3Dfor-the-badge%26logo%3Dgithub%26logoColor%3Dwhite" alt="github" width="279" height="28"&gt;&lt;/a&gt; &lt;a href="https://www.linkedin.com/in/jos%C3%A9-r-99896a39/" rel="noopener noreferrer"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9kqbdgfO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.shields.io/badge/Acesse%2520o%2520meu-linkedin-0A66C2%3Fstyle%3Dfor-the-badge%26logo%3Dlinkedin%26logoColor%3Dwhite" alt="linkedin" width="224" height="28"&gt;&lt;/a&gt; &lt;a href="https://twitter.com/aromademirtilo" rel="noopener noreferrer"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9ylJcV2Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.shields.io/badge/Acesse%2520o%2520meu-twitter-1D9BF0%3Fstyle%3Dfor-the-badge%26logo%3Dtwitter%26logoColor%3Dwhite" alt="twitter" width="217" height="28"&gt;&lt;/a&gt; &lt;a href="https://www.instagram.com/learningenuity/" rel="noopener noreferrer"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hUb8NGUS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.shields.io/badge/Acesse%2520o%2520meu-Instagram-E4405F%3Fstyle%3Dfor-the-badge%26logo%3Dinstagram%26logoColor%3Dwhite" alt="Instagram" width="236" height="28"&gt;&lt;/a&gt; &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vICBHb9p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.shields.io/badge/STATUS-EM_DESENVOLVIMENTO-green%3Fstyle%3Dfor-the-badge" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vICBHb9p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.shields.io/badge/STATUS-EM_DESENVOLVIMENTO-green%3Fstyle%3Dfor-the-badge" alt="Badge Status" width="250" height="28"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Falácias&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;A palavra tem origem no termo em latim “fallacia”, aquilo que engana ou ilude. Desta forma, falácia será algo enganoso. As falácias são construídas por raciocínios aparentemente corretos que levam à falsas conclusões.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Fonte: Site &lt;a href="https://www.significados.com.br/falacia/#:~:text=Fal%C3%A1cia%20significa%20erro%2C%20engano%20ou,de%20proposi%C3%A7%C3%B5es%20que%20s%C3%A3o%20falsas." rel="noopener noreferrer"&gt;Significados.com.br&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;O texto abaixo é referente à branch &lt;a href="https://github.com/jtonynet/cine-ticket-study-microsservices/tree/feature/initial-main-000" rel="noopener noreferrer"&gt;feature/initial-main-000&lt;/a&gt; do repositório de estudo.&lt;/p&gt;




&lt;h2&gt;
  
  
  🐘 na sala (Falácias, Trade-offs e CAP)
&lt;/h2&gt;

&lt;p&gt;Antes de começarmos, é importante observar o &lt;strong&gt;elefante na sala&lt;/strong&gt; e aprender a conviver com ele. Tive a experiência de trabalhar com monólito, aplicação única e gigantesca, e ajudei "lapida-los" em serviços menores, mas isso não se deu por "mágica". &lt;em&gt;Algumas coisas pareciam corretas mas nos levaram à falsas conclusões&lt;/em&gt; e erros foram cometidos. Desejamos ser um pouco mais eficientes do que "tentativa e erro" pura e simples, precisamos "falhar rápido" e acertar nossos equívocos. &lt;a href="https://en.wikipedia.org/wiki/Fail-fast" rel="noopener noreferrer"&gt;Fail fast&lt;/a&gt; deve ser permitido e incentivado. Mas ele, o elefante, continuava lá, se recusando a sair da sala.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Estrangular&lt;/strong&gt; do &lt;strong&gt;&lt;a href="https://www.redhat.com/architect/pros-and-cons-strangler-architecture-pattern" rel="noopener noreferrer"&gt;Strangler Pattern&lt;/a&gt;&lt;/strong&gt;, é como nos referimos ao processo de trocar responsabilidades de um monólito em serviços menores. Eu preferia que o termo fosse &lt;strong&gt;lapidar&lt;/strong&gt;  por ser mais respeitoso ao que viabilizou o negócio, mas o mercado usa tecnicamente o termo "estrangular". Um &lt;a href="https://www.amazon.com.br/Programador-Pragm%C3%A1tico-Aprendiz-Mestre-ebook/dp/B019HM0H90" rel="noopener noreferrer"&gt;Programador Pragmático&lt;/a&gt; segundo &lt;a href="https://en.wikipedia.org/wiki/Andy_Hunt_(author)" rel="noopener noreferrer"&gt;Andy Hunt&lt;/a&gt;, entende que:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;'&lt;em&gt;Um bom software hoje geralmente é preferível a um software perfeito amanhã. Se você der a seus usuários algo com que brincar desde o início, o feedback deles geralmente o levará a uma solução final melhor.&lt;/em&gt;' &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Não é objetivo desse estudo definir por onde começar esse estrangulamento ou seus microsserviços, mas é importante que o leitor saiba ou relembre o conceito de &lt;a href="https://medium.com/rd-shipit/descoberta-dos-dom%C3%ADnios-ddd-do-rd-station-marketing-atrav%C3%A9s-do-eventstorming-5c4743d5b7ea" rel="noopener noreferrer"&gt;descoberta dos domínios&lt;/a&gt;. No mundo ideal, ele foi feito antes. O artigo do link explica bem e continua na metáfora do elefante :D&lt;/p&gt;




&lt;h2&gt;
  
  
  🗣️ Falácias
&lt;/h2&gt;

&lt;p&gt;Aplicações passam por evoluções, monólitos para escalar com disponibilidade, após comprovado modelo de negócio, podem ser "tunados" (um pente fino com otimizações na própria codebase, banco e infra), porém não raro são "estranguladas" a partir de feedbacks como: site lento, quedas, área "x" inacessível, etc...&lt;/p&gt;

&lt;p&gt;Aprendi na dor as &lt;a href="https://nighthacks.com/jag/res/Fallacies.html" rel="noopener noreferrer"&gt;Falácias de Microsserviços&lt;/a&gt;, dentre as quais "&lt;em&gt;a largura de banda não é infinita, rastreabilidade é difícil e existem custos!&lt;/em&gt;" podem causar mais danos. A medida que a solução distribuída for sendo construída apontarei quais foram as dores que já tive no processo.&lt;/p&gt;

&lt;p&gt;Temos que ter cuidado com as soluções dos pontos de feedback, distribuir responsabilidades também é distribuir desafios e você pode estar substituindo um problema por vários outros. É necessária análise de opções para não se transformar no que pejorativamente é chamado de "monólito distribuído", ou seja um parque de microsserviços mal implementados e/ou com domínios mal planejados. Aqueles que não levaram em conta as Falácias e com Trade-offs inadequados. Causam mais dor ao negócio do que o monólito que visavam substituir.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔄 Trade-offs
&lt;/h2&gt;

&lt;p&gt;Nem mesmo projetos de software novos, chamados de "&lt;a href="https://en.wikipedia.org/wiki/Greenfield_project" rel="noopener noreferrer"&gt;greenfield&lt;/a&gt;", estão livres de decisões que tragam benefícios por um lado, mas dificultam a implantação futura de certos recursos por outro. Chamamos isso de &lt;strong&gt;&lt;a href="https://en.wikipedia.org/wiki/Trade-off" rel="noopener noreferrer"&gt;Trade-offs&lt;/a&gt;&lt;/strong&gt; ou &lt;strong&gt;compensações&lt;/strong&gt;. Se nem novos projetos escapam de tradeOffs, imaginem os que já estão rodando, os estrangulados.&lt;/p&gt;

&lt;p&gt;Caches garantem que sua aplicação não caia mas por outro lado aumentam o tempo que atualizações cheguem aos seus clientes. Um banco NoSql é ótimo para documentos mas podem não garantir a consistência apresentada por um relacional. Isso são compensações&lt;/p&gt;

&lt;p&gt;Mesmo a &lt;a href="https://www.primevideotech.com/video-streaming/scaling-up-the-prime-video-audio-video-monitoring-service-and-reducing-costs-by-90" rel="noopener noreferrer"&gt;Amazon &lt;em&gt;propagadora de microsserviços, "sofreu" com seus Trade-offs&lt;/em&gt;&lt;/a&gt;, e nobres, leiam o artigo deles antes de dizerem: &lt;em&gt;"A Amazon voltou aos monólitos, RUN THE HILLS"&lt;/em&gt;, por favor!&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%2Fw8oxckmke9v7apgzdw48.gif" 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%2Fw8oxckmke9v7apgzdw48.gif" alt="Principal Engineer, lidando com Trade-offs" width="640" height="332"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Principal Engineer da Amazon, Bruce Wayne, lidando com Trade-offs (estavam no carnaval, por isso a fantasia de Batman 🦇, não, pera...)&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🔀 Teorema de CAP
&lt;/h2&gt;

&lt;p&gt;Entendidos os Trade-offs e cientes que não temos como escapar deles, chegamos ao &lt;strong&gt;&lt;a href="https://en.wikipedia.org/wiki/CAP_theorem" rel="noopener noreferrer"&gt;Teorema de CAP&lt;/a&gt;&lt;/strong&gt; um tripé onde devemos escolher dois de seus pilares para privilegiar, ou como gosto de chamar &lt;em&gt;"não se pode ter tudo"&lt;/em&gt;.&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%2Fn56rsaf6nttsxie87qz3.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%2Fn56rsaf6nttsxie87qz3.png" alt="Image description" width="800" height="796"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Imagem retirada do artigo wiki citado acima&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Um resumo desse tripé seria:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;C&lt;/strong&gt;onsistency (Consistência)

&lt;ul&gt;
&lt;li&gt;Privilegia que os dados entre os microsserviços sejam sempre os mais atualizados, pense no nosso estudo de caso que o filme "X" foi cadastrado adequadamente. Quanto tempo para ser exibido no website? Quanto tempo para ser exibido no aplicativo mobile, ele existindo? Comprei o ingresso de um assento, quanto tempo para aquela cadeira não estar mais disponível para outro usuário?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A&lt;/strong&gt;vailability (Disponibilidade)

&lt;ul&gt;
&lt;li&gt;Caso tenha lido o primeiro artigo, já sabe que a seguinte pergunta deve ser respondida na "regra dos nove". Por quantas horas percentuais durante um ano meu site e/ou aplicativo mobile estiveram de pé?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;P&lt;/strong&gt;artition Tolerance (Tolerância a Partição de Rede)

&lt;ul&gt;
&lt;li&gt;Seus microsserviços toleram que um nó, instância, deles caia? O sistema como um todo vai continuar respondendo a queda de um ou mais nós?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Em minha experiência centrada em negócios que ofertam produtos ou serviços, dentre o tripé do "CAP" sempre tendíamos por uma alta "regra dos nove" ou seja &lt;em&gt;Availability&lt;/em&gt; e caso um nó de serviço caia, que isso não afete a aplicação e prontamente outro o substitua para que não exista impacto nas vendas ou seja &lt;em&gt;Partition Tolerance&lt;/em&gt;.&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%2F6c4olj762agdi09f3mn3.gif" 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%2F6c4olj762agdi09f3mn3.gif" alt="Image description" width="400" height="347"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como cada escolha é uma renúncia, percebam que esse foco em vendas deixa descoberta a característica de ter sempre o dado mais atualizado em todos os pontos de nosso sistema ou seja a &lt;em&gt;Consistency&lt;/em&gt;. Agimos na intersecção "AP" do diagrama. Essa abordagem encontra como maior trade-Off a &lt;a href="https://pt.wikipedia.org/wiki/Consist%C3%AAncia_posterior" rel="noopener noreferrer"&gt;Consistência eventual OU Consistência posterior&lt;/a&gt; como também pode ser chamada.&lt;/p&gt;

&lt;p&gt;No nosso caso pode ocorrer de em um delta de tempo, vendermos o mesmo ingresso duas vezes e a ultima compra deve ser cancelada Ou vender um ingresso para um filme que tiramos de exibição. Isso pode acontecer e devemos trabalhar para mitigar.&lt;/p&gt;




&lt;h2&gt;
  
  
  🤓 Conclusão (por hora)
&lt;/h2&gt;

&lt;p&gt;Vimos que há um elefante na sala, e ele sempre existirá. Coisas que podemos tomar por certas, podem nos enganar no contexto de serviços distribuídos. Também vimos "&lt;em&gt;Compensações ou Trade-offs&lt;/em&gt;" que valem para toda a extensão de desenvolvimento de software e não apenas aos microsserviços e o "&lt;em&gt;teorema de CAP&lt;/em&gt;".&lt;/p&gt;

&lt;p&gt;Não somos capazes de atender "&lt;em&gt;Consistência, Disponibilidade e Tolerância a Partição de Rede&lt;/em&gt;" ao mesmo tempo e em minha experiência as duas ultimas são as atendidas a favor de venda/prestação de serviço constantes (alta disponibilidade, regra dos nove e Tolerância),  causando a chamada "&lt;em&gt;Consistência eventual OU Consistência posterior&lt;/em&gt;" que pode ser mitigada mas não suprimida&lt;/p&gt;

&lt;p&gt;Esses são nossos &lt;strong&gt;Desafios!&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  👣 Próximos passos
&lt;/h2&gt;

&lt;p&gt;Em próximos artigos vamos dar inicio ao projeto técnico.&lt;br&gt;
Temos a teoria, sabemos que existem desafios mas a disponibilidade deve ser garantida.&lt;/p&gt;

&lt;p&gt;Vamos trabalhar em favor de uma &lt;a href="https://github.blog/2023-06-08-developer-experience-what-is-it-and-why-should-you-care/" rel="noopener noreferrer"&gt;"dev experience" ou "DevEx"&lt;/a&gt;, começando a criar e padronizar nossos processos que levam a &lt;strong&gt;estabilidade&lt;/strong&gt;, primeiro princípio da disponibilidade&lt;/p&gt;

&lt;p&gt;Até breve.&lt;/p&gt;




&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;👈 Anterior&lt;/th&gt;
&lt;th&gt;Próximo 👉&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://dev.to/learningenuity/01-estudo-de-microsservicos-ingressosx-motivacao-355j"&gt;A Motivação&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://dev.to/learningenuity/03-estudo-de-microsservicos-ingressox-monorepo-e-docker-1l7g"&gt;Monorepo com Docker&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>braziliandevs</category>
      <category>monorepo</category>
      <category>systemdesign</category>
      <category>microservices</category>
    </item>
    <item>
      <title>01 - Estudo de Microsserviços ingresso.x - Motivação</title>
      <dc:creator>José Antonio</dc:creator>
      <pubDate>Thu, 27 Jul 2023 06:14:27 +0000</pubDate>
      <link>https://dev.to/learningenuity/01-estudo-de-microsservicos-ingressosx-motivacao-355j</link>
      <guid>https://dev.to/learningenuity/01-estudo-de-microsservicos-ingressosx-motivacao-355j</guid>
      <description>&lt;h3&gt;
  
  
  🔓 Esse artigo é o primeiro de uma sequência de estudo em andamento.
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/jtonynet/cine-ticket-study-microsservices" rel="noopener noreferrer"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bCohonYm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.shields.io/badge/Reposit%25C3%25B3rio%2520do%2520estudo-github-181717%3Fstyle%3Dfor-the-badge%26logo%3Dgithub%26logoColor%3Dwhite" alt="github" width="279" height="28"&gt;&lt;/a&gt; &lt;a href="https://www.linkedin.com/in/jos%C3%A9-r-99896a39/" rel="noopener noreferrer"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9kqbdgfO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.shields.io/badge/Acesse%2520o%2520meu-linkedin-0A66C2%3Fstyle%3Dfor-the-badge%26logo%3Dlinkedin%26logoColor%3Dwhite" alt="linkedin" width="224" height="28"&gt;&lt;/a&gt; &lt;a href="https://twitter.com/aromademirtilo" rel="noopener noreferrer"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9ylJcV2Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.shields.io/badge/Acesse%2520o%2520meu-twitter-1D9BF0%3Fstyle%3Dfor-the-badge%26logo%3Dtwitter%26logoColor%3Dwhite" alt="twitter" width="217" height="28"&gt;&lt;/a&gt; &lt;a href="https://www.instagram.com/learningenuity/" rel="noopener noreferrer"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hUb8NGUS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.shields.io/badge/Acesse%2520o%2520meu-Instagram-E4405F%3Fstyle%3Dfor-the-badge%26logo%3Dinstagram%26logoColor%3Dwhite" alt="Instagram" width="236" height="28"&gt;&lt;/a&gt; &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vICBHb9p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.shields.io/badge/STATUS-EM_DESENVOLVIMENTO-green%3Fstyle%3Dfor-the-badge" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vICBHb9p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.shields.io/badge/STATUS-EM_DESENVOLVIMENTO-green%3Fstyle%3Dfor-the-badge" alt="Badge Status" width="250" height="28"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Microsserviço&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;Pequena aplicação, executa uma única tarefa e o faz com eficiência.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Fonte: Livro &lt;a href="https://www.amazon.com.br/Microsservi%C3%A7os-Prontos-Para-Produ%C3%A7%C3%A3o-Padronizados/dp/8575226215" rel="noopener noreferrer"&gt;Microsserviços Prontos para Produção&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;O texto abaixo é referente à branch &lt;a href="https://github.com/jtonynet/cine-ticket-study-microsservices/tree/feature/initial-main-000" rel="noopener noreferrer"&gt;feature/initial-main-000&lt;/a&gt; do repositório de estudo.&lt;/p&gt;




&lt;h2&gt;
  
  
  📚 Motivação:
&lt;/h2&gt;

&lt;p&gt;A pandemia foi gatilho para muitas pessoas. Com incertezas enormes, alguns tiveram sérios problemas e outros aproveitaram a oportunidade entre cursos e leituras. Podendo ocorrer picos e vales de ambos os espectros na mesma pessoa. É importante não julgar ninguém por suas fases mais complicadas!&lt;/p&gt;

&lt;p&gt;Nesse contexto, quis superar a minha “sina dos 30% de leitura". A cada 10 livros, lia 3 deles até o final (geralmente arquitetura) ou chegava até um terço de outros (ainda assim melhor que Valve com  trilogias, cadê o Half Life 3?)&lt;/p&gt;

&lt;p&gt;Não sinto "culpa" por essa "sina" pois livros com foco em ferramentas tendem a ficar obsoletos rapidamente e documentação, cursos e palestras são boas alternativas que suprem o &lt;strong&gt;estudo constante&lt;/strong&gt;. Mas gosto do hábito da leitura com fichamentos, marcações e &lt;a href="https://www.amazon.com.br/gp/product/8531615259/ref=ewc_pr_img_3?smid=A1ZZFT5FULY4LN&amp;amp;psc=1" rel="noopener noreferrer"&gt;mapas mentais&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Organizando a estante entre livros novos e antigos, destacou-se o já aniversariante na prateleira &lt;a href="https://www.amazon.com.br/Microsservi%C3%A7os-Prontos-Para-Produ%C3%A7%C3%A3o-Padronizados/dp/8575226215" rel="noopener noreferrer"&gt;Microsserviços Prontos Para Produção&lt;/a&gt; de &lt;a href="https://en.wikipedia.org/wiki/Susan_Fowler" rel="noopener noreferrer"&gt;Susan Fowler&lt;/a&gt; (sem parentesco com outro Fowler famoso, o &lt;a href="https://martinfowler.com/" rel="noopener noreferrer"&gt;Martin Fowler&lt;/a&gt;) Peguei o bendito, “curto” e focado em &lt;strong&gt;disponibilidade&lt;/strong&gt;. Alguns dirão que &lt;a href="https://samnewman.io/" rel="noopener noreferrer"&gt;Sam Newman&lt;/a&gt; seria a melhor escolha. Mas fui na da ex-SRE do Uber por alguns motivos pessoais.&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%2Fhbs3w1raeumxzqu4c1lv.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%2Fhbs3w1raeumxzqu4c1lv.png" alt="Novos Livros chegando na estante" width="720" height="748"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Charge do &lt;a href="https://padrim.com.br/linhadotrem" rel="noopener noreferrer"&gt;linhadotrem&lt;/a&gt;, mas poderia muito bem ser minha estante&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A leitura de um tema já conhecido dos meus últimos anos de trabalho, foi ao encontro de um &lt;a href="https://www.youtube.com/watch?v=0TMr8rsmU-k" rel="noopener noreferrer"&gt;vídeo sobre a escalabilidade de determinado site de ingressos&lt;/a&gt; que um amigo sugeriu assistir. O mapa mental que fiz do livro se encaixou com minha experiência junto a esse vídeo.&lt;/p&gt;

&lt;p&gt;Pronto, deu vontade de fazer a minha implementação, de maneira educacional, do projeto sugerido pelo vídeo.&lt;/p&gt;

&lt;p&gt;Em arquitetura de Software &lt;strong&gt;&lt;a href="https://martinfowler.com/bliki/MonolithFirst.html" rel="noopener noreferrer"&gt;Monolith First&lt;/a&gt;&lt;/strong&gt; sempre! Uma aplicação única e gigantesca que valida seu negócio. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Para algo que não se sabe ao certo como vai escalar, iniciar na técnica de monólitos seria o mais adequado" - &lt;a href="https://www.s2n.com.br/pt/" rel="noopener noreferrer"&gt;Renato Viço&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Diz o mais precavido e ele geralmente está certo! Mas problemas específicos como alta &lt;strong&gt;disponibilidade&lt;/strong&gt;, requerem soluções específicas. “Não existem balas de prata” ou o já famoso "depende!"&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%2F2czbl0cb1p4jwccjdc7j.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%2F2czbl0cb1p4jwccjdc7j.png" alt="Papagaio aprende a falar depende e vira Dev Sênior" width="693" height="411"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🏃 Falando sobre Disponibilidade:
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;'Microsserviços parecem uma &lt;strong&gt;solução mágica&lt;/strong&gt; (e um tanto óbvia), mas sabemos que não é bem assim. Em The Mythical Man-Month (&lt;a href="https://www.amazon.com.br/m%C3%ADtico-homem-m%C3%AAs-ensaios-engenharia-software/dp/8550802530" rel="noopener noreferrer"&gt;O Mítico Homem-mês&lt;/a&gt;), &lt;a href="https://en.wikipedia.org/wiki/Fred_Brooks" rel="noopener noreferrer"&gt;Frederick Brooks&lt;/a&gt; explicou por que não existem balas de prata na engenharia de software, uma ideia que ele resumiu da seguinte forma: "Não há um único desenvolvimento, em tecnologia ou técnicas de gerenciamento, que sozinho prometa até mesmo uma melhoria de uma ordem de grandeza dentro de uma década em termos de produtividade, confiabilidade e simplicidade."’&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Citação do livro Microsserviços Prontos Para Produção citando outro livro relevante.&lt;br&gt;
Estudar é construção de conhecimento ou uma constante "Inception".&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Pelo tamanho do desafio, “um site nacional que atenda a demanda da compra de entradas para lançamentos de filmes Blockbusters simultâneos” o que seria equivalente a uma varejista escalar em uma BlackFriday, faz sentido o uso de serviços distribuídos de &lt;strong&gt;catálogo&lt;/strong&gt;, &lt;strong&gt;autorização&lt;/strong&gt;, &lt;strong&gt;reservas&lt;/strong&gt;, &lt;strong&gt;pagamentos&lt;/strong&gt; e &lt;strong&gt;orquestração&lt;/strong&gt; e cada um deles possuírem seus próprios níveis de &lt;strong&gt;disponibilidade&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disponibilidade&lt;/strong&gt; é uma meta, medida na "regra dos 9" ou quantas casas com o numero 9 relativo ao percentual de tempo sua solução atende? Ou &lt;strong&gt;disponibilidade = uptime/(uptime+downtime)&lt;/strong&gt;, onde uptime é o tempo que sua aplicação respondeu adequadamente aos requests o inverso de downtime, quando existe falha.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Downtime permitido:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Disponibilidade 99% (dois noves):&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;3,65 dias/ano&lt;/li&gt;
&lt;li&gt;7,20 horas/mês&lt;/li&gt;
&lt;li&gt;1,68 horas/semana&lt;/li&gt;
&lt;li&gt;14,4 minutos/dia&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Disponibilidade 99,9% (três noves):&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;8,76 horas/ano&lt;/li&gt;
&lt;li&gt;43,8 minutos/mês&lt;/li&gt;
&lt;li&gt;10,1 minutos/semana&lt;/li&gt;
&lt;li&gt;1,44 minuto/dia&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Disponibilidade 99,99% (quatro noves):&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;52,56 minutos/ano&lt;/li&gt;
&lt;li&gt;4,38 minutos/mês&lt;/li&gt;
&lt;li&gt;1,01 minuto/semana&lt;/li&gt;
&lt;li&gt;8,66 segundos/dia&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Disponibilidade 99,999% (cinco noves):&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;5,26 minutos/ano&lt;/li&gt;
&lt;li&gt;25,9 segundos/mês&lt;/li&gt;
&lt;li&gt;6,05 segundos/semana&lt;/li&gt;
&lt;li&gt;864,3 milissegundos/dia&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Partindo de um modelo mais "simples", síncrono e bloqueante; devo ir implementando soluções mais elaborados de &lt;a href="https://www.amazon.com.br/System-Design-Interview-Insiders-English-ebook/dp/B08B3FWYBX" rel="noopener noreferrer"&gt;System Design&lt;/a&gt; aos poucos. O objetivo é estudar e compartilhar, tendo disponibilidade como foco, podendo passar por assíncrona e não bloqueante até chegar em uma solução Orientada a Eventos.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Princípios de disponibilidade:&lt;/strong&gt;&lt;br&gt;
Para alcançar essa meta temos alguns princípios, os que irei adotar por hora são esses: &lt;em&gt;Estabilidade, Confiabilidade, Escalabilidade, Desempenho e Documentação&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Então rascunhei o projeto tendo esses princípios em mente e devo ir  avançando com ‘baby steps’ indicando nos futuros artigos o que implementei para cada princípio.&lt;/p&gt;

&lt;p&gt;Todos demandam um investimento de estudo nesse momento e pretendo ir a favor do &lt;strong&gt;desenvolvimento iterativo e incremental&lt;/strong&gt;. Iniciando por um &lt;a href="https://monorepo.tools/" rel="noopener noreferrer"&gt;monorepo&lt;/a&gt; e ir escalando. Os princípios que dependem única exclusivamente do desenvolvedor sendo implantados de forma “simples” e ir adicionando complexidade aos poucos.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Diagrama&lt;/strong&gt;:&lt;br&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%2Fj103do44bmh7mag1zrva.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%2Fj103do44bmh7mag1zrva.png" alt="Diagrama de Arquitetura de Microserviços" width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Já o Princípio de "&lt;em&gt;Monitoramento&lt;/em&gt;", no momento foi excluido por depender de trabalho conjunto a &lt;a href="https://aws.amazon.com/pt/devops/what-is-devops/" rel="noopener noreferrer"&gt;DevOps&lt;/a&gt; e embora pretenda implantar um minimo, não é meu objetivo me aprofundar nisso por hora. Em cenário real seria imprescindível, mas pretendo ter um &lt;strong&gt;MVP&lt;/strong&gt; (Produto Viável Mínimo) sem as soluções de infra para Monitoramento por enquanto.&lt;/p&gt;




&lt;h2&gt;
  
  
  🤓 Conclusão (por hora)
&lt;/h2&gt;

&lt;p&gt;Vimos o que gerou a criação deste estudo. Pandemia como um catalisador, incentivando leitura técnica e como ela me levou a observar outras abordagens a problemas que já vivenciei e estudei em outras mídias como: cursos, videos e palestras.&lt;/p&gt;

&lt;p&gt;A sugestão de um vídeo de influenciador que deu origem a esse estudo de implementação sob a luz dos meus conhecimentos prévios e recém adquiridos em áreas de constante evolução&lt;/p&gt;

&lt;p&gt;Vimos também, disponibilidade como métrica para o sucesso de soluções de internet e quais dos seus princípios pretendo aplicar no meu repositório de estudos&lt;/p&gt;

&lt;p&gt;Essa é minha &lt;strong&gt;Motivação!&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  👣 Próximos passos
&lt;/h2&gt;

&lt;p&gt;Próximos artigos "mais técnicos" virão. Compartilhar esse experimento no espírito de aprender em público, fixando  conteúdo e documentando informalmente o processo. Quando ensinamos também aprendemos.&lt;/p&gt;

&lt;p&gt;Fujam de suas "sinas de 30%" ou seja lá qual for a &lt;strong&gt;crença limitante&lt;/strong&gt; que possa estar te impedindo de &lt;strong&gt;evoluir&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Até breve.&lt;/p&gt;




&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;👈 Anterior&lt;/th&gt;
&lt;th&gt;Próximo 👉&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://dev.to/learningenuity/02-estudo-de-microsservicos-ingressosx-desafios-2f35"&gt;Alguns Desafios&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>braziliandevs</category>
      <category>monorepo</category>
      <category>systemdesign</category>
      <category>microservices</category>
    </item>
  </channel>
</rss>
