<?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: Zayniddin Atabaev</title>
    <description>The latest articles on DEV Community by Zayniddin Atabaev (@zayniddindev).</description>
    <link>https://dev.to/zayniddindev</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%2F1131439%2F708bfd1f-c064-4492-afcb-25ab82787c95.jpg</url>
      <title>DEV Community: Zayniddin Atabaev</title>
      <link>https://dev.to/zayniddindev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/zayniddindev"/>
    <language>en</language>
    <item>
      <title>Node.js uchun ORM tanlaymiz!</title>
      <dc:creator>Zayniddin Atabaev</dc:creator>
      <pubDate>Sat, 26 Apr 2025 11:49:17 +0000</pubDate>
      <link>https://dev.to/zayniddindev/nodejs-uchun-orm-tanlaymiz-433</link>
      <guid>https://dev.to/zayniddindev/nodejs-uchun-orm-tanlaymiz-433</guid>
      <description>&lt;p&gt;Postda o'zim eng asosiylari deb bilgan 5 ta ORM'ni taqqoslamoqchiman: Prisma, TypeORM, Sequalize, Drizzle va Objection.js. Kyselyni ham qo'shmoqchi edim, lekin u shunchaki query builder bo'lgani uchun uni qo'shmaslikka qaror qildim, lekin u ham yaxshi tool. Quyida turli kategoriyalar bo'yicha o'z fikrlarim bilan bo'lishaman.&lt;/p&gt;

