Backend Ready | IT
8.32K subscribers
1.25K photos
93 videos
6 files
1K links
По всем вопросам: @AdilNow
Download Telegram
👩‍💻 Хватит учить только синтаксис, начинай делать реальные проекты!

Python Ready — авторский канал, где Python перестаёт быть только теорией и становится рабочим инструментом. Мини-проекты, боты, советы, разборы задач, гайды и шпаргалки для каждого программиста.

🔥 Советую подписаться: @python_ready
Please open Telegram to view this post
VIEW IN TELEGRAM
2
Хочешь посмотреть, как Java эволюционировала, фича за фичей?

brunoborges сделал офигенный сайт, где изменения языка Java показаны рядом, в формате side-by-side. Идеально для студентов и для тех, кто модернизирует легаси-приложения.

Зацени:
https://javaevolved.github.io

Backend Ready | #урок
Please open Telegram to view this post
VIEW IN TELEGRAM
3
Один умный человек, написал эссе про алгоритм BM25, который лежит в основе Elasticsearch, Apache Solr и Apache Lucene.

Зачем? Просто потому что ему было нечем заняться, он нырнул в кроличью нору информационного поиска: пытался понять, почему и где TF-IDF в итоге упирается в свои пределы, как на самом деле устроен BM25 под капотом, и почему системы вроде Elasticsearch, Solr и Lucene сделали его своей дефолтной функцией ранжирования.

В эссе узнаете, почему BM25 так хорошо работает, как каждая часть формулы влияет на ранжирование, и какое место он занимает в современном retrieval-стеке.

Этот текст должен дать тебе нормальную ментальную модель, чтобы понимать BM25 и также IDF из популярного TF-IDF. Зацени.

Backend Ready | #урок
Please open Telegram to view this post
VIEW IN TELEGRAM
Fastify — когда Express становится слишком медленным 🏎️

Express — это классика, но он был создан в те времена, когда Node.js только зарождался. Fastify — это современный фреймворк, созданный с фокусом на максимальную производительность и минимальные накладные расходы. Он буквально «летает» за счет оптимизации JSON-схем и встроенной системы плагинов.

Шаг 1 — создаем первый роут:
Синтаксис похож на Express, но сразу предлагает использовать async/await.

npm install fastify


const fastify = require('fastify')({ logger: true });

fastify.get('/ping', async (request, reply) => {
return { status: 'pong' }; // JSON парсится автоматически
});

fastify.listen({ port: 3000 }, (err) => {
if (err) throw err;
console.log('Fastify запущен!');
});


Зачем это нужно? 🚀

Сверхскорость: Fastify считается одним из самых быстрых фреймворков для Node.js. Он тратит меньше ресурсов процессора на каждый запрос.
Валидация «из коробки»: Fastify использует JSON Schema для проверки входных данных. Это не только делает API безопасным, но и ускоряет сериализацию ответов в 2 раза. 🛡️
Экосистема плагинов: Вместо хаотичного мидлвара, как в Express, здесь строгая и понятная иерархия плагинов.



Крутые фишки: 📝

Hooks: Ты можешь вклиниться в любой момент жизненного цикла запроса (onRequest, preHandler и т.д.).
Типизация: Отличная поддержка TypeScript прямо из коробки. 🧩
Декораторы: Позволяют легко добавлять новые методы в объекты request и reply без костылей.
Логирование: Встроенный сверхбыстрый логгер Pino (о котором мы писали раньше).

Пример с валидацией:
const schema = {
params: {
type: 'object',
properties: { id: { type: 'number' } }
}
};

fastify.get('/user/:id', { schema }, async (req, res) => {
return { userId: req.params.id };
});


> Важный нюанс: Если ты начинаешь новый проект в 2026 году — выбирай Fastify. Express всё еще жив, но Fastify предлагает более современную архитектуру и лучшую производительность для микросервисов.

---

### **Пакет cron — планируем задачи по расписанию **

В любом серьезном бэкенде есть задачи, которые должны выполняться сами по себе: рассылка писем по утрам, чистка старых логов или бэкап базы данных в полночь. Пакет cron позволяет настроить выполнение функций по расписанию с помощью стандартного синтаксиса crontab.

Шаг 1 — настраиваем «будильник»:

npm install cron


const { CronJob } = require('cron');

const job = new CronJob(
'0 0 * * *', // Каждый день в полночь
function() {
console.log('Время делать бэкап базы данных! 💾');
},
null, // Коллбэк при остановке
true, // Запустить сразу
'Europe/Moscow' // Часовой пояс
);


Зачем это нужно? 🚀

