🤔 Что в твоем понимании значит правильный код?
Это код, который не только выполняет поставленные задачи, но и соответствует ряду критериев, обеспечивающих его качество, читаемость, сопровождение и эффективность.
🚩Характеристики
🟠Читаемость
Переменные, функции, классы и другие сущности должны иметь понятные и описательные имена, которые отражают их назначение. Следование стандартам кодирования и стиля, включая правильное форматирование, отступы и использование комментариев. Использование комментариев для объяснения сложных или неочевидных частей кода, но не для очевидных вещей, которые можно понять из названий переменных и функций.
🟠Сопровождаемость
Код должен быть разбит на модули, функции или классы с чётко определёнными задачами. Это упрощает его понимание, тестирование и изменение. Избегание дублирования кода через применение принципа DRY (Don't Repeat Yourself). Код должен быть легко тестируемым. Написание автоматических тестов для проверки корректности работы помогает предотвратить ошибки.
🟠Эффективность
Код должен быть оптимизирован для выполнения задач с минимальными затратами ресурсов, таких как время выполнения и использование памяти. Использование эффективных алгоритмов и структур данных для обеспечения хорошей производительности, особенно на больших объемах данных.
🟠Надежность
Код должен корректно обрабатывать ошибки и исключительные ситуации, предотвращая неожиданные сбои. Проверка входных данных для предотвращения некорректного поведения программы.
🟠Документированность
Написание документации, описывающей основные компоненты системы, их взаимодействие и использование. Хорошо документированный код облегчает его понимание для других разработчиков.
🟠Применение принципов и паттернов проектирования
Применение принципов SOLID для создания устойчивого, гибкого и масштабируемого кода. Использование проверенных решений для общих задач проектирования.
🚩Примеры
Читаемость и сопровождаемость
Тестируемость
⚙ Backend Ready | #урок
Это код, который не только выполняет поставленные задачи, но и соответствует ряду критериев, обеспечивающих его качество, читаемость, сопровождение и эффективность.
🚩Характеристики
🟠Читаемость
Переменные, функции, классы и другие сущности должны иметь понятные и описательные имена, которые отражают их назначение. Следование стандартам кодирования и стиля, включая правильное форматирование, отступы и использование комментариев. Использование комментариев для объяснения сложных или неочевидных частей кода, но не для очевидных вещей, которые можно понять из названий переменных и функций.
🟠Сопровождаемость
Код должен быть разбит на модули, функции или классы с чётко определёнными задачами. Это упрощает его понимание, тестирование и изменение. Избегание дублирования кода через применение принципа DRY (Don't Repeat Yourself). Код должен быть легко тестируемым. Написание автоматических тестов для проверки корректности работы помогает предотвратить ошибки.
🟠Эффективность
Код должен быть оптимизирован для выполнения задач с минимальными затратами ресурсов, таких как время выполнения и использование памяти. Использование эффективных алгоритмов и структур данных для обеспечения хорошей производительности, особенно на больших объемах данных.
🟠Надежность
Код должен корректно обрабатывать ошибки и исключительные ситуации, предотвращая неожиданные сбои. Проверка входных данных для предотвращения некорректного поведения программы.
🟠Документированность
Написание документации, описывающей основные компоненты системы, их взаимодействие и использование. Хорошо документированный код облегчает его понимание для других разработчиков.
🟠Применение принципов и паттернов проектирования
Применение принципов SOLID для создания устойчивого, гибкого и масштабируемого кода. Использование проверенных решений для общих задач проектирования.
🚩Примеры
Читаемость и сопровождаемость
def calculate_area(radius):
"""Calculate the area of a circle given its radius."""
import math
if radius < 0:
raise ValueError("Radius cannot be negative")
return math.pi * radius ** 2
Тестируемость
def add(a, b):
"""Add two numbers and return the result."""
return a + b
# Unit test for the add function
def test_add():
assert add(2, 3) == 5
assert add(-1, 1) == 0
assert add(0, 0) == 0
test_add()
Please open Telegram to view this post
VIEW IN TELEGRAM
Видел интересное видео от CTO Zerodha про то, как они масштабировали Postgres с 7+ млн таблиц.
Технология просто выносит мозг, а если копнуть глубже, становится еще веселее:
- синхронщина? не масштабируется, значит выкидываем.
- все в async. тяжелую генерацию отчетов ставим в очередь.
- независимый middleware, которому все равно на базу и на приложение.
- собрали “DungBeetle” на Go: обобщенные, независимые от СУБД HTTP API, чтобы тянуть отчеты из любой базы.
- результаты сливаем в отдельную Results DB, а приложение читает уже оттуда.
Вот так выглядит настоящий масштаб.
Смотреть видео
⚙ Backend Ready | #урок
Технология просто выносит мозг, а если копнуть глубже, становится еще веселее:
- синхронщина? не масштабируется, значит выкидываем.
- все в async. тяжелую генерацию отчетов ставим в очередь.
- независимый middleware, которому все равно на базу и на приложение.
- собрали “DungBeetle” на Go: обобщенные, независимые от СУБД HTTP API, чтобы тянуть отчеты из любой базы.
- результаты сливаем в отдельную Results DB, а приложение читает уже оттуда.
Вот так выглядит настоящий масштаб.
Смотреть видео
Please open Telegram to view this post
VIEW IN TELEGRAM
Python 3.14 стал до 30 % быстрее благодаря новому интерпретатору с tail call — ускорение без изменений в коде, просто обновите версию.
Команда CPython продолжает ускорять Python. Так, релиз 3.14 уже включает одну из самых заметных внутренних реформ — новый байт-кодовый интерпретатор.
Читать статью
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4❤1👍1
🤔 Как можно заблокировать конкретные поля в Postgres?
В PostgreSQL можно использовать различные методы для блокировки конкретных полей или строк таблицы, чтобы предотвратить их изменение или обеспечить управление конкурентным доступом к данным. Наиболее распространенные способы включают использование транзакционных блокировок и политик доступа.
🟠Использование блокировок уровня строки (Row-Level Locks)
PostgreSQL поддерживает блокировки уровня строки с помощью команд
🟠Использование политик доступа (Row-Level Security Policies)
Политики безопасности на уровне строк позволяют определить, кто и при каких условиях может видеть или изменять данные в таблице. Это обеспечивается с помощью функций и политик безопасности.
🟠Использование триггеров (Triggers)
Триггеры позволяют автоматически выполнять определенные действия перед или после операции
🟠Ограничения на уровне столбца (Column-Level Constraints)
Ограничения на уровне столбца могут использоваться для ограничения возможных значений или для создания выражений, которые должны быть выполнены для выполнения изменения.
⚙ Backend Ready | #урок
В PostgreSQL можно использовать различные методы для блокировки конкретных полей или строк таблицы, чтобы предотвратить их изменение или обеспечить управление конкурентным доступом к данным. Наиболее распространенные способы включают использование транзакционных блокировок и политик доступа.
🟠Использование блокировок уровня строки (Row-Level Locks)
PostgreSQL поддерживает блокировки уровня строки с помощью команд
SELECT FOR UPDATE и SELECT FOR SHARE. Эти команды позволяют заблокировать конкретные строки для изменения другими транзакциями, пока текущая транзакция не завершится.SELECT FOR UPDATE:BEGIN; -- Начало транзакции
-- Выбираем и блокируем строки для обновления
SELECT * FROM my_table WHERE id = 1 FOR UPDATE;
-- Выполняем необходимые операции
UPDATE my_table SET field = 'new_value' WHERE id = 1;
COMMIT; -- Завершение транзакции
SELECT FOR SHARE:BEGIN; -- Начало транзакции
-- Выбираем и блокируем строки для чтения
SELECT * FROM my_table WHERE id = 1 FOR SHARE;
-- Выполняем необходимые операции
-- Изменение данных будет заблокировано для других транзакций
-- Однако, можно выполнять SELECT
COMMIT; -- Завершение транзакции
🟠Использование политик доступа (Row-Level Security Policies)
Политики безопасности на уровне строк позволяют определить, кто и при каких условиях может видеть или изменять данные в таблице. Это обеспечивается с помощью функций и политик безопасности.
-- Включаем безопасность на уровне строк для таблицы
ALTER TABLE my_table ENABLE ROW LEVEL SECURITY;
-- Создаем роль, которая будет иметь доступ
CREATE ROLE limited_role;
-- Создаем политику, которая позволяет только чтение данных
CREATE POLICY read_only_policy ON my_table
FOR SELECT
USING (true); -- Условие для выполнения SELECT
-- Применяем политику для роли limited_role
GRANT SELECT ON my_table TO limited_role;
🟠Использование триггеров (Triggers)
Триггеры позволяют автоматически выполнять определенные действия перед или после операции
INSERT, UPDATE, DELETE. Можно создать триггер, который будет блокировать изменение конкретных полей.CREATE OR REPLACE FUNCTION prevent_update()
RETURNS TRIGGER AS $$
BEGIN
IF NEW.field IS DISTINCT FROM OLD.field THEN
RAISE EXCEPTION 'Field "field" cannot be updated';
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Применяем триггер к таблице
CREATE TRIGGER prevent_update_trigger
BEFORE UPDATE ON my_table
FOR EACH ROW
EXECUTE FUNCTION prevent_update();
🟠Ограничения на уровне столбца (Column-Level Constraints)
Ограничения на уровне столбца могут использоваться для ограничения возможных значений или для создания выражений, которые должны быть выполнены для выполнения изменения.
ALTER TABLE my_table
ADD CONSTRAINT field_check CHECK (field IS NOT NULL);
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3❤1🔥1😁1
Axios против Fetch: выбираем инструмент для запросов в 2026 году 📡
Несмотря на то что в Node.js давно завезли нативный
Разница в подходе: 🛠️
— Fetch: Это низкоуровневый API. Чтобы получить JSON, тебе нужно сделать два шага: сначала дождаться ответа, а потом вызвать
— Axios: Это обертка, которая делает всю грязную работу за тебя. Он автоматически парсит JSON и возвращает готовый объект в
Почему Axios всё еще круче? 🚀
— Интерцепторы (Interceptors): Можно создать функцию, которая будет автоматически добавлять токен авторизации к каждому запросу или логировать время ответа. С
— Таймауты: В Axios таймаут задается одной строкой в конфиге. В
— Обработка ошибок: Axios считает ошибкой любой статус, кроме 2xx.
Пример интерцептора в Axios:
Когда использовать Fetch? 🏗️
— Если ты пишешь легкую библиотеку и не хочешь лишних зависимостей.
— Если ты работаешь в Edge-окружениях (например, Vercel Edge Functions), где важен размер бандла.
— Если тебе просто нужно сделать один запрос и ты не хочешь тянуть NPM-пакет.
Методы и фишки: 📝
— axios.all([]) — удобный аналог
— Base URL — возможность задать корень API один раз и дальше писать только пути. 🧩
— XSRF Protection — встроенная защита от подделки межсайтовых запросов.
> Итог:
---
### **Пакет
Разработка на Node.js без этого пакета — это страдание. Отредактировал файл -> Перешел в консоль ->
Шаг 1 — установка и запуск:
Обычно его ставят как
Зачем это нужно? 🚀
— Скорость разработки: Ты видишь результат своих правок через секунду. 🏎️
— Гибкость: Можно настроить, какие файлы игнорировать (например, тесты или логи), чтобы сервер не перезагружался зря.
— Поддержка любого языка: Через
Крутые фишки: 📝
— nodemon.json — файл настроек, где можно прописать расширения (
— Ручной рестарт: Если что-то зависло, просто введи
— Запуск команд: Можно настроить выполнение линтера или тестов перед каждым перезапуском.
> Важный нюанс: В Node.js 18+ появился встроенный флаг
⚙ Backend Ready | #урок
Несмотря на то что в Node.js давно завезли нативный
fetch, библиотека Axios всё еще остается стандартом в индустрии. Почему разработчики не спешат переходить на «встроенное» решение? Разница в подходе: 🛠️
— Fetch: Это низкоуровневый API. Чтобы получить JSON, тебе нужно сделать два шага: сначала дождаться ответа, а потом вызвать
.json().— Axios: Это обертка, которая делает всю грязную работу за тебя. Он автоматически парсит JSON и возвращает готовый объект в
response.data.Почему Axios всё еще круче? 🚀
— Интерцепторы (Interceptors): Можно создать функцию, которая будет автоматически добавлять токен авторизации к каждому запросу или логировать время ответа. С
fetch тебе придется писать обертку руками. 🔍— Таймауты: В Axios таймаут задается одной строкой в конфиге. В
fetch для этого нужно создавать AbortController (как мы учили в прошлых постах). ⏱️— Обработка ошибок: Axios считает ошибкой любой статус, кроме 2xx.
fetch же не выдаст ошибку, даже если сервер вернул 404 или 500 — тебе нужно вручную проверять свойство res.ok.Пример интерцептора в Axios:
const axios = require('axios');
const api = axios.create({ baseURL: 'https://api.example.com' });
api.interceptors.request.use(config => {
config.headers.Authorization = 'Bearer SECRET_TOKEN';
return config;
});
const data = await api.get('/users'); // Токен подставится сам!
Когда использовать Fetch? 🏗️
— Если ты пишешь легкую библиотеку и не хочешь лишних зависимостей.
— Если ты работаешь в Edge-окружениях (например, Vercel Edge Functions), где важен размер бандла.
— Если тебе просто нужно сделать один запрос и ты не хочешь тянуть NPM-пакет.
Методы и фишки: 📝
— axios.all([]) — удобный аналог
Promise.all для параллельных запросов.— Base URL — возможность задать корень API один раз и дальше писать только пути. 🧩
— XSRF Protection — встроенная защита от подделки межсайтовых запросов.
> Итог:
fetch — это база, которую нужно знать. Но если ты строишь серьезное приложение с кучей запросов, сложной авторизацией и логированием — Axios сэкономит тебе часы времени и сотни строчек кода. ✅---
### **Пакет
nodemon — забываем про ручной перезапуск сервера 🔄**Разработка на Node.js без этого пакета — это страдание. Отредактировал файл -> Перешел в консоль ->
Ctrl+C -> Вверх -> Enter. И так 500 раз в день. Nodemon делает это за тебя: он следит за файлами в папке и перезапускает процесс мгновенно после сохранения.Шаг 1 — установка и запуск:
Обычно его ставят как
devDependency, чтобы он не улетал на боевой сервер.npm install --save-dev nodemon
// package.json
"scripts": {
"dev": "nodemon index.js"
}
npm run dev
Зачем это нужно? 🚀
— Скорость разработки: Ты видишь результат своих правок через секунду. 🏎️
— Гибкость: Можно настроить, какие файлы игнорировать (например, тесты или логи), чтобы сервер не перезагружался зря.
— Поддержка любого языка: Через
nodemon можно запускать даже Python или Ruby скрипты, если тебе нужен авто-рестарт.Крутые фишки: 📝
— nodemon.json — файл настроек, где можно прописать расширения (
.js, .json, .graphql) и папки для слежки. ⚙️— Ручной рестарт: Если что-то зависло, просто введи
rs в терминале, и nodemon перезапустит сервер без выхода из программы.— Запуск команд: Можно настроить выполнение линтера или тестов перед каждым перезапуском.
> Важный нюанс: В Node.js 18+ появился встроенный флаг
--watch. Можно запускать так: node --watch index.js. Это работает быстрее и не требует установки пакетов. Но nodemon всё еще популярен из-за более гибких настроек и удобного лога в консоли. ✅Please open Telegram to view this post
VIEW IN TELEGRAM
❤1👍1🔥1
Python Ready — авторский канал, где Python перестаёт быть только теорией и становится рабочим инструментом. Мини-проекты, боты, советы, разборы задач, гайды и шпаргалки для каждого программиста.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2
Хочешь посмотреть, как Java эволюционировала, фича за фичей?
brunoborges сделал офигенный сайт, где изменения языка Java показаны рядом, в формате side-by-side. Идеально для студентов и для тех, кто модернизирует легаси-приложения.
Зацени:
https://javaevolved.github.io
⚙ Backend Ready | #урок
brunoborges сделал офигенный сайт, где изменения языка Java показаны рядом, в формате side-by-side. Идеально для студентов и для тех, кто модернизирует легаси-приложения.
Зацени:
https://javaevolved.github.io
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 | #урок
Зачем? Просто потому что ему было нечем заняться, он нырнул в кроличью нору информационного поиска: пытался понять, почему и где TF-IDF в итоге упирается в свои пределы, как на самом деле устроен BM25 под капотом, и почему системы вроде Elasticsearch, Solr и Lucene сделали его своей дефолтной функцией ранжирования.
В эссе узнаете, почему BM25 так хорошо работает, как каждая часть формулы влияет на ранжирование, и какое место он занимает в современном retrieval-стеке.
Этот текст должен дать тебе нормальную ментальную модель, чтобы понимать BM25 и также IDF из популярного TF-IDF. Зацени.
Please open Telegram to view this post
VIEW IN TELEGRAM
Fastify — когда Express становится слишком медленным 🏎️
Express — это классика, но он был создан в те времена, когда Node.js только зарождался. Fastify — это современный фреймворк, созданный с фокусом на максимальную производительность и минимальные накладные расходы. Он буквально «летает» за счет оптимизации JSON-схем и встроенной системы плагинов.
Шаг 1 — создаем первый роут:
Синтаксис похож на Express, но сразу предлагает использовать
Зачем это нужно? 🚀
— Сверхскорость: Fastify считается одним из самых быстрых фреймворков для Node.js. Он тратит меньше ресурсов процессора на каждый запрос.
— Валидация «из коробки»: Fastify использует JSON Schema для проверки входных данных. Это не только делает API безопасным, но и ускоряет сериализацию ответов в 2 раза. 🛡️
— Экосистема плагинов: Вместо хаотичного мидлвара, как в Express, здесь строгая и понятная иерархия плагинов.
Крутые фишки: 📝
— Hooks: Ты можешь вклиниться в любой момент жизненного цикла запроса (
— Типизация: Отличная поддержка TypeScript прямо из коробки. 🧩
— Декораторы: Позволяют легко добавлять новые методы в объекты
— Логирование: Встроенный сверхбыстрый логгер Pino (о котором мы писали раньше).
Пример с валидацией:
> Важный нюанс: Если ты начинаешь новый проект в 2026 году — выбирай Fastify. Express всё еще жив, но Fastify предлагает более современную архитектуру и лучшую производительность для микросервисов. ✅
---
### **Пакет
В любом серьезном бэкенде есть задачи, которые должны выполняться сами по себе: рассылка писем по утрам, чистка старых логов или бэкап базы данных в полночь. Пакет
Шаг 1 — настраиваем «будильник»:
Зачем это нужно? 🚀
— Автоматизация: Тебе не нужно помнить о рутинных задачах — сервер сделает всё сам.
— Гибкость: Можно настроить запуск раз в секунду, раз в месяц или только по рабочим дням в 9 утра. 📅
— Надежность: Задачи работают в фоне и не мешают пользователям пользоваться сайтом.
Как читать синтаксис (5 звезд): 📝
—
—
—
—
Крутые фишки: 📝
— Поддержка часовых поясов: Твой сервер может стоять в США, но выполнять задачи по времени твоего города.
— Управление: Задачи можно динамически создавать, останавливать (
— async/await: Внутри задачи можно спокойно использовать асинхронный код для запросов к БД или API.
> Важный нюанс: Если у тебя один сервер —
⚙ Backend Ready | #урок
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. ✅Please open Telegram to view this post
VIEW IN TELEGRAM
BullMQ — мощные очереди задач для тех, кто вырос из обычного Cron 🐂
Когда твой проект растет, простых задач «по расписанию» становится мало. Что, если нужно отправить 10 000 писем, но API почтового сервиса тормозит? Или нужно обработать тяжелое видео, не заставляя пользователя ждать ответа? Здесь на сцену выходит BullMQ — стандарт для очередей задач в Node.js, работающий на базе Redis.
Шаг 1 — создаем очередь и воркер:
Одна часть приложения (продюсер) кидает задачу в очередь, а другая (воркер) — выполняет её, когда освободится.
Зачем это нужно? 🚀
— Фоновая обработка: Пользователь нажимает «Загрузить», и мы сразу говорим ему «Ок, скоро всё будет», а само видео обрабатывается в фоне. 🎬
— Устойчивость к сбоям: Если воркер упадет или сервер перезагрузится, задача не пропадет. Она останется в Redis и будет выполнена позже.
— Rate Limiting: Можно ограничить выполнение задач (например, не больше 5 запросов в секунду к стороннему API), чтобы не получить бан. 🛡️
— Повторы (Retries): Если задача упала с ошибкой (например, сеть мигнула), BullMQ может автоматически попробовать еще раз через 5, 10 или 60 минут.
Крутые фишки: 📝
— Priorities: Можно сделать так, чтобы задачи от Premium-пользователей всегда шли в начало очереди. ✨
— Delayed Jobs: Выполни задачу не сейчас, а ровно через 2 часа.
— Parent/Child Jobs: Создавай сложные цепочки — выполни задачу А, и только если она успешна, запускай задачи Б и В.
— Панель управления: Есть готовые админки (например, BullBoard), где можно в реальном времени смотреть, сколько задач в очереди, сколько упало и почему. 📊
Почему Redis? 🤔
Redis работает в оперативной памяти, поэтому обмен задачами происходит мгновенно. Это намного быстрее, чем хранить очередь в обычной реляционной базе вроде PostgreSQL.
> Важный нюанс: BullMQ — это профессиональный инструмент. Если тебе просто нужно раз в день чистить логи, обычного
⚙ Backend Ready | #урок
Когда твой проект растет, простых задач «по расписанию» становится мало. Что, если нужно отправить 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 хватит. Но если от выполнения задачи зависят деньги или лояльность юзера — используй очереди. ✅Please open Telegram to view this post
VIEW IN TELEGRAM
🔌 Модуль
Когда мы делаем HTTP-запрос, Node.js сам разрешает домены, но иногда приложению нужно делать это вручную: проверить существование домена, получить его IP или узнать MX-записи почтового сервера.
dns — резолвинг и проверка сети**
—
—
—
—
— dns.resolve() — отправляет реальный запрос к DNS-серверам в сети. Позволяет узнать IP-адреса, привязанные к домену.
— dns.lookup() — использует настройки операционной системы (например, файл
— dns.reverse() — выполняет обратное преобразование: вы передаете IP-адрес, а модуль пытается найти имя хоста, которое ему соответствует.
— dns.resolveMx() — возвращает записи почтового обмена. Идеально для проверки, существует ли почтовый сервер у домена перед отправкой письма.
— dns.getServers() — показывает список IP-адресов DNS-серверов, которые в данный момент использует твоя система для резолвинга.
⚙ Backend Ready | #урок
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-серверов, которые в данный момент использует твоя система для резолвинга.
Please open Telegram to view this post
VIEW IN TELEGRAM
🧩 Модуль
Работа со строками через
url — разбор и валидация адресов
—
—
—
—
—
— new URL() — создает объект, который разбивает строку на части: протокол, хост, порт, путь и параметры.
— searchParams — мощный инструмент для работы с GET-запросами. Позволяет легко добавлять, удалять или изменять параметры без ручного склеивания строк.
— pathname — возвращает только путь к ресурсу. Полезно для роутинга, чтобы отсечь домен и параметры поиска.
— origin — возвращает комбинацию протокола и хоста. Идеально для настройки CORS или проверки источника запроса.
— Безопасность — если передать в конструктор
⚙ Backend Ready | #урок
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 некорректную строку, он выдаст ошибку. Это отличный способ проверить, является ли строка валидной ссылкой, прежде чем сохранять её в базу.Please open Telegram to view this post
VIEW IN TELEGRAM
❤2
🔐 Права доступа в Linux — разбираемся с chmod и chown!
В Linux всё есть файл, и безопасность системы строится на том, кто может эти файлы читать, изменять или запускать. Если вы хоть раз видели ошибку
В этом посте:
— Разбираем магические цифры
— Учимся менять владельца файлов через
— Настраиваем права на чтение, запись и запуск.
— Узнаем, как рекурсивно исправить доступ во всей папке.
---
Каждый файл в Linux имеет три группы прав: для Владельца (User), для Группы (Group) и для Всех остальных (Others). Для каждой группы можно разрешить или запретить три действия: r (read — чтение), w (write — запись) и x (execute — запуск).
Как читать цифровой код:
— 4 — чтение (read)
— 2 — запись (write)
— 1 — запуск (execute)
— 0 — нет прав
Складывая эти цифры, мы получаем нужный уровень доступа. Например,
Популярные комбинации:
—
—
—
Иногда проблема не в правах, а в том, что файл принадлежит не тому пользователю (например,
Часто права нужно поправить не в одном файле, а во всей папке с вложенными проектами. Для этого используйте флаг
Использование правильных прав — это не просто «чтобы работало», а защита вашего сервера от взлома. Скрипты должны иметь флаг
⚙ Backend Ready | #урок
В 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) должны быть закрыты от всех, кроме владельца.Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
🛰️ Модуль
Хотя класс
querystring — парсинг и сборка запросов
—
—
—
—
— parse() — превращает строку параметров (то, что идет после знака
— stringify() — делает обратную операцию: берет объект и собирает из него корректную строку параметров, которую можно подставить в URL.
— escape() / unescape() — низкоуровневые методы для работы со спецсимволами. Они заменяют пробелы, кавычки и кириллицу на безопасные коды (например,
— Отличие от URLSearchParams —
⚙ Backend Ready | #урок
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), чтобы сервер мог их прочитать.— Отличие от URLSearchParams —
querystring работает быстрее и поддерживает кастомные разделители. Если вместо & и = тебе нужно использовать ; и :, этот модуль справится в одну строку.const custom = qs.parse('name:tom;age:20', ';', ':');
console.log(custom.name); // tom
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1
📦 Модуль
Node.js работает на движке V8 от Google. Встроенный модуль
v8 — мониторинг и управление памятью
—
—
—
—
— getHeapStatistics() — возвращает детальный отчет о состоянии «кучи» (Heap). Можно узнать общий размер выделенной памяти и лимит, после которого приложение упадет с ошибкой
— serialize() / deserialize() — позволяют превращать объекты JS в бинарный формат V8 и обратно. Это работает быстрее, чем
— setFlagsFromString() — позволяет менять настройки движка прямо во время работы кода. Например, можно принудительно включить или выключить оптимизацию определенных функций (использовать только в целях отладки!).
— Heap Snapshots — через API этого модуля можно программно создавать снимки памяти, чтобы потом проанализировать их в Chrome DevTools и понять, какие объекты «едят» оперативку и не удаляются сборщиком мусора.
⚙ Backend Ready | #урок
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 и понять, какие объекты «едят» оперативку и не удаляются сборщиком мусора.
Please open Telegram to view this post
VIEW IN TELEGRAM
🧩 Модуль
Склеивать пути вручную через
path — навигация по файловой системе
—
—
—
—
—
— path.join() — объединяет все переданные сегменты пути в одну строку, используя разделитель текущей ОС. Он также чистит путь от лишних точек и двойных слешей.
— path.resolve() — превращает последовательность путей в абсолютный путь. Он всегда стартует от корня проекта, что гарантирует точность при поиске файлов.
— path.basename() — возвращает только имя файла из длинного пути. Если вторым аргументом передать расширение, оно будет отрезано.
— path.extname() — достает только расширение файла. Удобно для фильтрации загрузок (например, разрешать только
— path.parse() — разбирает путь на части и возвращает объект с корнем, папкой, полным именем, расширением и именем без расширения.
⚙ Backend Ready | #урок
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' } */
Please open Telegram to view this post
VIEW IN TELEGRAM
🔐 Модуль
Безопасность — это не только HTTPS. Модуль
crypto — шифрование и хэширование
—
—
—
—
— crypto.createHash() — создает необратимый отпечаток данных (хэш). Обычно используется для проверки целостности файлов или сравнения паролей (через алгоритм SHA-256).
— crypto.randomBytes() — генерирует криптографически сильные случайные данные. Это гораздо безопаснее, чем
— crypto.scrypt() — современный алгоритм для безопасного хэширования паролей. Он специально сделан медленным и ресурсозатратным, чтобы защитить от подбора паролей методом перебора (Brute-force).
— Cipher и Decipher — инструменты для симметричного шифрования. Ты можешь зашифровать текст ключом, передать его по сети, а на другом конце расшифровать тем же ключом.
— Hmac — (Hash-based Message Authentication Code). Позволяет убедиться, что данные не были изменены в процессе передачи, используя секретный ключ.
⚙ Backend Ready | #урок
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). Позволяет убедиться, что данные не были изменены в процессе передачи, используя секретный ключ.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2