&lt;h2&gt;
  
  
  Querying
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Prisma - ✅✅ a'lo darajada! O'zi client library generate qilib beradi va shuni metodlarini ishlatasiz. Query builder yo'q ☹️&lt;/li&gt;
&lt;li&gt;TypeORM - ✅ yaxshi, o'zini model metodlarini ishlatasiz. Query builder bor lekin unchalik ham zo'r deb bo'lmaydi, shaxsan meni asabimni o'ynaydi&lt;/li&gt;
&lt;li&gt;Sequelize - ✅ yaxshi, o'zini model metodlarini ishlatasiz. Query builder yo'q ☹️&lt;/li&gt;
&lt;li&gt;Drizzle - ✅✅ a'lo darajada! Query builder ham bo'r! (batteries included dermidi😄)&lt;/li&gt;
&lt;li&gt;Objection.js - ✅ yaxshi, chunki u Knex.js!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Type Safety
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Prisma - ✅✅ a'lo darajada!&lt;/li&gt;
&lt;li&gt;TypeORM - ✅ yaxshi va asosan o'zizga bog'liq :)&lt;/li&gt;
&lt;li&gt;Sequelize - ❌ by default support yo'q, &lt;a href="https://sequelize.org/docs/v6/other-topics/typescript/" rel="noopener noreferrer"&gt;bir amallasa bo'ladi&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Drizzle - ✅✅ a'lo darajada!&lt;/li&gt;
&lt;li&gt;Objection.js - ⚠️ &lt;a href="https://github.com/Vincit/objection.js/blob/main/typings/objection/index.d.ts" rel="noopener noreferrer"&gt;bor&lt;/a&gt;, lekin zo'r emas ☹️&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Schema definition
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Prisma - o'zini &lt;code&gt;.prisma&lt;/code&gt; faylida yozasiz. Declarative va sodda&lt;/li&gt;
&lt;li&gt;TypeORM - TypeScript decoratorlar bilan entitiy classlar yaratasiz, umuman olganda yaxshi&lt;/li&gt;
&lt;li&gt;Sequelize - object qilib yozasiz, shunchaki norm&lt;/li&gt;
&lt;li&gt;Drizzle - function'lar ko'rinishida yozasiz, menga yoqadi!&lt;/li&gt;
&lt;li&gt;Objection.js - class qilib yozasiz, JSON schema bilan input validation qo'shsa bo'ladi, lekin juda unchalik declarative emas&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Migration support
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Prisma - ✅✅ a'lo darajada! prisma cli tool orqali migratsiya yaratish va yuritish mumkin, yoki dev env uchun shunchaki database bilan sync qilsa bo'ladi, migratsiya querylarni generate qilishi yaxshi&lt;/li&gt;
&lt;li&gt;TypeORM - ⚠️ o'rtacha, cli tool bor lekin unchalik aniq migration querylar generate qilib bermaydi va asosan &lt;a href="https://github.com/typeorm/typeorm/issues/3280" rel="noopener noreferrer"&gt;buggy&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Sequelize - ✅ yaxshi, chidasa bo'ladi&lt;/li&gt;
&lt;li&gt;Drizzle - ✅✅ Prisma!&lt;/li&gt;
&lt;li&gt;Objection.js - ⚠️ Knex orqali qilishgan va migration querylarni o'zingiz yozib chiqishingiz kerak ☹️&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Performance
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/zayniddindev/orm-battle" rel="noopener noreferrer"&gt;Stupid performance testdan&lt;/a&gt; olgan natijalarim (Insertion time of 100k users):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prisma: 2:12.528 (m:ss.mmm)&lt;/li&gt;
&lt;li&gt;TypeORM: 3:24.115 (m:ss.mmm)&lt;/li&gt;
&lt;li&gt;Sequelize: 2:05.304 (m:ss.mmm)&lt;/li&gt;
&lt;li&gt;Drizzle: 👑 1:41.666 (m:ss.mmm)&lt;/li&gt;
&lt;li&gt;Objection.js: 1:53.682 (m:ss.mmm)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Community &amp;amp; Ecosystem
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Prisma - ✅✅ a'lo darajada!&lt;/li&gt;
&lt;li&gt;TypeORM - ✅ yaxshi, lekin maintenance negadir uncha yaxshimasday oxirgi vaqtlarda ☹️&lt;/li&gt;
&lt;li&gt;Sequelize - ✅ yaxshi, lekin asosan qariyabdi va asta sekinlik bilan undan voz kechishyabdi ☹️&lt;/li&gt;
&lt;li&gt;Drizzle - ✅ tez o'syabdi, lekin baribir nisbatan yosh&lt;/li&gt;
&lt;li&gt;Objection.js - ⚠️ unchalik emas to'g'risi, norm&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Developer experience, a.k.a. DX (or my own experience🙂)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Prisma - ✅✅ a'lo darajada!&lt;/li&gt;
&lt;li&gt;TypeORM - ✅ yaxshi, lekin yana aytaman, ko'p asab buzadi ☹️&lt;/li&gt;
&lt;li&gt;Sequelize - ⚠️ unchalik zo'r emas to'g'risi, shunga o'zi undan kechishyabdi deb o'ylayman&lt;/li&gt;
&lt;li&gt;Drizzle - ✅✅ a'lo darajada!&lt;/li&gt;
&lt;li&gt;Objection.js - ✅ amallasa bo'ladi :)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Xulosa
&lt;/h2&gt;

&lt;p&gt;Prisma yoki Drizzle ishlating. The end!&lt;/p&gt;