Автоматизация: Тебе не нужно помнить о рутинных задачах — сервер сделает всё сам.
Гибкость: Можно настроить запуск раз в секунду, раз в месяц или только по рабочим дням в 9 утра. 📅
Надежность: Задачи работают в фоне и не мешают пользователям пользоваться сайтом.



Как читать синтаксис (5 звезд): 📝

* * * * * * (секунды, минуты, часы, день месяца, месяц, день недели).
0 */2 * * * — каждые два часа.
0 9 * * 1-5 — в 9:00 с понедельника по пятницу. 👔
30 18 * * * — каждый день в 18:30.

Крутые фишки: 📝

Поддержка часовых поясов: Твой сервер может стоять в США, но выполнять задачи по времени твоего города.
Управление: Задачи можно динамически создавать, останавливать (job.stop()) и запускать заново в коде. ⚙️
async/await: Внутри задачи можно спокойно использовать асинхронный код для запросов к БД или API.

> Важный нюанс: Если у тебя один сервер — cron идеален. Если же у тебя кластер из 10 серверов, обычный cron запустится на каждом из них одновременно. В таких случаях лучше использовать распределенные очереди задач, например BullMQ или Agenda.

Backend Ready | #урок
Please open Telegram to view this post
VIEW IN TELEGRAM
BullMQ — мощные очереди задач для тех, кто вырос из обычного Cron 🐂

Когда твой проект растет, простых задач «по расписанию» становится мало. Что, если нужно отправить 10 000 писем, но API почтового сервиса тормозит? Или нужно обработать тяжелое видео, не заставляя пользователя ждать ответа? Здесь на сцену выходит BullMQ — стандарт для очередей задач в Node.js, работающий на базе Redis.

Шаг 1 — создаем очередь и воркер:
Одна часть приложения (продюсер) кидает задачу в очередь, а другая (воркер) — выполняет её, когда освободится.

npm install bullmq ioredis


const { Queue, Worker } = require('bullmq');

// 1. Создаем очередь
const videoQueue = new Queue('video-processing');

// 2. Добавляем задачу (например, из контроллера)
await videoQueue.add('compress', { videoId: 42, format: 'mp4' });

// 3. Воркер в отдельном процессе подхватывает задачу
const worker = new Worker('video-processing', async job => {
console.log(`Обработка видео ${job.data.videoId}...`);
// Тут логика сжатия
return 'Done';
});


Зачем это нужно? 🚀

Фоновая обработка: Пользователь нажимает «Загрузить», и мы сразу говорим ему «Ок, скоро всё будет», а само видео обрабатывается в фоне. 🎬
Устойчивость к сбоям: Если воркер упадет или сервер перезагрузится, задача не пропадет. Она останется в Redis и будет выполнена позже.
Rate Limiting: Можно ограничить выполнение задач (например, не больше 5 запросов в секунду к стороннему API), чтобы не получить бан. 🛡️
Повторы (Retries): Если задача упала с ошибкой (например, сеть мигнула), BullMQ может автоматически попробовать еще раз через 5, 10 или 60 минут.



Крутые фишки: 📝

Priorities: Можно сделать так, чтобы задачи от Premium-пользователей всегда шли в начало очереди.
Delayed Jobs: Выполни задачу не сейчас, а ровно через 2 часа.
Parent/Child Jobs: Создавай сложные цепочки — выполни задачу А, и только если она успешна, запускай задачи Б и В.
Панель управления: Есть готовые админки (например, BullBoard), где можно в реальном времени смотреть, сколько задач в очереди, сколько упало и почему. 📊

Почему Redis? 🤔
Redis работает в оперативной памяти, поэтому обмен задачами происходит мгновенно. Это намного быстрее, чем хранить очередь в обычной реляционной базе вроде PostgreSQL.

> Важный нюанс: BullMQ — это профессиональный инструмент. Если тебе просто нужно раз в день чистить логи, обычного node-cron хватит. Но если от выполнения задачи зависят деньги или лояльность юзера — используй очереди.

Backend Ready | #урок
Please open Telegram to view this post
VIEW IN TELEGRAM
🔌 Модуль dns — работаем с доменными именами напрямую

Когда мы делаем HTTP-запрос, Node.js сам разрешает домены, но иногда приложению нужно делать это вручную: проверить существование домена, получить его IP или узнать MX-записи почтового сервера.

dns — резолвинг и проверка сети**

dns.resolve()
dns.lookup()
dns.reverse()
dns.getServers()

dns.resolve() — отправляет реальный запрос к DNS-серверам в сети. Позволяет узнать IP-адреса, привязанные к домену.

const dns = require('dns');

