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
Forwarded from Исходный Код
🛡️ Модуль
Node.js построен вокруг событий. Почти всё — от HTTP-серверов до потоков чтения файлов — работает на базе класса
events — создание и обработка событий
—
—
—
—
— emit() — генерирует событие, передавая данные всем подписанным слушателям. Это похоже на крик в рупор: кто слушает, тот среагирует.
— on() — регистрирует постоянного слушателя. Каждый раз, когда событие случается, вызывается колбэк.
— once() — срабатывает только один раз. После первого выполнения слушатель автоматически удаляется. Удобно для одноразовых действий, например, инициализации БД.
— removeListener() — отписывает конкретную функцию от события. Это критически важно для предотвращения утечек памяти, если ты динамически создаешь слушателей.
— error — это специальное событие. Если ты сделаешь
— MaxListeners — по умолчанию на одно событие можно повесить не более 10 слушателей. Если нужно больше, используй
events — архитектура на основе событийNode.js построен вокруг событий. Почти всё — от HTTP-серверов до потоков чтения файлов — работает на базе класса
EventEmitter. Этот модуль позволяет создавать свои события и строить слабо связанную архитектуру приложения.events — создание и обработка событий
—
emit()—
on() / once()—
removeListener()—
eventNames()— emit() — генерирует событие, передавая данные всем подписанным слушателям. Это похоже на крик в рупор: кто слушает, тот среагирует.
const EventEmitter = require('events');
const myEmitter = new EventEmitter();
myEmitter.emit('order_created', { id: 105 });
— on() — регистрирует постоянного слушателя. Каждый раз, когда событие случается, вызывается колбэк.
— once() — срабатывает только один раз. После первого выполнения слушатель автоматически удаляется. Удобно для одноразовых действий, например, инициализации БД.
myEmitter.on('update', (data) => console.log('Обновлено:', data));
myEmitter.once('start', () => console.log('Запуск системы...'));
— removeListener() — отписывает конкретную функцию от события. Это критически важно для предотвращения утечек памяти, если ты динамически создаешь слушателей.
— error — это специальное событие. Если ты сделаешь
emit('error') и на него никто не подписан, Node.js завершит процесс с ошибкой. Всегда вешай обработчик ошибок!myEmitter.on('error', (err) => {
console.error('Что-то пошло не так:', err.message);
});
— MaxListeners — по умолчанию на одно событие можно повесить не более 10 слушателей. Если нужно больше, используй
setMaxListeners(). Это сделано для того, чтобы ты случайно не создал бесконечный цикл подписок.🌊 Модуль
Если тебе нужно прочитать файл размером 10 ГБ на сервере с 2 ГБ оперативки, обычный
stream — потоковая обработка данных
—
—
—
—
— Readable — поток, из которого можно читать. Данные поступают по мере готовности, не забивая память целиком.
— Writable — поток, в который можно записывать. Например, отправка ответа пользователю или запись логов в файл.
— Transform — особый вид потока, который изменяет данные «на лету». Например, можно сжимать текст в Gzip прямо в процессе чтения.
— pipeline() — современный способ объединения потоков. В отличие от
— Backpressure — механизм, который не дает источнику «затопить» приемник данными, если тот не успевает их обрабатывать. Стримы в Node.js управляют этим автоматически.
⚙ Backend Ready | #урок
stream — работа с огромными данными без перегрузки RAMЕсли тебе нужно прочитать файл размером 10 ГБ на сервере с 2 ГБ оперативки, обычный
fs.readFile уронит приложение. Стримы решают эту проблему, передавая данные небольшими кусочками (чанками), как конвейер.stream — потоковая обработка данных
—
Readable—
Writable—
Duplex / Transform—
pipeline()— Readable — поток, из которого можно читать. Данные поступают по мере готовности, не забивая память целиком.
const fs = require('fs');
const readable = fs.createReadStream('big_video.mp4');
readable.on('data', (chunk) => {
console.log(`Получено ${chunk.length} байт`);
});
— Writable — поток, в который можно записывать. Например, отправка ответа пользователю или запись логов в файл.
const writable = fs.createWriteStream('copy.mp4');
readable.pipe(writable); // Автоматическая перекачка данных
— Transform — особый вид потока, который изменяет данные «на лету». Например, можно сжимать текст в Gzip прямо в процессе чтения.
const zlib = require('zlib');
readable.pipe(zlib.createGzip()).pipe(writable);
— pipeline() — современный способ объединения потоков. В отличие от
.pipe(), он корректно обрабатывает ошибки во всех звеньях цепи и очищает ресурсы, если что-то пошло не так.const { pipeline } = require('stream/promises');
await pipeline(
fs.createReadStream('file.txt'),
zlib.createGzip(),
fs.createWriteStream('file.txt.gz')
);
— Backpressure — механизм, который не дает источнику «затопить» приемник данными, если тот не успевает их обрабатывать. Стримы в Node.js управляют этим автоматически.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2👎1
200 тыс.₽ сейчас РЕАЛЬНО базовый минимум ⏺️
Который нужен для комфортной жизни в любом месте⤵️
Не знаешь, где словить такой куш?
Удаленка в долларах💸 — канал для профи из СНГ с вакансиями в стабильной валюте.
IT, маркетинг, дизайн, крипта: ты точно в этом разбираешься
Осталось только начать нормально зарабатывать!
15+ актуальных вакансий за сегодня уже в канале:
https://t.me/+qoCsrhInumQyN2Ni🔗
Который нужен для комфортной жизни в любом месте
Не знаешь, где словить такой куш?
Удаленка в долларах
IT, маркетинг, дизайн, крипта: ты точно в этом разбираешься
Осталось только начать нормально зарабатывать!
15+ актуальных вакансий за сегодня уже в канале:
https://t.me/+qoCsrhInumQyN2Ni
Please open Telegram to view this post
VIEW IN TELEGRAM
📦 Модуль
Node.js по умолчанию работает в одном потоке. Это значит, что даже на мощном сервере с 16 ядрами ваше приложение будет использовать только одно. Модуль
cluster — многопоточность для бэкенда
—
—
—
—
— cluster.isPrimary — свойство, которое помогает понять, является ли текущий процесс "главным" (менеджером) или "рабочим" (воркером).
— cluster.fork() — создает новый рабочий процесс. Каждый воркер имеет свою память и свой Event Loop, но все они делят один и тот же порт сервера.
— Балансировка нагрузки — Master-процесс сам распределяет входящие запросы между воркерами. Если один воркер занят тяжелыми вычислениями, запрос уйдет свободному.
— Устойчивость — если один из воркеров упадет из-за ошибки, Master-процесс может это отследить и мгновенно запустить новый экземпляр.
⚙ Backend Ready | #урок
cluster — масштабируем приложение на все ядра CPUNode.js по умолчанию работает в одном потоке. Это значит, что даже на мощном сервере с 16 ядрами ваше приложение будет использовать только одно. Модуль
cluster позволяет легко запустить клон вашего приложения на каждом ядре, увеличивая производительность в разы.cluster — многопоточность для бэкенда
—
cluster.isPrimary—
cluster.fork()—
cluster.on('exit')—
process.pid— cluster.isPrimary — свойство, которое помогает понять, является ли текущий процесс "главным" (менеджером) или "рабочим" (воркером).
const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;
if (cluster.isPrimary) {
// Мастер-процесс создает воркеры
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
} else {
// Рабочие процессы запускают сервер
http.createServer((req, res) => {
res.writeHead(200);
res.end('Hello World');
}).listen(8000);
}
— cluster.fork() — создает новый рабочий процесс. Каждый воркер имеет свою память и свой Event Loop, но все они делят один и тот же порт сервера.
— Балансировка нагрузки — Master-процесс сам распределяет входящие запросы между воркерами. Если один воркер занят тяжелыми вычислениями, запрос уйдет свободному.
— Устойчивость — если один из воркеров упадет из-за ошибки, Master-процесс может это отследить и мгновенно запустить новый экземпляр.
cluster.on('exit', (worker, code, signal) => {
console.log(`Воркер ${worker.process.pid} умер. Запускаю новый...`);
cluster.fork();
});
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
🤔 Какие http методы могут быть?
HTTP (HyperText Transfer Protocol) методы представляют собой набор стандартных операций, которые используются для взаимодействия между клиентом и сервером в сети. Каждый метод определяет конкретное действие, которое должен выполнить сервер. Вот основные HTTP методы и их предназначение:
🟠GET
Метод GET используется для получения данных с сервера. Он запрашивает представление ресурса, не изменяя его состояния. GET запросы часто используются для запросов веб-страниц и получения данных из API.
🟠POST
Метод POST используется для отправки данных на сервер с целью создания или обновления ресурса. Это может включать отправку формы на веб-сайте или загрузку файла. POST запросы обычно содержат данные в теле запроса.
🟠PUT
Метод PUT используется для обновления существующего ресурса или создания нового ресурса на сервере. Если ресурс уже существует, он будет обновлен, если нет — будет создан.
🟠DELETE
Метод DELETE используется для удаления ресурса с сервера. Запросы DELETE могут быть небезопасными, так как они изменяют состояние сервера, удаляя данные.
🟠PATCH
Метод PATCH используется для частичного обновления ресурса. В отличие от PUT, который заменяет весь ресурс, PATCH изменяет только указанные части ресурса.
🟠HEAD
Метод HEAD аналогичен GET, но без тела ответа. Используется для получения метаданных о ресурсе, таких как заголовки, без загрузки самого ресурса.
🟠OPTIONS
Метод OPTIONS используется для запроса информации о поддерживаемых методах на сервере или на конкретном ресурсе. Это может быть полезно для определения доступных операций перед отправкой основного запроса.
🟠CONNECT
Метод CONNECT используется для установления туннеля к серверу через прокси. Обычно используется для HTTPS через прокси.
🟠TRACE
Метод TRACE выполняет тестовый запрос по маршруту до ресурса. Он возвращает запрос, полученный сервером, что может помочь в диагностике сетевых проблем или выявлении изменений в маршруте запроса.
⚙ Backend Ready | #урок
HTTP (HyperText Transfer Protocol) методы представляют собой набор стандартных операций, которые используются для взаимодействия между клиентом и сервером в сети. Каждый метод определяет конкретное действие, которое должен выполнить сервер. Вот основные HTTP методы и их предназначение:
🟠GET
Метод GET используется для получения данных с сервера. Он запрашивает представление ресурса, не изменяя его состояния. GET запросы часто используются для запросов веб-страниц и получения данных из API.
🟠POST
Метод POST используется для отправки данных на сервер с целью создания или обновления ресурса. Это может включать отправку формы на веб-сайте или загрузку файла. POST запросы обычно содержат данные в теле запроса.
🟠PUT
Метод PUT используется для обновления существующего ресурса или создания нового ресурса на сервере. Если ресурс уже существует, он будет обновлен, если нет — будет создан.
🟠DELETE
Метод DELETE используется для удаления ресурса с сервера. Запросы DELETE могут быть небезопасными, так как они изменяют состояние сервера, удаляя данные.
🟠PATCH
Метод PATCH используется для частичного обновления ресурса. В отличие от PUT, который заменяет весь ресурс, PATCH изменяет только указанные части ресурса.
🟠HEAD
Метод HEAD аналогичен GET, но без тела ответа. Используется для получения метаданных о ресурсе, таких как заголовки, без загрузки самого ресурса.
🟠OPTIONS
Метод OPTIONS используется для запроса информации о поддерживаемых методах на сервере или на конкретном ресурсе. Это может быть полезно для определения доступных операций перед отправкой основного запроса.
🟠CONNECT
Метод CONNECT используется для установления туннеля к серверу через прокси. Обычно используется для HTTPS через прокси.
🟠TRACE
Метод TRACE выполняет тестовый запрос по маршруту до ресурса. Он возвращает запрос, полученный сервером, что может помочь в диагностике сетевых проблем или выявлении изменений в маршруте запроса.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4
🏗️ Модуль
Иногда возможностей Node.js не хватает, и нужно вызвать системную команду, запустить Python-скрипт или скомпилировать C++ код. Модуль
child_process — работа с системными командами
—
—
—
—
— exec() — запускает команду в оболочке (shell) и буферизирует весь вывод. Идеально для коротких команд, результат которых помещается в память.
— spawn() — запускает процесс и работает с ним через потоки (streams). Это лучший выбор для тяжелых задач или команд с огромным выводом, так как данные передаются частями.
— fork() — специальный метод для запуска других Node.js модулей. Он создает выделенный канал связи (IPC) между родителем и ребенком, позволяя обмениваться объектами через
— Безопасность — никогда не передавайте данные от пользователя напрямую в
⚙ Backend Ready | #урок
child_process — запуск внешних программ и скриптовИногда возможностей Node.js не хватает, и нужно вызвать системную команду, запустить Python-скрипт или скомпилировать C++ код. Модуль
child_process позволяет Node.js порождать дочерние процессы и общаться с ними.child_process — работа с системными командами
—
exec()—
spawn()—
fork()—
execFile()— exec() — запускает команду в оболочке (shell) и буферизирует весь вывод. Идеально для коротких команд, результат которых помещается в память.
const { exec } = require('child_process');
exec('ls -lh', (err, stdout, stderr) => {
if (err) return console.error(err);
console.log(`Файлы:\n${stdout}`);
});
— spawn() — запускает процесс и работает с ним через потоки (streams). Это лучший выбор для тяжелых задач или команд с огромным выводом, так как данные передаются частями.
const { spawn } = require('child_process');
const child = spawn('find', ['/']);
child.stdout.on('data', (data) => {
console.log(`Чанк данных: ${data.length}`);
});
— fork() — специальный метод для запуска других Node.js модулей. Он создает выделенный канал связи (IPC) между родителем и ребенком, позволяя обмениваться объектами через
send().// В родительском коде
const n = fork('worker.js');
n.on('message', (m) => console.log('Получено:', m));
n.send({ hello: 'world' });
— Безопасность — никогда не передавайте данные от пользователя напрямую в
exec(), иначе злоумышленник может выполнить произвольный код на сервере (Command Injection). Используйте spawn() с массивом аргументов — это безопаснее.Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3
🚀 Модуль
Если
worker_threads — многопоточность без копирования процессов
—
—
—
—
— isMainThread — флаг, который помогает понять, выполняется ли код в основном потоке или внутри воркера.
— workerData — позволяет передавать данные из основного потока в воркер при его создании. Это могут быть любые клонируемые объекты.
— parentPort — специальный канал связи, через который воркер может отправлять сообщения обратно в основной поток с помощью
— SharedArrayBuffer — в отличие от
— Зачем это нужно? — Обычный код Node.js блокирует Event Loop при тяжелых циклах. Воркеры позволяют перенести эти циклы «в сторону», чтобы сервер продолжал отвечать на запросы других пользователей.
⚙ Backend Ready | #урок
worker_threads — настоящий параллелизм в Node.jsЕсли
cluster копирует весь процесс, то worker_threads позволяет запускать тяжелые вычисления в отдельных потоках внутри одного и того же процесса. Это идеальное решение для задач, которые нагружают процессор (CPU-intensive), таких как обработка изображений или сложные математические расчеты.worker_threads — многопоточность без копирования процессов
—
Worker—
parentPort—
isMainThread—
workerData— isMainThread — флаг, который помогает понять, выполняется ли код в основном потоке или внутри воркера.
const { Worker, isMainThread, parentPort, workerData } = require('worker_threads');
if (isMainThread) {
const worker = new Worker(__filename, { workerData: 'начать расчет' });
worker.on('message', (result) => console.log('Результат:', result));
} else {
const result = `Воркер получил: ${workerData}`;
parentPort.postMessage(result);
}
— workerData — позволяет передавать данные из основного потока в воркер при его создании. Это могут быть любые клонируемые объекты.
— parentPort — специальный канал связи, через который воркер может отправлять сообщения обратно в основной поток с помощью
postMessage().— SharedArrayBuffer — в отличие от
cluster, воркеры могут разделять одну и ту же область памяти. Это позволяет огромным массивам данных быть доступными для всех потоков одновременно без затрат на копирование.— Зачем это нужно? — Обычный код Node.js блокирует Event Loop при тяжелых циклах. Воркеры позволяют перенести эти циклы «в сторону», чтобы сервер продолжал отвечать на запросы других пользователей.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
📡 Модуль
Если
net — создание TCP-серверов и сокетов
—
—
—
—
— net.createServer() — создает TCP-сервер. В отличие от HTTP, здесь вы сами решаете, какой протокол использовать для общения — будь то чат, передача файлов или свой проприетарный формат.
— net.connect() — создает клиентское соединение с сервером по IP и порту. Это база для написания своих баз данных, прокси-серверов или систем мониторинга.
— socket.pipe() — сокеты в Node.js являются дуплексными стримами. Это значит, что вы можете «пробросить» данные из одного соединения в другое одной командой. Так пишутся простейшие прокси-серверы.
— IPC (Inter-Process Communication) — модуль
⚙ Backend Ready | #урок
net — фундамент сетевого взаимодействияЕсли
http — это высокоуровневый стандарт для веба, то модуль net — это «низкий уровень». Он позволяет работать напрямую с TCP-сокетами, создавая серверы и клиенты, которые общаются голыми данными без лишних заголовков.net — создание TCP-серверов и сокетов
—
net.createServer()—
net.connect()—
socket.write()—
socket.pipe()— net.createServer() — создает TCP-сервер. В отличие от HTTP, здесь вы сами решаете, какой протокол использовать для общения — будь то чат, передача файлов или свой проприетарный формат.
const net = require('net');
const server = net.createServer((socket) => {
socket.write('Привет от TCP сервера!\n');
socket.on('data', (data) => {
console.log('Клиент прислал:', data.toString());
});
});
server.listen(8080);
— net.connect() — создает клиентское соединение с сервером по IP и порту. Это база для написания своих баз данных, прокси-серверов или систем мониторинга.
const client = net.connect({ port: 8080 }, () => {
console.log('Подключено к серверу!');
client.write('Привет, сервер!');
});
— socket.pipe() — сокеты в Node.js являются дуплексными стримами. Это значит, что вы можете «пробросить» данные из одного соединения в другое одной командой. Так пишутся простейшие прокси-серверы.
— IPC (Inter-Process Communication) — модуль
net умеет работать не только с сетью, но и с локальными именованными каналами (Unix Domain Sockets). Это самый быстрый способ заставить два процесса на одном сервере обмениваться даннымиPlease open Telegram to view this post
VIEW IN TELEGRAM
🛡️ Модуль
Если модуль
tls — шифрование сетевого трафика
—
—
—
—
— tls.createServer() — создает сервер, который требует SSL/TLS сертификаты для работы. Без них браузер или клиент не смогут установить безопасное соединение.
— Сертификаты (Key & Cert) — для работы
— tls.connect() — позволяет создать клиент, который безопасно подключается к TLS-серверу. Он автоматически проверяет валидность сертификата сервера, защищая от атак типа «человек посередине» (MITM).
— ALPN (Application-Layer Protocol Negotiation) — расширение TLS, которое позволяет клиенту и серверу договориться, какой протокол использовать (например, HTTP/2 или HTTP/1.1) еще в процессе установки защищенного соединения.
— Безопасность — модуль
⚙ Backend Ready | #урок
tls — защищенные сетевые соединенияЕсли модуль
net работает с «голым» TCP, то tls (Transport Layer Security) добавляет поверх него слой шифрования. Это фундамент для создания защищенных серверов, таких как HTTPS, и безопасной передачи данных, которую невозможно перехватить.tls — шифрование сетевого трафика
—
tls.createServer()—
tls.connect()—
pfx / key / cert—
ALPN— tls.createServer() — создает сервер, который требует SSL/TLS сертификаты для работы. Без них браузер или клиент не смогут установить безопасное соединение.
const tls = require('tls');
const fs = require('fs');
const options = {
key: fs.readFileSync('server-key.pem'),
cert: fs.readFileSync('server-cert.pem')
};
tls.createServer(options, (socket) => {
socket.write('Вы подключены по защищенному каналу!\n');
socket.pipe(socket);
}).listen(8000);
— Сертификаты (Key & Cert) — для работы
tls нужны закрытый ключ (key) и сертификат (cert). В разработке часто используют самоподписанные сертификаты, но в продакшене — только от доверенных центров (CA).— tls.connect() — позволяет создать клиент, который безопасно подключается к TLS-серверу. Он автоматически проверяет валидность сертификата сервера, защищая от атак типа «человек посередине» (MITM).
— ALPN (Application-Layer Protocol Negotiation) — расширение TLS, которое позволяет клиенту и серверу договориться, какой протокол использовать (например, HTTP/2 или HTTP/1.1) еще в процессе установки защищенного соединения.
— Безопасность — модуль
tls по умолчанию использует современные протоколы (TLS 1.2 и 1.3) и отключает старые, уязвимые версии (вроде SSLv3), обеспечивая высокий уровень защиты «из коробки».Please open Telegram to view this post
VIEW IN TELEGRAM
❤1
🛡️ Модуль
Модуль
os — системные данные и ресурсы
—
—
—
—
—
— os.cpus() — возвращает массив объектов с данными о каждом ядре процессора (модель, скорость, время работы). Это ключевой метод для автоматического масштабирования через модуль
— os.freemem() / os.totalmem() — показывают объем свободной и общей оперативной памяти в байтах. Помогает приложению понять, стоит ли сейчас запускать тяжелую задачу или памяти уже критически мало.
— os.networkInterfaces() — выдает детальную информацию о сетевых интерфейсах (IP-адреса, MAC-адреса). Нужно, если вашему серверу необходимо знать свой локальный или внешний IP.
— os.platform() / os.type() — возвращают название платформы (
— os.homedir() — возвращает путь к домашней папке текущего пользователя. Это гораздо надежнее, чем пытаться угадать путь вручную.
⚙ Backend Ready | #урок
os — информация об операционной системеМодуль
os предоставляет методы для взаимодействия с операционной системой, на которой запущен Node.js. Это позволяет адаптировать работу приложения под конкретное железо: узнавать количество ядер, объем свободной оперативной памяти или домашнюю директорию пользователя.os — системные данные и ресурсы
—
os.cpus()—
os.freemem() / os.totalmem()—
os.networkInterfaces()—
os.homedir()—
os.platform()— os.cpus() — возвращает массив объектов с данными о каждом ядре процессора (модель, скорость, время работы). Это ключевой метод для автоматического масштабирования через модуль
cluster.const os = require('os');
console.log(`Ядер процессора: ${os.cpus().length}`);
— os.freemem() / os.totalmem() — показывают объем свободной и общей оперативной памяти в байтах. Помогает приложению понять, стоит ли сейчас запускать тяжелую задачу или памяти уже критически мало.
const freeGB = (os.freemem() / 1024 / 1024 / 1024).toFixed(2);
console.log(`Свободно памяти: ${freeGB} GB`);
— os.networkInterfaces() — выдает детальную информацию о сетевых интерфейсах (IP-адреса, MAC-адреса). Нужно, если вашему серверу необходимо знать свой локальный или внешний IP.
— os.platform() / os.type() — возвращают название платформы (
win32, linux, darwin). Позволяет писать условия для специфических системных команд.if (os.platform() === 'win32') {
console.log('Запущено на Windows');
}
— os.homedir() — возвращает путь к домашней папке текущего пользователя. Это гораздо надежнее, чем пытаться угадать путь вручную.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
🧪 Модуль
Модуль
assert — утверждения и проверки
—
—
—
—
— assert.ok() — проверяет, является ли значение истинным (
— assert.strictEqual() — проверяет равенство значений и их типов (как оператор
— assert.deepStrictEqual() — незаменим для сравнения объектов и массивов. Обычное
— assert.throws() — проверяет, что функция действительно выдает ошибку при определенных условиях. Это важно для тестирования обработки исключений.
— Строгий режим — рекомендуется всегда использовать
⚙ Backend Ready | #урок
assert — простейшее тестирование и валидацияМодуль
assert предназначен для проверки условий в коде. Если условие не выполняется, программа выбрасывает ошибку. Это встроенный инструмент для написания тестов и защиты от некорректных данных на этапе разработки.assert — утверждения и проверки
—
assert.strictEqual()—
assert.deepStrictEqual()—
assert.throws()—
assert.ok()— assert.ok() — проверяет, является ли значение истинным (
truthy). Если передать false, 0 или null, программа выдаст ошибку.const assert = require('assert');
assert.ok(5 > 2); // Всё ок
// assert.ok(1 === 2, 'Единица не равна двойке!'); // Выбросит AssertionError
— assert.strictEqual() — проверяет равенство значений и их типов (как оператор
===). Идеально для проверки того, что функция вернула именно то, что вы ожидали.— assert.deepStrictEqual() — незаменим для сравнения объектов и массивов. Обычное
=== сравнивает ссылки, а этот метод заглядывает внутрь и сравнивает каждое свойство.const obj1 = { a: { b: 1 } };
const obj2 = { a: { b: 1 } };
// assert.strictEqual(obj1, obj2); // Ошибка (разные ссылки)
assert.deepStrictEqual(obj1, obj2); // Всё ок (содержимое одинаковое)
— assert.throws() — проверяет, что функция действительно выдает ошибку при определенных условиях. Это важно для тестирования обработки исключений.
assert.throws(
() => { throw new Error('Упс!'); },
/Упс/
);
— Строгий режим — рекомендуется всегда использовать
assert.strict, так как он применяет более строгие правила сравнения, предотвращая случайные ошибки с приведением типов.Please open Telegram to view this post
VIEW IN TELEGRAM
❤3
Вот одна из самых базовых вещей про то, как работает память в операционных системах, но со временем многие это просто забывают. Небольшое напоминание: когда вы вызываете
Когда вы делаете
Это и есть lazy allocation. ОС назначает реальные страницы только тогда, когда вы начинаете в них писать. Вы можете вызвать
-
-
Почему это важно? Потому что именно RSS реально конкурирует за ресурсы. Именно на него смотрит OOM killer, и именно он в итоге тормозит систему.
У вас может быть процесс, который в профайлере показывает 10 ГБ выделенной памяти, а реально потребляет только 2 ГБ RAM. Разница возникает потому, что большая часть этих областей, выделенных через
Кстати, именно поэтому утечки памяти могут долго оставаться незаметными. Если вы сделали
Самый простой способ посмотреть RSS процесса, это запустить
Так что всегда следите именно за RSS, а не только за объемом памяти, выделенной через
malloc(), вы на самом деле не получаете память, вы получаете обещание.Когда вы делаете
malloc на 1 ГБ, ОС говорит: «Окей, вот тебе 1 ГБ», но реально пока не отдает ни одного байта. На этом этапе выделяется виртуальная память, а фактическое потребление RAM, то есть RSS (Resident Set Size), остается прежним.Это и есть lazy allocation. ОС назначает реальные страницы только тогда, когда вы начинаете в них писать. Вы можете вызвать
malloc() хоть на терабайты на ноутбуке с 16 ГБ RAM, и вызов пройдет успешно. Падение, тот самый segmentation fault, случится позже, когда вы попытаетесь эту память использовать, а система уже не сможет ее реально предоставить.-
malloc(1GB) -> виртуальная память +1 ГБ, RSS +0 МБ-
memset(ptr, 0, 1GB) -> RSS +1 ГБПочему это важно? Потому что именно RSS реально конкурирует за ресурсы. Именно на него смотрит OOM killer, и именно он в итоге тормозит систему.
У вас может быть процесс, который в профайлере показывает 10 ГБ выделенной памяти, а реально потребляет только 2 ГБ RAM. Разница возникает потому, что большая часть этих областей, выделенных через
malloc, была зарезервирована, но к ней так и не было доступа.Кстати, именно поэтому утечки памяти могут долго оставаться незаметными. Если вы сделали
malloc(), потеряли указатель и ни разу в эту память не записали, то вы утекли по виртуальному адресному пространству, но не по физической памяти.Самый простой способ посмотреть RSS процесса, это запустить
ps aux. В выводе вы увидите VSZ (virtual) и RSS (resident) в КБ. Это можно получить и программно :)Так что всегда следите именно за RSS, а не только за объемом памяти, выделенной через
malloc, если хотите понимать, сколько памяти процесс реально потребляет.❤4
🛠️ Модуль
Модуль
util — утилиты и полифиллы
—
—
—
—
— util.promisify() — один из самых важных методов. Он превращает любую функцию, работающую на колбэках, в функцию, которая возвращает
— util.inspect() — продвинутая замена
— util.format() — позволяет создавать строки с использованием спецификаторов (как в языке C). Удобно для создания кастомных логов с динамическими данными.
— util.deprecate() — помечает функцию как устаревшую. При её вызове пользователь увидит в консоли предупреждение, но программа продолжит работу. Идеально для поддержки старых версий вашего API.
— Проверки типов — раньше в
⚙ Backend Ready | #Уроки
util — вспомогательные инструменты для разработчикаМодуль
util содержит набор полезных функций, которые упрощают отладку и расширяют возможности стандартного JavaScript. Он помогает форматировать строки, работать с промисами и проверять типы данных без лишнего кода.util — утилиты и полифиллы
—
util.promisify()—
util.format()—
util.inspect()—
util.callbackify()— util.promisify() — один из самых важных методов. Он превращает любую функцию, работающую на колбэках, в функцию, которая возвращает
Promise. Это позволяет использовать async/await со старыми библиотеками.const util = require('util');
const fs = require('fs');
const readFile = util.promisify(fs.readFile);
const data = await readFile('config.json', 'utf8');
— util.inspect() — продвинутая замена
console.log для объектов. Он умеет красиво подсвечивать синтаксис, ограничивать глубину вложенности и показывать скрытые свойства (неперечисляемые).const obj = { a: 1, b: { c: 2 } };
console.log(util.inspect(obj, { colors: true, depth: 0 }));
— util.format() — позволяет создавать строки с использованием спецификаторов (как в языке C). Удобно для создания кастомных логов с динамическими данными.
const msg = util.format('Пользователь %s залогинился в %d:00', 'Admin', 12);
// Результат: Пользователь Admin залогинился в 12:00
— util.deprecate() — помечает функцию как устаревшую. При её вызове пользователь увидит в консоли предупреждение, но программа продолжит работу. Идеально для поддержки старых версий вашего API.
— Проверки типов — раньше в
util было много методов вроде isArray, но теперь они переехали в глобальные объекты (Array.isArray). Тем не менее, util.types всё еще полезен для проверки специфических объектов движка (например, isRegExp или isDate).Please open Telegram to view this post
VIEW IN TELEGRAM
❤1
🧪 Модуль
Модуль
zlib — алгоритмы сжатия Gzip, Deflate и Brotli
—
—
—
—
— Сжатие файлов —
— Brotli против Gzip — Node.js поддерживает современный алгоритм
— Сжатие «в памяти» — если данных немного, можно использовать методы с колбэками или промисами для быстрого сжатия буфера без создания стримов.
— HTTP-оптимизация — если вы пишете свой сервер на модуле
— Уровни сжатия — вы можете настраивать баланс между скоростью и качеством сжатия (параметр
⚙ Backend Ready | #Уроки
zlib — сжатие данных «на лету»Модуль
zlib предоставляет возможности для архивации данных. Это критически важно для веб-серверов: сжатие HTTP-ответов с помощью Gzip или Brotli позволяет уменьшить размер передаваемого трафика в несколько раз, ускоряя загрузку сайта для пользователей.zlib — алгоритмы сжатия Gzip, Deflate и Brotli
—
createGzip() / createGunzip()—
createBrotliCompress()—
gzip() / gunzip()—
pipeline()— Сжатие файлов —
zlib лучше всего работает в связке со стримами. Вы можете читать файл, «прогонять» его через поток сжатия и сразу записывать результат в архив, не загружая весь файл в память.const zlib = require('zlib');
const fs = require('fs');
const { pipeline } = require('stream');
const gzip = zlib.createGzip();
const source = fs.createReadStream('input.txt');
const destination = fs.createWriteStream('input.txt.gz');
pipeline(source, gzip, destination, (err) => {
if (err) console.error('Ошибка сжатия:', err);
});
— Brotli против Gzip — Node.js поддерживает современный алгоритм
Brotli, который сжимает текстовые данные (HTML, JS, CSS) на 15-20% эффективнее, чем старый добрый Gzip. В модуле он доступен через createBrotliCompress.— Сжатие «в памяти» — если данных немного, можно использовать методы с колбэками или промисами для быстрого сжатия буфера без создания стримов.
const input = 'Много повторяющегося текста текста текста';
zlib.gzip(input, (err, buffer) => {
console.log('Сжатый размер:', buffer.length);
});
— HTTP-оптимизация — если вы пишете свой сервер на модуле
http, вы можете проверять заголовок Accept-Encoding и автоматически сжимать ответ, если браузер клиента это поддерживает.— Уровни сжатия — вы можете настраивать баланс между скоростью и качеством сжатия (параметр
level). Чем выше уровень, тем меньше файл, но тем больше нагрузки на процессор.Please open Telegram to view this post
VIEW IN TELEGRAM
❤2
Модуль
Если тебе нужно создать CLI-интерфейс, который задает вопросы пользователю и обрабатывает ответы, модуль
readline — интерфейс для командной строки
—
—
—
—
— Интерфейс ввода-вывода — для работы нужно создать экземпляр интерфейса, связав его с вводом (
— question() — метод, который выводит вопрос в консоль и ждет, пока пользователь нажмет Enter. Ответ передается в колбэк.
— Чтение потока — если нужно обрабатывать каждую введенную строку (например, для создания чат-бота или кастомной оболочки), используется событие
— Promises API — в новых версиях Node.js можно использовать
— Завершение работы — важно всегда вызывать
⚙ Backend Ready | #Уроки
readline — интерактивный ввод в консолиЕсли тебе нужно создать CLI-интерфейс, который задает вопросы пользователю и обрабатывает ответы, модуль
readline — самый простой встроенный способ это сделать. Он позволяет читать данные из стандартного потока ввода (process.stdin) построчно.readline — интерфейс для командной строки
—
createInterface()—
question()—
on('line')—
close()— Интерфейс ввода-вывода — для работы нужно создать экземпляр интерфейса, связав его с вводом (
stdin) и выводом (stdout) консоли.const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
— question() — метод, который выводит вопрос в консоль и ждет, пока пользователь нажмет Enter. Ответ передается в колбэк.
rl.question('Как тебя зовут? ', (answer) => {
console.log(`Привет, ${answer}!`);
rl.close();
});
— Чтение потока — если нужно обрабатывать каждую введенную строку (например, для создания чат-бота или кастомной оболочки), используется событие
line. Оно срабатывает каждый раз, когда пользователь нажимает Enter.rl.on('line', (input) => {
console.log(`Ты ввел: ${input}`);
});
— Promises API — в новых версиях Node.js можно использовать
readline/promises, чтобы не тонуть в колбэках и работать через await.const readline = require('readline/promises');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
const age = await rl.question('Сколько тебе лет? ');
console.log(`Твой возраст: ${age}`);
rl.close();
— Завершение работы — важно всегда вызывать
rl.close(), иначе процесс Node.js будет продолжать висеть в памяти, ожидая нового ввода.Please open Telegram to view this post
VIEW IN TELEGRAM
🔗 Модуль
Разные операционные системы используют разные разделители путей: Windows предпочитает обратный слэш (
path — манипуляция путями без ошибок
—
—
—
—
— path.join() — объединяет сегменты пути в одну строку, используя специфичный для системы разделитель. Это гораздо надежнее, чем складывать строки через
— path.resolve() — превращает последовательность путей в абсолютный путь. Он работает как команда
— path.extname() — моментально возвращает расширение файла. Полезно, когда нужно отфильтровать только
— path.parse() — разбирает строку пути на составные части: корень, директорию, базовое имя, расширение и имя файла без расширения. Возвращает удобный объект.
— dirname и filename — хотя это глобальные переменные, их почти всегда используют вместе с модулем
⚙ Backend Ready | #Уроки
path — работа с путями к файлам и папкамРазные операционные системы используют разные разделители путей: Windows предпочитает обратный слэш (
\), а Linux и macOS — прямой (/). Модуль path позволяет писать кроссплатформенный код, который будет корректно работать на любой системе, автоматически подстраиваясь под её правила.path — манипуляция путями без ошибок
—
path.join()—
path.resolve()—
path.extname()—
path.parse()— path.join() — объединяет сегменты пути в одну строку, используя специфичный для системы разделитель. Это гораздо надежнее, чем складывать строки через
+.const path = require('path');
const fullPath = path.join('users', 'bairas', 'projects', 'app.js');
// Windows: users\bairas\projects\app.js
// Linux: users/bairas/projects/app.js
— path.resolve() — превращает последовательность путей в абсолютный путь. Он работает как команда
cd в терминале: берет текущую рабочую директорию и «наслаивает» на неё переданные сегменты.— path.extname() — моментально возвращает расширение файла. Полезно, когда нужно отфильтровать только
.jpg картинки или .js скрипты в папке.console.log(path.extname('index.html')); // '.html'
— path.parse() — разбирает строку пути на составные части: корень, директорию, базовое имя, расширение и имя файла без расширения. Возвращает удобный объект.
const info = path.parse('/home/user/dir/file.txt');
/*
{
root: '/',
dir: '/home/user/dir',
base: 'file.txt',
ext: '.txt',
name: 'file'
}
*/
— dirname и filename — хотя это глобальные переменные, их почти всегда используют вместе с модулем
path, чтобы вычислить путь к файлам относительно текущего скрипта, а не от места запуска терминала.Please open Telegram to view this post
VIEW IN TELEGRAM
❤2
🔐 Модуль
Модуль
crypto — шифрование и хеширование
—
—
—
—
— Хеширование (createHash) — превращает строку в уникальный отпечаток фиксированной длины. Это необратимый процесс, который чаще всего используется для проверки целостности файлов или сравнения паролей (хотя для паролей лучше подходят специализированные алгоритмы вроде Argon2).
— HMAC (createHmac) — это хеш-код, который создается с использованием секретного ключа. Он гарантирует не только то, что данные не изменились, но и то, что они были отправлены именно тем, у кого есть этот ключ. Часто используется в API для подписи запросов.
— Симметричное шифрование (createCipheriv) — позволяет зашифровать данные так, чтобы их можно было расшифровать обратно. Для этого используется алгоритм (например, AES-256), ключ и вектор инициализации (IV).
— randomBytes() — генерирует криптографически стойкие случайные данные. В отличие от стандартного
— Цифровые подписи — методы
⚙ Backend Ready | #Уроки
crypto — криптография и безопасностьМодуль
crypto предоставляет набор криптографических функций, которые позволяют защитить данные в вашем приложении. Это не просто инструмент для «закрытия» данных, а мощный движок для создания хешей, генерации ключей, шифрования и работы с цифровыми подписями.crypto — шифрование и хеширование
—
createHash()—
createHmac()—
createCipheriv() / createDecipheriv()—
randomBytes()— Хеширование (createHash) — превращает строку в уникальный отпечаток фиксированной длины. Это необратимый процесс, который чаще всего используется для проверки целостности файлов или сравнения паролей (хотя для паролей лучше подходят специализированные алгоритмы вроде Argon2).
const crypto = require('crypto');
const hash = crypto.createHash('sha256').update('секретный_пароль').digest('hex');
console.log(hash);
— HMAC (createHmac) — это хеш-код, который создается с использованием секретного ключа. Он гарантирует не только то, что данные не изменились, но и то, что они были отправлены именно тем, у кого есть этот ключ. Часто используется в API для подписи запросов.
— Симметричное шифрование (createCipheriv) — позволяет зашифровать данные так, чтобы их можно было расшифровать обратно. Для этого используется алгоритм (например, AES-256), ключ и вектор инициализации (IV).
const algorithm = 'aes-256-cbc';
const key = crypto.randomBytes(32);
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv(algorithm, key, iv);
let encrypted = cipher.update('секретные данные', 'utf8', 'hex');
encrypted += cipher.final('hex');
— randomBytes() — генерирует криптографически стойкие случайные данные. В отличие от стандартного
Math.random(), результат этого метода невозможно предугадать, что делает его идеальным для создания токенов, солей для паролей и ключей сессий.— Цифровые подписи — методы
sign и verify позволяют подписывать данные закрытым ключом и проверять их открытым. Это основа безопасности в распределенных системах и блокчейне.Please open Telegram to view this post
VIEW IN TELEGRAM
❤1
📡 Модуль
Модуль
http — база веб-коммуникаций
—
—
—
—
— createServer() — основной метод для запуска сервера. В колбэк приходят два объекта:
— IncomingMessage (req) — объект, из которого можно достать всё о клиенте: URL, метод (GET/POST), заголовки и тело запроса. Поскольку это поток (Stream), данные из тела запроса нужно собирать по частям.
— ServerResponse (res) — через этот объект ты управляешь тем, что увидит пользователь. Ты можешь устанавливать статус-коды (200, 404, 500) и отправлять данные в любом формате: от обычного текста до JSON или HTML.
— http.request() — позволяет Node.js самому выступать в роли клиента. С его помощью можно делать запросы к сторонним API или микросервисам.
— Производительность — стандартный модуль
⚙ Backend Ready | #Уроки
http — создание веб-серверов без библиотекМодуль
http — это сердце сетевых возможностей Node.js. Именно на нем построены такие гиганты, как Express или Fastify. Он позволяет создать полноценный веб-сервер, который умеет принимать запросы, парсить заголовки и отправлять ответы пользователям.http — база веб-коммуникаций
—
createServer()—
request()—
IncomingMessage—
ServerResponse— createServer() — основной метод для запуска сервера. В колбэк приходят два объекта:
req (запрос от пользователя) и res (твой ответ ему).const http = require('http');
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Привет! Ты на сервере Node.js');
});
server.listen(3000);
— IncomingMessage (req) — объект, из которого можно достать всё о клиенте: URL, метод (GET/POST), заголовки и тело запроса. Поскольку это поток (Stream), данные из тела запроса нужно собирать по частям.
— ServerResponse (res) — через этот объект ты управляешь тем, что увидит пользователь. Ты можешь устанавливать статус-коды (200, 404, 500) и отправлять данные в любом формате: от обычного текста до JSON или HTML.
— http.request() — позволяет Node.js самому выступать в роли клиента. С его помощью можно делать запросы к сторонним API или микросервисам.
const options = {
hostname: 'google.com',
port: 80,
path: '/',
method: 'GET'
};
const req = http.request(options, (res) => {
console.log(`Статус: ${res.statusCode}`);
});
req.end();
— Производительность — стандартный модуль
http очень быстрый, так как не содержит лишних «надстроек». Это отличный выбор, когда нужно написать максимально легкий микросервис или прокси-сервер.Please open Telegram to view this post
VIEW IN TELEGRAM
❤3