</description>
      <category>orm</category>
      <category>node</category>
      <category>sql</category>
    </item>
    <item>
      <title>Transaction against concurrency</title>
      <dc:creator>Zayniddin Atabaev</dc:creator>
      <pubDate>Fri, 14 Jun 2024 19:13:11 +0000</pubDate>
      <link>https://dev.to/zayniddindev/transaction-against-concurrency-18hf</link>
      <guid>https://dev.to/zayniddindev/transaction-against-concurrency-18hf</guid>
      <description>&lt;p&gt;Keling kichik app yasab ko'ramiz. Aytaylik user registratsiya qilmoqchimiz, stack uchun Express.js + PostgreSQL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&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;pg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pg&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="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="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="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&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;dbClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;pg&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="s2"&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;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;root&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="s2"&gt;1234&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="s2"&gt;test&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&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;checkEmailExist&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&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;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;dbClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s2"&gt;`SELECT id
    FROM users
    WHERE email = $1
    LIMIT 1`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rowCount&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&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;registerUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;dbClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s2"&gt;`INSERT INTO users (email)
     VALUES ($1)
     RETURNING id`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&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;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/register&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&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="c1"&gt;// get email from request body&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// check if email is not taken&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;emailExist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;checkEmailExist&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;emailExist&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&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;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Email already exist&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// register new user&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;registerUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&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;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;User registered successfully!&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="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;dbClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&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="mi"&gt;3000&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="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="s2"&gt;OLD server is running on port 3000&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="k"&gt;catch &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="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="nf"&gt;error&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="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Boshlanishiga hammasi yaxshi. App lauch bo'ldi va minglab foydalanuvchilar ro'yhatdan o'tdi. Keyin database'ga bir qarab ko'rsangiz ba'zi email'lar duplicate bo'lgan. WTH!&lt;/p&gt;

&lt;p&gt;Shu joyida &lt;em&gt;concurrency&lt;/em&gt; esga tushadi va bugni reproduce qilishga urinib ko'rasiz(pastdagi script). Ya'ni faraz qilaylik, &lt;code&gt;checkEmailExist&lt;/code&gt; funksiyasi ishlashi uchun biror N vaqt oladi va shu vaqt oralig'idagi  boshqa /register endpointga kelgan requestlar ham execute bo'ladi. Concurrency! Va qarabsizki sizda duplikatlar bor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&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;register&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:3000/register&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="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;johndoe@gmail.com&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="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &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="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&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="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="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&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;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})();&lt;/span&gt; &lt;span class="c1"&gt;// Surprise! We have 5 johndoe@gmail.com's in db&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Qanday yechim qilamiz? &lt;strong&gt;Transactions&lt;/strong&gt;! Bizga &lt;em&gt;wrapper&lt;/em&gt; funksiya kerak bo'ladi:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;$transaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// start db transaction&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;dbClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;BEGIN&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;dbClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SET TRANSACTION ISOLATION LEVEL SERIALIZABLE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// execute main function&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;f&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// commit db transaction&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;dbClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;COMMIT&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &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="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;dbClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ROLLBACK&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;checkEmailExist&lt;/code&gt; va &lt;code&gt;registerUser&lt;/code&gt; funksiyalari o'zgarmaydi, rout handlerni azgina o'zgartiramiz:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/register&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&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="c1"&gt;// get email from request body&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;$transaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &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="c1"&gt;// check if email is not taken&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;emailExist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;checkEmailExist&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;emailExist&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Email already exist&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="c1"&gt;// register new user&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;registerUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;return&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;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;User registered successfully!&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="k"&gt;catch &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="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="nf"&gt;error&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="k"&gt;return&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;json&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="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Va qarabsizki muammo hal!&lt;/p&gt;

&lt;p&gt;Qanday test qilaman? &lt;code&gt;checkEmailExist&lt;/code&gt; funksiyani sekin ishlashini &lt;em&gt;simulate&lt;/em&gt; qilamiz, masalan quyidagini qo'shib qo'yamiz:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// simulate delay&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/zayniddindev/transaction-against-concurrency" rel="noopener noreferrer"&gt;Loyiha kodlari&lt;/a&gt; | &lt;a href="https://t.me/scriptjs" rel="noopener noreferrer"&gt;Telegram kanal&lt;/a&gt;&lt;/p&gt;

</description>
      <category>concurrency</category>
      <category>transactions</category>
      <category>postgres</category>
    </item>
    <item>
      <title>"12 faktorli" dastur</title>
      <dc:creator>Zayniddin Atabaev</dc:creator>
      <pubDate>Fri, 27 Oct 2023 14:23:16 +0000</pubDate>
      <link>https://dev.to/zayniddindev/12-faktorli-dastur-1hi1</link>
      <guid>https://dev.to/zayniddindev/12-faktorli-dastur-1hi1</guid>
      <description>&lt;p&gt;Ushbu maqolada dasturiy ta'minotni muvofaqiyatli ishlab chiqish uchun ishlatiladigan metodologiyalardan biri bilan tanishamiz.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Diskleymer&lt;/em&gt;: This is the Uzbek translation of &lt;a href="https://12factor.net" rel="noopener noreferrer"&gt;https://12factor.net&lt;/a&gt;. Tarjimasi chiqmagan inglizcha so'zlar oxiriga "*" belgisi qo'yilgan&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;"12 faktor"&lt;/strong&gt; - bu dasturiy ta'monot ishlab chiqish metodologiyasi bo'lib, u bizga quyidagi qulayliklarni beradi:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Dasturni ishga tushirish uchun deklarativ ko'rsatmalar&lt;/strong&gt; - bu loyihaga yangi qo'shiluvchilar uchun jarayonni tez va oson qiladi;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dasturni operatsion tizimi bilan kam aloqadorligi&lt;/strong&gt; - bu dasturni istalgan muhitda ishlashini ta'minlaydi&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bulutli platformalarda joylashtirish uchun mos&lt;/strong&gt; - bu serverlar va tizim adminstratorlariga bo'lgan ehtiyojni bartaraf etadi;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;dev&lt;/code&gt; va &lt;code&gt;prod&lt;/code&gt; orasidagi farqni kamaytirish&lt;/strong&gt; - bu yangi fichalarni tezkorlik bilan qo'shishga imkon beradi;&lt;/li&gt;
&lt;li&gt;Kam harakat va harajat bilan dasturni kengaytirishga yordam beradi.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;SaaS (software-as-a-service), ya'ni xizmat ko'rinishidagi dasturiy ta'minot ishlab chiqaruvchi injiner yoki shunaqa dasturlarni deploy* qiluvchi devops dasturchi ushbu metodologiyani bilishi maqsadga muvofiq.&lt;/p&gt;

&lt;p&gt;12 faktor quyidagilardan iborat:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Kod bazasi&lt;/li&gt;
&lt;li&gt;Dependency'lar*&lt;/li&gt;
&lt;li&gt;Konfiguratsiya&lt;/li&gt;
&lt;li&gt;Yordamchi xizmatlar&lt;/li&gt;
&lt;li&gt;Build, release, run*&lt;/li&gt;
&lt;li&gt;Protses&lt;/li&gt;
&lt;li&gt;Port orqali bog'lash&lt;/li&gt;
&lt;li&gt;Bir vaqtda ishga tushirish (concurrency)&lt;/li&gt;
&lt;li&gt;Ishga tushirish/tugatish&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dev&lt;/code&gt; va &lt;code&gt;prod&lt;/code&gt; yaqinligi&lt;/li&gt;
&lt;li&gt;Loglar&lt;/li&gt;
&lt;li&gt;Admin protseslar&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  1. Kodbaza
&lt;/h2&gt;

&lt;p&gt;"12 faktorli" dastur albatta versiya nazorati orqali ishlab chiqiladi. Bunda kodlarni &lt;code&gt;repo&lt;/code&gt;da saqlaymiz. Repo - bu kodlarimizni vaqt davomida o'zgarishini yozib boruvchi ma'mumotlar bazasi. Misol uchun &lt;a href="https://git-scm.com" rel="noopener noreferrer"&gt;Git&lt;/a&gt;. Kodbaza va dastur orasidagi bog'liqliklarni quyidagicha ko'rish mumkin:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Agar kodbaza ko'p bo'lsa, unda biz dastur emas &lt;strong&gt;distributed system&lt;/strong&gt; qilayapmiz. Undagi har bir element alohida dastur va ularni har birini "12 faktor" asosida ishlab chiqamiz;&lt;/li&gt;
&lt;li&gt;Agar ko'plab dasturlar bir xil kodbazadan foydalanayotgan bo'lsa bu "12 faktorni" buzilishiga olib keladi. Bunday holatda kodlarni kutubxona ko'rinishida &lt;strong&gt;dependency manager&lt;/strong&gt;* orqali ishlatish kerak bo'ladi. Misol uchun &lt;a href="https://npmjs.com" rel="noopener noreferrer"&gt;npm&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Bitta dasturda bitta kodbaza bo'ladi, lekin uni bemalol hohlagancha deploy* qilsa bo'ladi. &lt;strong&gt;Deploy&lt;/strong&gt; - bu dasturni biror mashinada ishga tushirish hisoblanadi. Masalan, React.js'da qilingan vebsaytni &lt;a href="https://vercel.com" rel="noopener noreferrer"&gt;Vercel&lt;/a&gt;'da deploy qilish mumkin. Bundan tashqari turli mashinalarda dasturning turli versiyalari deploy qilinishi mumkin.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Dependency'lar
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Dependency&lt;/strong&gt;lar - bu dasturdagi bir-biriga bog'liq komponentlar majmui. Bu komponentlarni bevosita e'lon qilib qo'yish va izolyatsiya qilish zarur. Ko'p holatlarda dependency'larni e'lon qilish uchun har til/texnologiyaning o'zini package* sistemasi bo'ladi. Misol uchun &lt;strong&gt;Node.js&lt;/strong&gt; da &lt;strong&gt;npm&lt;/strong&gt;. Bunda &lt;code&gt;package.json&lt;/code&gt; faylda barcha dependency'lar ro'yhati kiritiladi. Bu bizga loyihani ishga tushirish uchun kerakli dependency'larni osonlik bilan o'rnatish imkonini beradi.&lt;/p&gt;

&lt;p&gt;Bundan tashqari dasturimizning dependency'lari faqat dasturning o'zidan boshqarilishi zarur. Masalan, sizning komputeringizda &lt;code&gt;curl&lt;/code&gt; o'rnatilgan va siz dasturda uni ishlatdingiz, lekin uni deklaratsiya qilmadingiz. Endi biror hamkasbingiz dasturni ishlatishda muammoga duch keldi, chunki unda &lt;code&gt;curl&lt;/code&gt; yo'q. Yana ham muhimi, har bir dependency deklaratsiyasi o'zi bilan birga versiyasini ham bildirishi kerak. Chunki masalan &lt;code&gt;npm i express&lt;/code&gt; bizga hozir &lt;code&gt;4.18.2&lt;/code&gt; versiyani beradi va dastur shu versiya bilan ishlaydi. Lekin biror vaqtdan keyin bu buyruq boshqa versiyani olib kelishi mumkin va bu dastur notog'ri ishlashiga sabab bo'ladi.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Konfiguratsiya
&lt;/h2&gt;

&lt;p&gt;Dastur konfigurtasiyasi (qisqa qilib konfig) turli xil deploy'larda turlicha bo'lishi mumkin, masalan &lt;code&gt;staging&lt;/code&gt;, &lt;code&gt;production&lt;/code&gt;, &lt;code&gt;dev&lt;/code&gt;. Konfig o'z ichiga quyidagilarni oladi:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ma'lumotlar bazasi, Redis yoki boshqa shunga o'xshash yordamchi xizmatlar uchun maxfiy kalitlar;&lt;/li&gt;
&lt;li&gt;Tashqi xizmatlar uchun maxfiy kalitlar, misol uchun Amazon S3 yoki Telegram Bot tokeni;&lt;/li&gt;
&lt;li&gt;Dasturni deploy qilish uchun turli argumentlar, misol uchun host va port.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Ba'zi dasturlarda bunaqa ma'lumotlar kodni ichida bo'ladi (&lt;em&gt;hardcode&lt;/em&gt;), bu esa "12 faktorni" qo'pol buzish hisoblanadi! Bunday ma'lumotlar &lt;strong&gt;environment&lt;/strong&gt; &lt;em&gt;(dastur ishga tushuvchi muhit)&lt;/em&gt; da saqlanishi zarur. Yoki bo'lmasa alohida konfig faylda saqlash kerak, misol uchun &lt;code&gt;.env&lt;/code&gt; yoku &lt;code&gt;config.yml&lt;/code&gt;. Bu fayllar Git'ga yuborilmaydi, ya'ni har bir deploy uchun alohida yoziladi. Muhimi kodga aralashmaydi.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Yordamchi xizmatlar
&lt;/h2&gt;

&lt;p&gt;Yordamchi xizmat - bu dastur o'z faoliyati davomida internet orqali bog'lanib, biror amaliyotni bajaruvchi yoki ma'lumot oluvchi tashqi resurs hisoblanadi. Misol qilib ma'lumotlar bazasi (MySQL, MongoDB), &lt;em&gt;message/queue&lt;/em&gt;* tizimlar (RabbitMQ), SMTP xizmatlar (mailing* uchun) yoki kesh tizimlari (Redis, Memcached) kabilarni ko'rsatish mumkin.&lt;/p&gt;

&lt;p&gt;Bu xizmatlarni odatda dasturni deploy qilgan devops mutaxasislani o'zlari sozlashadi. Lokal deploy qilishdan tashqari 3-tomon servislaridan ham foydalaniladi, masalan SMTP yoki xatira uchun &lt;em&gt;API&lt;/em&gt;*lar.&lt;/p&gt;

&lt;p&gt;"12 faktor"li dasturlar lokal va 3-tomon xizmatlarini birdek ishlata olishi kerak, ya'ni masalan databaza lokal deploy qilingan bo'lsa ham, 3-tomon servisi orqali olingan bo'lsa ham birdek ishlay olishi kerak. Bunda o'sha resursni konfiglarida dastur bog'lanishi uchun URL yoki shunga o'shash parametrlar bo'ladi.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Build, release, run
&lt;/h2&gt;

&lt;p&gt;Kodimiz deploy qilish uchun 3 ta bosqichdan o'tadi:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Build&lt;/strong&gt;, bunda kod ishlashi uchun barcha &lt;em&gt;dependency&lt;/em&gt;'lar o'rnatiladi va ishga tushirsa bo'ladigan formatda keltiriladi (&lt;em&gt;executable&lt;/em&gt; yoki script);&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Release&lt;/strong&gt;, bunda &lt;code&gt;build&lt;/code&gt;dagi dastur olinadi va konfiglar bilan ta'minlanadi. Natijada dasturimiz ishga tushirishga tayyor bo'ladi.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run&lt;/strong&gt; yani ishlatish, bunda dastur kerakli muhitda ishga tushiriladi.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;"12 faktorli" dasturlarda bu 3 ta bosqich albatta alohida ajratilishi kerak. Ya'ni masalan &lt;em&gt;runtime&lt;/em&gt; da kodga o'zgartirish kiritib bo'lmasligi kerak.&lt;br&gt;
Bundan tashqari har bir release uchun noyob &lt;em&gt;id&lt;/em&gt; yoki &lt;em&gt;teg&lt;/em&gt; qo'yish kelgusida rollback* qilish imkonini beradi. Rollback - bu biror xatolik tufayli dasturni avvalgi versiyasiga qaytarish hisoblanadi. Masalan, dasturni Docker image* qilib build qilish mumkin va unga teg beramiz. &lt;a href="https://hub.docker.com" rel="noopener noreferrer"&gt;DockerHub&lt;/a&gt;'dagi image'larni teglari bilan ko'rgan bo'lishingiz kerak. &lt;a href="https://caprover.com" rel="noopener noreferrer"&gt;Caprover&lt;/a&gt; orqali Docker image'larni deploy qilish mumkin va unda rollback funksiyasi ham bor. &lt;/p&gt;

&lt;h2&gt;
  
  
  6. Protses
&lt;/h2&gt;

&lt;p&gt;Dastur bitta muhitda bir yoki bir nechta protses bo'lib ishlaydi. Oddiy holatda bu bitta executable* fayl yoki skript bo'ladi.&lt;/p&gt;

&lt;p&gt;"12 faktorli" dasturda state* bo'lmaydi, ya'ni hech qanday data saqlamaydi. Agar data saqlash kerak bo'lsa yordamchi xizmatlardan foydalanadi, masalan databaza.&lt;br&gt;
Vaqtinchalik saqlash uchun ma'lumotlarni faylsistemada saqlab turish mumkin. Masalan bitta &lt;code&gt;.jpg&lt;/code&gt; faylni internetdan yuklab olib, uni ustida amal bajarib, &lt;code&gt;S3&lt;/code&gt;'ga yuklab, foydalanuvchiga &lt;code&gt;URL&lt;/code&gt;ni yuborib, keyin faylni o'chirib yuborish. Bunda fayl kelajakda saqlanib qolishi uchun zarurat yo'q.&lt;/p&gt;

&lt;p&gt;Ba'zida web serverda "user session" yoki Telegram Bot'dagi session*ni saqlab qo'yamiz. Bu in-memory saqlash bo'lib, "12 faktor"ni buzish hisoblanadi.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Port orqali bog'lash
&lt;/h2&gt;

&lt;p&gt;Web dasturlar ko'p holatlarda vebserver ichida alohida "konteyner" bo'lib ishlaydi. Bu dasturni portable*, ya'ni qulay qiladi. Bunda dastur tashqi serverning biror parametriga bog'liq bo'lmasligi kerak. Aksincha uni ixtiyoriy port orqali ishlatishning iloji bo'lishi kerak. Masalan, siz Node.js'da server qildingiz va "srazi" uni 3 ta instance*da ishlatmoqchisiz. Ularni 3001, 3002 va 3003 portlarda ishga tushirasiz va serverdagi 80 portga kelgan so'rovlarni ushbu instance'larga bo'lib berasiz. Buni hozirgi kundagi odatiy implementatsiya sifatida ko'rishimiz mumkin.&lt;/p&gt;

&lt;p&gt;Bundan tashqari yordamchi xizmatlarni ham port orqali bog'lash mumkin. Bunda URL orqali asosiy dastur yordamchi dasturga so'rov yuboradi.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Concurrency
&lt;/h2&gt;

&lt;p&gt;"12 faktorli" dasturlarni concurrency* orqali scale-out* qilish mumkin va bu horizontal scaling. Concurrency deganda bir yoki bir nercha vazifani bir vaqtda bajarilishi tushuniladi. "Scaling" esa dasturni kengaytirish, uni katta miqdordagi bosimni ko'tara olishini ta'minlashni bildiradi. &lt;/p&gt;

&lt;p&gt;Protseslar asosiy o'yin qatnashchilari bo'lib, uning turlariga qarab o'z dasturimizni loyihalashtiramiz. Turlari deganda thread* (potok), protses yoki worker kabilarni tushunishimiz mumkin. Misol uchun, HTTP so'rovni protses bilan handle* qilsak, ko'p vaqt oladigan vazifalarni worker bilan amalga oshiramiz.&lt;br&gt;
Bundan tashqari queue* tizimini implementatsiya qilib ham dasturni responsiveness*ini oshirish mumkin. Queue - bu vazifalarni navbatga qo'shib qo'yib, FIFO tartibida bajarishdir.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Disposability
&lt;/h2&gt;

&lt;p&gt;Dastur tez ishga tushishi va zararsiz to'xtashi kerak. Bu bizga tezroq deploy qilish va konfiglarni o'zgartirish imkonini beradi. Protses &lt;code&gt;SIGTERM&lt;/code&gt; (signal terminate) olganda &lt;code&gt;graceful shutdown&lt;/code&gt; qilishi kerak. Graceful shutdown - bu dastur vazifa olishni to'xtatib, bajarayotgan vazifalarni tugatib, tashqi resurslar bilan aloqani uzib talofatlarsiz to'xtashidir. Dastur qachon va qanday signal qabul qiladi? Signalni komputerdagi servis menejer beradi, misol uchun systemd yoki deylik Docker.&lt;/p&gt;

&lt;p&gt;Worker protses uchun graceful shutdown qilish birmuncha qiyin. Bunda worker uchun topshiriq qaytadan queue'ga qaytarilishi kerak va keyin worker(lar) vazifasini to'xtatishi mumkin bo'ladi. Bu huddi databazadagi transaksiyaga o'xshaydi, agar muammo bo'lsa terminate qilish kerak. Bundan tashqari dasturning faqat &lt;code&gt;master&lt;/code&gt; protsesi signalni qabul qiladi, bu degani boshqa slave fork*larni graceful shutdown qilish kerak bo'ladi. Ko'proq o'qish uchun &lt;a href="http://lwn.net/Articles/191059" rel="noopener noreferrer"&gt;"Crash-only design"&lt;/a&gt;ni o'qishingiz mumkin.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. &lt;code&gt;dev&lt;/code&gt; va &lt;code&gt;prod&lt;/code&gt; yaqinligi
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;dev&lt;/code&gt; va &lt;code&gt;prod&lt;/code&gt; orasidagi farq biz uchun minusga ishlaydi. Yomon alomatlar:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;dev&lt;/code&gt;dan &lt;code&gt;prod&lt;/code&gt;ga chiqish uchun dasturchi ko'p vaqt sarflaydi;&lt;/li&gt;
&lt;li&gt;Injiner kod yozadi, devops uni deploy qiladi;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dev&lt;/code&gt; va &lt;code&gt;prod&lt;/code&gt;dagi ishlatilgan texnologiyalar farq qiladi.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Agar bu alomatlar sizning ish joyingizda bo'lsa, ishlar chatoq. Chunki bular unumdorlikni tushirib yuboradi va dasturni ishlab chiqish jarayonini sekinlashtitadi.&lt;/p&gt;

&lt;p&gt;Biz daploy muhitidagi yordamchi resurslar uchun abstraktsiyalar yozamiz, lekin bu resurslar farq qilgani uchun bizga ko'zlanganidek yordam bermaydi. Shunda ham abstraktsiyalar muhim, chunki ular boshqa yordamchi xizmatga o'tganimizda ko'plab bosh og'riqlarimizni kamaytiradi.&lt;/p&gt;

&lt;h2&gt;
  
  
  11. Loglar
&lt;/h2&gt;

&lt;p&gt;Loglar bizga dasturni harakterini ko'rsatib beradi. Loglarga qarab dastur o'tmishda va hozir qanday ishlayotganini ko'ra olamiz. Loglar vebserverlarda asosan faylga yoziladi, lekin bu shunchaki logni saqlash formati xolos.&lt;/p&gt;

&lt;p&gt;Loglar shunchaki &lt;code&gt;.logfile&lt;/code&gt; deb nomlanuvchi fayl emas, ular aslida ma'lumotlar oqimi (stream*). Stream dasturdan real vaqt davomida kelib turadi va biz uni monitor qila olamiz. Dastur loglarni saqlab qo'yish haqida qayg'urmasligi kerak, shunchaki ularni stream qilib &lt;code&gt;stdout&lt;/code&gt;ga berib tursa bo'lgani. Local deployda dasturchi loglarni terminal orqali real vaqtda ko'rib turadi, prod'da esa &lt;code&gt;stdout&lt;/code&gt;dagi loglar tashqaridan olib turiladi va uzoq muddatga saqlab qo'yiladi. Bu yerdan esa kelajakda analiz, hodisalarni vaqt bo'yicha o'zgarishi va shunga o'xshash ma'lumotlar hosil qilinadi.&lt;/p&gt;

&lt;h2&gt;
  
  
  12. Admin protseslar
&lt;/h2&gt;

&lt;p&gt;Ba'zida asosiy dastur ishlab turgan protsesdan boshqa, bir martalik vazifani bajarish uchun protses ochishga to'g'ri keladi. Masalan, databazaga migratsiyalarni qo'llash, REPL ishga tushirish yoki biror skript faylni yurgizish. Bunda bir martalik admin protseslar asosiy uzoq muddat ishlaydigan protsesniki bilan bir xil muhitda ishlashi kerak. Bundan tashqari, admin protses kod bilan birga bo'lishi kerak va yangilanishi, chunki sinxronlik bilan muammo chiqishi mumkin.&lt;br&gt;
"12 faktor" metogologiyasi har doim REPL uchun supporti bor tillar/texnologiyalarni avzal ko'radi, chunki ularda admin protseslarni ishga tushirish oson kechadi.&lt;/p&gt;

&lt;h2&gt;
  
  
  Xulosa
&lt;/h2&gt;

&lt;p&gt;Umuman olganda, "12 faktor" dasturiy ta'minotni ishlab chiqish, deploy qilish, monitoring va kengaytirish uchun muhim ko'rsatmalar to'plami bo'lib, muvofaqiyatli dasturlar uchun dasturulamal sifatida e'tirof qilsa bo'ladi.&lt;/p&gt;

&lt;p&gt;Asosiy manba: &lt;a href="https://12factor.net" rel="noopener noreferrer"&gt;https://12factor.net&lt;/a&gt;&lt;/p&gt;

</description>
      <category>12factor</category>
      <category>software</category>
      <category>saas</category>
      <category>methodology</category>
    </item>
  </channel>
</rss>