dns.resolve('google.com', (err, addresses) => {
console.log('IP адреса:', addresses);
});
// Результат: IP адреса: ['142.250.185.142', ...]




dns.lookup() — использует настройки операционной системы (например, файл hosts). Это быстрее, но не всегда дает актуальные данные из интернета.

dns.lookup('localhost', (err, address) => {
console.log('Адрес:', address);
});
// Результат: Адрес: 127.0.0.1


dns.reverse() — выполняет обратное преобразование: вы передаете IP-адрес, а модуль пытается найти имя хоста, которое ему соответствует.
dns.resolveMx() — возвращает записи почтового обмена. Идеально для проверки, существует ли почтовый сервер у домена перед отправкой письма.

dns.resolveMx('github.com', (err, addresses) => {
console.log(addresses);
});


dns.getServers() — показывает список IP-адресов DNS-серверов, которые в данный момент использует твоя система для резолвинга.

Backend Ready | #урок
Please open Telegram to view this post
VIEW IN TELEGRAM
🧩 Модуль url — безопасный парсинг и сборка ссылок**

Работа со строками через split или регулярные выражения — прямой путь к ошибкам и уязвимостям. В Node.js есть встроенный класс URL, который соответствует международным стандартам и автоматически обрабатывает спецсимволы.

url — разбор и валидация адресов

new URL()
url.searchParams
url.pathname
url.origin
url.format()

new URL() — создает объект, который разбивает строку на части: протокол, хост, порт, путь и параметры.

const myUrl = new URL('https://api.test.ru:8080/v1/user?id=10#hash');

console.log(myUrl.host); // api.test.ru:8080
console.log(myUrl.protocol); // https:
console.log(myUrl.hash); // #hash




searchParams — мощный инструмент для работы с GET-запросами. Позволяет легко добавлять, удалять или изменять параметры без ручного склеивания строк.

const link = new URL('https://shop.ru/search');
link.searchParams.append('sort', 'desc');
link.searchParams.set('page', '1');

console.log(link.href);
// https://shop.ru/search?sort=desc&page=1


pathname — возвращает только путь к ресурсу. Полезно для роутинга, чтобы отсечь домен и параметры поиска.
origin — возвращает комбинацию протокола и хоста. Идеально для настройки CORS или проверки источника запроса.

const site = new URL('https://blog.js.org/posts/123');
console.log(site.origin); // https://blog.js.org


Безопасность — если передать в конструктор URL некорректную строку, он выдаст ошибку. Это отличный способ проверить, является ли строка валидной ссылкой, прежде чем сохранять её в базу.

Backend Ready | #урок
Please open Telegram to view this post
VIEW IN TELEGRAM
2
🔐 Права доступа в Linux — разбираемся с chmod и chown!

В Linux всё есть файл, и безопасность системы строится на том, кто может эти файлы читать, изменять или запускать. Если вы хоть раз видели ошибку Permission denied, значит, пришло время разобраться, как работают права доступа и как ими управлять.

В этом посте:
— Разбираем магические цифры 777, 644 и 755.
— Учимся менять владельца файлов через chown.
— Настраиваем права на чтение, запись и запуск.
— Узнаем, как рекурсивно исправить доступ во всей папке.

---

Каждый файл в Linux имеет три группы прав: для Владельца (User), для Группы (Group) и для Всех остальных (Others). Для каждой группы можно разрешить или запретить три действия: r (read — чтение), w (write — запись) и x (execute — запуск).

Как читать цифровой код:
4 — чтение (read)
2 — запись (write)
1 — запуск (execute)
0 — нет прав

Складывая эти цифры, мы получаем нужный уровень доступа. Например, 4+2+1 = 7 (полные права), а 4+2 = 6 (чтение и запись).

Популярные комбинации:
chmod 777 — «гуляй, кто хочешь». Все могут делать всё. Худший вариант для безопасности.
chmod 644 — стандарт для файлов. Владелец пишет и читает, остальные только читают.
chmod 755 — стандарт для папок и скриптов. Все могут зайти в папку или запустить файл, но менять его может только владелец.

Иногда проблема не в правах, а в том, что файл принадлежит не тому пользователю (например, root вместо вашего юзера). Чтобы сменить «хозяина», используется команда chown. Если нужно сменить и владельца, и группу сразу, пишем через двоеточие: sudo chown user:group filename.



Часто права нужно поправить не в одном файле, а во всей папке с вложенными проектами. Для этого используйте флаг -R (recursive). Но будьте осторожны: sudo chmod -R 777 / превратит вашу систему в решето за одну секунду.

Использование правильных прав — это не просто «чтобы работало», а защита вашего сервера от взлома. Скрипты должны иметь флаг +x только если вы собираетесь их запускать, а конфиги с паролями (вроде .env) должны быть закрыты от всех, кроме владельца.

Backend Ready | #урок
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
🛰️ Модуль querystring — работаем с параметрами запросов**

Хотя класс URL умеет парсить параметры, модуль querystring остается незаменимым, когда нужно быстро превратить объект в строку для тела запроса или разобрать сырые данные, которые приходят в POST-запросе от старых HTML-форм.

querystring — парсинг и сборка запросов

parse()
stringify()
escape()
unescape()

parse() — превращает строку параметров (то, что идет после знака ?) в обычный объект JavaScript.

const qs = require('querystring');

const query = 'user=admin&role=editor&active=true';
const parsed = qs.parse(query);

console.log(parsed.user); // admin




stringify() — делает обратную операцию: берет объект и собирает из него корректную строку параметров, которую можно подставить в URL.

const params = { search: 'node js', page: 5 };
const string = qs.stringify(params);

console.log(string); // search=node%20js&page=5


escape() / unescape() — низкоуровневые методы для работы со спецсимволами. Они заменяют пробелы, кавычки и кириллицу на безопасные коды (например, %20), чтобы сервер мог их прочитать.

Отличие от URLSearchParamsquerystring работает быстрее и поддерживает кастомные разделители. Если вместо & и = тебе нужно использовать ; и :, этот модуль справится в одну строку.

const custom = qs.parse('name:tom;age:20', ';', ':');
console.log(custom.name); // tom

Backend Ready | #урок
Please open Telegram to view this post
VIEW IN TELEGRAM
1
📦 Модуль v8 — заглядываем «под капот» движка Node.js**

Node.js работает на движке V8 от Google. Встроенный модуль v8 дает прямой доступ к управлению памятью и настройкам самого движка. Это инструмент для тех, кто хочет выжать из сервера максимум и найти утечки памяти.

v8 — мониторинг и управление памятью

v8.getHeapStatistics()
v8.setFlagsFromString()
v8.serialize()
v8.deserialize()

getHeapStatistics() — возвращает детальный отчет о состоянии «кучи» (Heap). Можно узнать общий размер выделенной памяти и лимит, после которого приложение упадет с ошибкой JavaScript heap out of memory.

const v8 = require('v8');
console.log(v8.getHeapStatistics());




serialize() / deserialize() — позволяют превращать объекты JS в бинарный формат V8 и обратно. Это работает быстрее, чем JSON.stringify, и поддерживает типы данных, которые JSON не умеет (например, Map, Set или BigInt).

const buffer = v8.serialize({ map: new Map([['id', 1]]) });
const data = v8.deserialize(buffer);


setFlagsFromString() — позволяет менять настройки движка прямо во время работы кода. Например, можно принудительно включить или выключить оптимизацию определенных функций (использовать только в целях отладки!).

Heap Snapshots — через API этого модуля можно программно создавать снимки памяти, чтобы потом проанализировать их в Chrome DevTools и понять, какие объекты «едят» оперативку и не удаляются сборщиком мусора.

Backend Ready | #урок
Please open Telegram to view this post
VIEW IN TELEGRAM
🧩 Модуль path — правильная работа с путями к файлам**

Склеивать пути вручную через / или \ — плохая практика, потому что в Windows и Linux разделители разные. Модуль path делает это автоматически, учитывая особенности операционной системы, на которой запущен твой код.

path — навигация по файловой системе

path.join()
path.resolve()
path.basename()
path.extname()
path.parse()

path.join() — объединяет все переданные сегменты пути в одну строку, используя разделитель текущей ОС. Он также чистит путь от лишних точек и двойных слешей.

const path = require('path');
const fullPath = path.join('users', 'admin', 'config.json');
// Windows: users\admin\config.json
// Linux: users/admin/config.json




path.resolve() — превращает последовательность путей в абсолютный путь. Он всегда стартует от корня проекта, что гарантирует точность при поиске файлов.

console.log(path.resolve('images', 'logo.png'));
// Результат: /Users/dev/project/images/logo.png


path.basename() — возвращает только имя файла из длинного пути. Если вторым аргументом передать расширение, оно будет отрезано.
path.extname() — достает только расширение файла. Удобно для фильтрации загрузок (например, разрешать только .jpg).

const file = 'static/uploads/photo.jpg';
console.log(path.basename(file)); // photo.jpg
console.log(path.extname(file)); // .jpg


path.parse() — разбирает путь на части и возвращает объект с корнем, папкой, полным именем, расширением и именем без расширения.

console.log(path.parse('/home/user/dir/file.txt'));
/* { root: '/', dir: '/home/user/dir', base: 'file.txt',
ext: '.txt', name: 'file' } */

Backend Ready | #урок
Please open Telegram to view this post
VIEW IN TELEGRAM
🔐 Модуль crypto — безопасность и шифрование данных

Безопасность — это не только HTTPS. Модуль crypto предоставляет набор инструментов для создания хэшей, генерации случайных паролей и шифрования сообщений. Это база для аутентификации и защиты конфиденциальной информации.

crypto — шифрование и хэширование

crypto.createHash()
crypto.randomBytes()
crypto.createCipheriv()
crypto.scrypt()

crypto.createHash() — создает необратимый отпечаток данных (хэш). Обычно используется для проверки целостности файлов или сравнения паролей (через алгоритм SHA-256).

const crypto = require('crypto');

const hash = crypto.createHash('sha256')
.update('секретный_пароль')
.digest('hex');
console.log(hash);
// Результат: 5e884898da28047151d0e56...




crypto.randomBytes() — генерирует криптографически сильные случайные данные. Это гораздо безопаснее, чем Math.random(). Идеально для создания токенов восстановления пароля или «соли».

crypto.randomBytes(16, (err, buf) => {
console.log(buf.toString('hex'));
});


crypto.scrypt() — современный алгоритм для безопасного хэширования паролей. Он специально сделан медленным и ресурсозатратным, чтобы защитить от подбора паролей методом перебора (Brute-force).

Cipher и Decipher — инструменты для симметричного шифрования. Ты можешь зашифровать текст ключом, передать его по сети, а на другом конце расшифровать тем же ключом.

const cipher = crypto.createCipheriv(algorithm, key, iv);
let encrypted = cipher.update('Важные данные', 'utf8', 'hex');
encrypted += cipher.final('hex');


Hmac — (Hash-based Message Authentication Code). Позволяет убедиться, что данные не были изменены в процессе передачи, используя секретный ключ.

Backend Ready | #урок
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
⏱️ Модуль timers — управление временем и очередью событий

В Node.js работа с задержками — это не просто пауза в коде. Модуль timers управляет тем, как и когда функции попадают в Event Loop. Помимо привычных браузерных методов, здесь есть специфические инструменты для оптимизации нагрузки.

timers — планирование выполнения кода

setTimeout() / clearTimeout()
setInterval() / clearInterval()
setImmediate()
process.nextTick()

setTimeout() — запускает код через указанное количество миллисекунд. В Node.js этот метод возвращает объект, который можно использовать для отмены или управления поведением процесса.

const timer = setTimeout(() => {
console.log('Прошло 2 секунды');
}, 2000);

// Если нужно отменить:
clearTimeout(timer);




setImmediate() — «микрозадача» Node.js. Она выполняет код сразу после того, как завершится текущая фаза опроса событий (Poll фаза). Это эффективнее, чем setTimeout(fn, 0).

setImmediate(() => {
console.log('Выполнится в фазе Check');
});


process.nextTick() — самый «быстрый» таймер. Он заставляет функцию выполниться сразу после текущей операции, еще до того, как Event Loop перейдет к следующей фазе. Чрезмерное использование может «заблокировать» ввод-вывод.

unref() и ref() — уникальные методы Node.js. Если вызвать timer.unref(), активный таймер не будет удерживать процесс от завершения, если в коде больше ничего не происходит.

const interval = setInterval(() => {}, 1000);
interval.unref(); // Сервер выключится, если нет других задач


Promisified Timers — в новых версиях Node.js можно использовать таймеры с await без лишних оберток.

const { setTimeout } = require('timers/promises');
await setTimeout(1000);
console.log('Ждали одну секунду');

Backend Ready | #урок
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Исходный Код
Смоделировали задачу с двумя ++ для разработчиков!

🔥 Ситуация:
Запускаем модуль выплат для e-commerce. Использовали стандартную схему с Webhooks от платежного шлюза. Локально все летает, автотесты подтверждают идемпотентность.


📊 После релиза видим аномалию:
У 0.1% юзеров транзакции дублируются. Причем в логах шлюза - два успешных вызова с разницей в 50 мс, а в нашей базе - две записи с разными ID, но одинаковым внешним Correlation ID.


🎮 Задача:
Вам нужно определить ту самую причину в логике бэкенда или БД, которая позволила создать дубль, несмотря на проверку.

🔍
Варианты ответов в карточках!


💬 Если дается сложно: две подсказки оставили в комментариях!

📱 Исходный код — подписаться!
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM