Перейти к содержанию

ru

2.0k Темы 2.9k Сообщения

Подкатегории


  • Раздел, посвящённый компьютерным играм! Обсуждаем новинки, делимся впечатлениями от прохождения и общаемся с единомышленниками. Геймеры всех платформ — присоединяйтесь!

    524 597
    524 Темы
    597 Сообщения
    GameFishG
    [image: 1778965215850-a02deb5f-552a-4060-92af-e776c9cad746-image.webp] Если коротко - добавили рематчи с боссами, новые навыки Дамианы в рукопашку, правки боев с боссами и пачку фиксов стабильности/багов. Что известно Вышло обновление 1.07.00 от 15 мая 2026. Ключевой фокус патча - добавить боссы для повторной битвы, усилить боевой арсенал Дамианы в рукопашном бою и подтянуть стабильность. В патче есть правки поведения ряда боссов, включая Пробуждённого Людвига (фикс некорректных движений при некоторых атаках). Параллельно Pearl Abyss в целом «заливают» игру апдейтами, продолжая линию 1.06.00/1.06.01, где уже завозили новых маунтов, добычу и т.п. Что интересного добавили Повторные бои с боссами. Добавили новый функционал рематчей: теперь с рядом боссов можно сражаться повторно, у каждого есть своё место для повторной битвы (список и локации спрятаны в выпадающем меню на странице патча, чтобы не спойлерить сюжет). Новые навыки для Дамианы (рукопашка). В патче отдельно подчёркивается добавление новых умений Дамианы для боя врукопашную, расширяющих её билд под ближний бой; названия и точные эффекты частично скрыты от спойлеров в интерфейсе самой заметки. Правки и улучшения боёв с боссами. Разработчики прошлись по ряду боссов: исправили баги с анимациями и поведением (например, у Пробуждённого Людвига были некорректные движения при некоторых атаках, сейчас это поправили). Общие фиксы стабильности. Патч включает «различные исправления ошибок и улучшения стабильности» — типичный набор мелких правок, чтобы уменьшить вылеты, подвисания и странные визуальные/логические баги. На внешних ресурсах апдейт 1.07.00 также описывают как еще один шаг к прокачке эндгейма и выравниванию качества жизни, на фоне предыдущих патчей с маунтами, добычей и настройкой сложности.
  • Раздел, посвящённый образованию! Обсуждаем курсы, учебные программы, методики обучения и делимся опытом саморазвития. Здесь найдётся место и для школьников, и для студентов, и для тех, кто учится всю жизнь. Присоединяйтесь — будем учиться вместе!

    32 101
    32 Темы
    101 Сообщения
    kirilljsxK
    TLS (Transport Layer Security) - это криптографический протокол, который обеспечивает защищённую передачу данных между сетевыми узлами, гарантируя конфиденциальность, целостность и аутентификацию. Он является современным преемником устаревшего протокола SSL и используется везде, где требуется шифрование сетевого трафика (например, в HTTPS). Что известно Три столпа безопасности: Конфиденциальность: данные шифруются с помощью симметричных алгоритмов, чтобы третьи лица не могли их прочитать. Целостность: используются коды аутентификации (MAC или AEAD), чтобы исключить незаметную подмену данных при передаче. Аутентификация: сервер (а опционально и клиент) подтверждает свою подлинность с помощью цифровых сертификатов X.509. Архитектура: Протокол работает поверх TCP и состоит из двух уровней. TLS Handshake (рукопожатие) отвечает за согласование алгоритмов, проверку сертификатов и генерацию общих ключей. TLS Record отвечает за фрагментацию и шифрование самих данных. Смена парадигмы: Раньше для обмена ключами часто использовался RSA. Современные версии требуют использования алгоритмов с прямой секретностью (Forward Secrecy), например, ECDHE. Это значит, что даже если злоумышленник сохранит весь трафик и позже украдёт приватный ключ сервера, он не сможет расшифровать прошлые сессии. Различия версий TLS Эволюция протокола направлена на отказ от уязвимых алгоритмов и ускорение установки соединения. Версия Статус (IETF) Ключевые особенности, отличия и уязвимости SSL 2.0 / 3.0 Запрещены Исторические версии. Содержат критические уязвимости (POODLE, DROWN). Использование категорически запрещено стандартом RFC 7568. TLS 1.0 Запрещены Вышел в 1999 году. Не поддерживает современные шифры. Уязвим к атакам BEAST и POODLE. Браузеры и крупные сервисы отключили его поддержку в 2020 году (RFC 8996). TLS 1.1 Запрещены Вышел в 2006 году. Устранял некоторые уязвимости CBC-режима, но так и не получил поддержки современных AEAD-шифров. Также официально запрещён к использованию (RFC 8996). TLS 1.2 Актуален (Золотой стандарт) Вышел в 2008 году. Добавил поддержку AEAD-шифров (GCM), алгоритмов SHA-256 и гибкость в настройке. До сих пор массово используется как резервный протокол для старых клиентов. TLS 1.3 Актуален (Рекомендуемый) Вышел в 2018 году (RFC 8446). Главное отличие: радикально упрощён и ускорен. Рукопожатие занимает 1-RTT (Round Trip Time) вместо 2-RTT, а для повторных подключений — 0-RTT. Из него полностью удалены небезопасные алгоритмы (RSA, CBC, MD5, SHA-1, RC4). Прямая секретность (PFS) теперь обязательна. Идеи и варианты: Практическое применение в инфраструктуре Если вы настраиваете веб-сервер (Nginx, Apache) или бэкенд (Node.js), вот список действий для достижения максимальной безопасности (оценка A+ на SSL Labs): Жёсткое отключение старых версий: В конфигурации сервера разрешите только TLSv1.2 и TLSv1.3. Оптимизация Cipher Suites (Наборов шифров): Оставьте только AEAD-шифры. Для TLS 1.3 это стандартные TLS_AES_256_GCM_SHA384 и TLS_CHACHA20_POLY1305_SHA256. Для TLS 1.2 оставьте ECDHE-ECDSA-AES256-GCM-SHA384 и ECDHE-RSA-AES256-GCM-SHA384. Переход на ECDSA-сертификаты: Используйте эллиптические кривые (например, P-256 или P-384) вместо RSA. Это значительно снижает нагрузку на CPU при рукопожатии (handshake) и ускоряет установку соединения. Внедрение HSTS (HTTP Strict Transport Security): Добавьте заголовок Strict-Transport-Security: max-age=31536000; includeSubDomains; preload. Это защитит от downgrade-атак, когда злоумышленник пытается принудительно перевести соединение на HTTP или TLS 1.0. Настройка OCSP Stapling: Вместо того чтобы заставлять браузер клиента самостоятельно проверять статус отзыва сертификата (что замедляет загрузку), настройте сервер так, чтобы он сам периодически запрашивал этот статус у центра сертификации и отдавал его клиенту вместе с сертификатом.
  • Все об искусственном интеллекте

    223 272
    223 Темы
    272 Сообщения
    AladdinA
    Подтверждаю, есть что-то такое в этом. наверно это и на людях работает, когда тебя заваливают правилами, и громоздкими инструкциями то ты тоже скорее всего запутаешься и ошибешься.
  • Актуальные IT-новости: обзоры технологий, релизы ПО, события индустрии (искусственный интеллект, кибербезопасность, стартапы). Аналитика рынка, тренды, кейсы компаний. Экспертные мнения, прогнозы, дискуссии о будущем IT. Следите за обновлениями Apple, Google, Microsoft и других гигантов.

    171 316
    171 Темы
    316 Сообщения
    kirilljsxK
    [image: 1791804890911-%D1%81%D0%BD%D0%B8%D0%BC%D0%BE%D0%BA-%D1%8D%D0%BA%D1%80%D0%B0%D0%BD%D0%B0-2026-10-12-%D0%B2-14.34.46-resized.webp] После атак БПЛА многие сервисы Яндекса перестали работать, а когда все восстановят - никто и не знает. Под удар попали такие сервисы как: Метрика Вебмастер Алиса Диск Частично не работает яндекс почта в корпоративном сегменте Ждем и надеемся что инженеры Яндекс все поправят.
  • Cоветы по работе с Node.js, Express, Nest.js, Fastify, Rust, Go, Spring. RESTful и GraphQL API, реализации микросервисной архитектуры, оптимизации с помощью кэширования, очередей и асинхронной обработки. Вопросы безопасности, аутентификация, авторизация, CI/CD, контейнеризация с Docker, облачные технологии AWS, Azure, GCP.

    94 118
    94 Темы
    118 Сообщения
    kirilljsxK
    Ниже представлена группировка основных core-модулей с кратким назначением. Это не исчерпывающий список для всех версий, но покрывает ключевые модули, которые вы можете встретить в документации Node.js. Сеть и HTTP http — создание HTTP-серверов и клиентов. https — то же, но с TLS/SSL. net — низкоуровневые TCP/IPC сокеты. dgram — UDP-сокеты. dns — DNS-резолвинг (запросы к DNS). tls — TLS/SSL обёртки для сокетов. Файловая система и потоки fs — работа с файловой системой (синхронно/асинхронно, стримы). fs/promises — promise-версия API fs. stream — базовые абстракции потоков (Readable, Writable, Duplex, Transform). stream/promises — promise-обёртки для потоков (например, pipeline). zlib — сжатие/распаковка (gzip, deflate, brotli и т.п.). Криптография и безопасность crypto — криптографические функции (хэши, шифрование, подписи, генерация ключей). tls — TLS-соединения (частично пересекается с безопасностью). Система и окружение os — информация об ОС (память, CPU, платформа и т.д.). process — глобальный объект процесса (переменные окружения, аргументы, сигналы). v8 — доступ к некоторым internals движка V8 (статистика, флаги). perf_hooks — Performance API (замеры времени, наблюдение за событиями). Модульность и загрузка module — система модулей CommonJS, builtinModules, createRequire и др. vm — запуск кода в изолированных контекстах (песочницы). wasi — WebAssembly System Interface (запуск WASM-модулей с доступом к ОС). Асинхронность и события events — EventEmitter, основа событийной модели. timers — setTimeout, setInterval, setImmediate и их promise-версии. async_hooks — отслеживание асинхронных контекстов (для логгеров, трейсинга). worker_threads — настоящие рабочие потоки для CPU-задач. child_process — запуск дочерних процессов. cluster — кластеризация (мастер + воркеры) для использования всех ядер. Утилиты и вспомогательные util — утилиты (наследование, форматирование, promisify, types и т.п.). assert — утверждения для тестов. buffer — работа с бинарными данными. querystring — парсинг/сериализация query-строк (устаревает, но ещё есть). url — парсинг и форматирование URL (включая WHATWG URL API). path — утилиты для работы с путями файлов. readline — чтение построчно из stdin (для CLI). repl — создание REPL-консоли. Отладка, тестирование, интроспекция test / node:test — встроенный тест-раннер (требует префикса node:). test/reporters / node:test/reporters — репортёры для node:test. inspector — доступ к V8 Inspector (для отладки, профилирования). trace_events — трассировка событий ядра Node.js. Новые/специфичные модули (требуют node:) node:sqlite — встроенный SQLite (появился в новых версиях). node:sea — Single Executable Application (упаковка в один бинарник). node:ffi — Foreign Function Interface (вызов нативных библиотек; экспериментально). Как посмотреть список в своей версии Node В любой современной Node.js можно выполнить: console.log(require('module').builtinModules); или в ESM: import { builtinModules } from 'node:module'; console.log(builtinModules); Это вернёет массив имён всех встроенных модулей для вашей версии (без префикса node:, кроме тех, где он обязателен).
  • HTML, CSS, JavaScript, React, Vue, Angular, Svelte, UI фреймворки! Адаптивная верстка, оптимизация, Webpack/Vite, SSR. Помощь новичкам, экспертные кейсы, тренды (PWA, JAMstack).

    217 310
    217 Темы
    310 Сообщения
    kirilljsxK
    Как получить пароль приложения для Яндекс почты Заходим в настройки почты [image: 1781089881341-0c693338-e460-4eb1-9bd7-876cf010ef69-image.webp] Далее проваливаемся в почтовые программы [image: 1781089890233-99e36ddc-39c3-474d-aa52-ae8dd5b90448-image.webp] Видим разрашения доступов [image: 1781089896691-f1ad9bea-dff3-4129-a698-659fa057c06f-image.webp] Тыкаем на пароли приложения [image: 1781089901577-2a2fa9f4-054a-4477-ae5f-e9c22268b998-image.webp] Яндекс опять показывает кучу всего не нужного, тыкаем на “Безопасность” [image: 1781089907155-617348df-dc05-4357-a5b6-3dbb9c9c0830-image.webp] И вот тут наконец-то мы видим наши долгожданные пароли приложений если прокрутить вниз [image: 1781089914494-0d2a66b2-fcf8-4e80-ad2a-c5cd7d415b4e-image.webp] Далее создаем пароль приложения, кстати важно! Пароль показывается один раз, так что запишите его. [image: 1781089921069-61868799-8d86-4cd8-8ef5-ed64a7a6377d-image.webp] Ну, а кому лень тыкать и понимать где находятся пароли приложения, вот ссылка - https://id.yandex.ru/security/app-passwords по ней сразу перейдете в нужный раздел, только убедитесь что вы залогинены в нужной вам почте.
  • iOS (Swift, Objective C), Android (Kotlin), Flutter, React Native! Создание UI/UX, тестирование, интеграция API, публикация в магазины. Решайте ошибки, делитесь лайфхаками, изучайте тренды (AR, IoT). Помощь новичкам и экспертные кейсы.

    5 11
    5 Темы
    11 Сообщения
    Q
    QuickBooks Integration Services | Sync eCom, CRM, Payroll Explore all QBIS services to sync QuickBooks with eCommerce, CRMs, payments and payroll tools. Automate your accounting. Start a free demo today! Managing multiple business applications alongside QuickBooks can quickly become overwhelming. Manually transferring sales data, customer information, payroll records, and payment transactions not only consumes valuable time but also increases the risk of accounting errors. QBIS helps businesses eliminate these challenges through powerful QuickBooks integration services designed to automate workflows and keep financial data accurate across all systems.
  • Синтаксис, библиотеки, фреймворки, алгоритмы, ООП, функциональное, асинхронное, многопоточное программирование. Помощь новичкам, советы экспертов, тренды и кейсы. Решайте задачи, делитесь кодом.

    545 741
    545 Темы
    741 Сообщения
    AladdinA
    Декоратор в Python это обычная функция, которая принимает другую функцию (или класс) как аргумент, расширяет её поведение и возвращает новый вызываемый объект. Синтаксис @decorator это просто синтаксический сахар: запись @timer над функцией foo полностью эквивалентна foo = timer(foo). def my_decorator(func): def wrapper(*args, **kwargs): print("до вызова") result = func(*args, **kwargs) print("после вызова") return result return wrapper @my_decorator def greet(name): print(f"Привет, {name}!") # Эквивалентно: greet = my_decorator(greet) greet("Alice") # до вызова # Привет, Alice! # после вызова Механизм работы в три шага: Python видит @decorator, вызывает decorator(func) в момент определения функции (не при вызове), сохраняет результат под тем же именем. Это важно: код декоратора вне wrapper выполняется один раз при загрузке модуля. functools.wraps — первое правило декораторов Без @wraps задекорированная функция теряет своё имя, docstring и сигнатуру. Это ломает отладку, help(), inspect, Sphinx-документацию и любые инструменты интроспекции. from functools import wraps def my_decorator(func): @wraps(func) # копирует __name__, __doc__, __module__, __annotations__ def wrapper(*args, **kwargs): return func(*args, **kwargs) return wrapper @my_decorator def add(a: int, b: int) -> int: """Складывает два числа.""" return a + b print(add.__name__) # add (без @wraps было бы 'wrapper') print(add.__doc__) # Складывает два числа. @wraps под капотом вызывает functools.update_wrapper, который копирует атрибуты __module__, __name__, __qualname__, __annotations__, __doc__ и обновляет __wrapped__, позволяя при необходимости добраться до оригинальной функции через add.__wrapped__. Встроенные декораторы — стандартная библиотека @property Превращает метод в управляемый атрибут с геттером, сеттером и делитером. Позволяет добавить валидацию без изменения публичного API класса. class Temperature: def __init__(self, celsius: float = 0): self._celsius = celsius @property def celsius(self) -> float: return self._celsius @celsius.setter def celsius(self, value: float): if value < -273.15: raise ValueError("Ниже абсолютного нуля невозможно") self._celsius = value @property def fahrenheit(self) -> float: return self._celsius * 9 / 5 + 32 t = Temperature(100) print(t.fahrenheit) # 212.0 t.celsius = -300 # ValueError @staticmethod и @classmethod @staticmethod объявляет метод, не привязанный ни к экземпляру (self), ни к классу (cls это просто функция внутри пространства имён класса. @classmethod передаёт сам класс первым аргументом, что позволяет создавать альтернативные конструкторы. class Date: def __init__(self, year: int, month: int, day: int): self.year, self.month, self.day = year, month, day @classmethod def from_string(cls, s: str) -> "Date": year, month, day = map(int, s.split("-")) return cls(year, month, day) # работает и в подклассах @staticmethod def is_leap_year(year: int) -> bool: return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0) d = Date.from_string("2024-03-15") print(Date.is_leap_year(2024)) # True @dataclass Автоматически генерирует __init__, __repr__, __eq__ и, опционально, методы сравнения и хэширования. Начиная с Python 3.10 можно использовать slots=True для экономии памяти. from dataclasses import dataclass, field @dataclass(order=True, frozen=True) class Point: x: float y: float label: str = field(default="", compare=False) p1 = Point(1.0, 2.0, "A") p2 = Point(3.0, 4.0, "B") print(p1 < p2) # True (сравнивает x, затем y) # p1.x = 5.0 # FrozenInstanceError, т.к. frozen=True Параметры eq, order, frozen, slots, kw_only (3.10+) и match_args (3.10+) позволяют точно настроить поведение. @abstractmethod Из модуля abc. Помечает метод как абстрактный: класс, содержащий хотя бы один такой метод, нельзя инстанциировать. Подкласс обязан переопределить все абстрактные методы. from abc import ABC, abstractmethod class Shape(ABC): @abstractmethod def area(self) -> float: ... @abstractmethod def perimeter(self) -> float: ... class Circle(Shape): def __init__(self, r: float): self.r = r def area(self) -> float: return 3.14159 * self.r ** 2 def perimeter(self) -> float: return 2 * 3.14159 * self.r # Shape() # TypeError: Can't instantiate abstract class c = Circle(5) @cached_property Добавлен в Python 3.8. Вычисляет значение при первом обращении, кэширует его в __dict__ экземпляра и больше не вызывает getter. В отличие от @property нет лишнего вызова при каждом обращении. from functools import cached_property import statistics class Dataset: def __init__(self, data: list[float]): self._data = data @cached_property def stats(self) -> dict: print("вычисляем...") # выполнится только один раз return { "mean": statistics.mean(self._data), "stdev": statistics.stdev(self._data), } ds = Dataset([1, 2, 3, 4, 5]) print(ds.stats) # вычисляем... {'mean': 3, 'stdev': 1.58...} print(ds.stats) # из кэша, без "вычисляем..." Важно: не работает с __slots__ и не потокобезопасен без внешней блокировки. @override (Python 3.12+) Из модуля typing. Сигнализирует тайп-чекеру, что метод переопределяет родительский. Если в родителе метод переименовали или удалили, тайп-чекер выдаст ошибку. from typing import override class Base: def process(self, data: str) -> str: return data.upper() class Child(Base): @override def process(self, data: str) -> str: # ошибка, если в Base нет process return data.lower() @deprecated (Python 3.13+) Из модуля warnings. Помечает функцию или класс как устаревший: при вызове автоматически выдаётся DeprecationWarning, а тайп-чекеры отображают предупреждение. from warnings import deprecated @deprecated("Используйте new_api() вместо этого") def old_api(): return 42 old_api() # DeprecationWarning: Используйте new_api() вместо этого functools — арсенал высшего порядка @lru_cache и @cache @lru_cache(maxsize=N) кэширует результаты функции по аргументам (мемоизация), выбрасывая наименее использованные записи при достижении лимита. @cache (Python 3.9+) это @lru_cache(maxsize=None) без ограничения размера. from functools import lru_cache, cache @lru_cache(maxsize=128) def fibonacci(n: int) -> int: if n < 2: return n return fibonacci(n - 1) + fibonacci(n - 2) print(fibonacci(50)) # мгновенно print(fibonacci.cache_info()) # CacheInfo(hits=48, misses=51, maxsize=128, currsize=51) fibonacci.cache_clear() # сбросить кэш # Для чистых функций без ограничения размера: @cache def factorial(n: int) -> int: return n * factorial(n - 1) if n else 1 Аргументы должны быть хэшируемыми. Список, словарь или другой изменяемый тип вызовет TypeError. Для методов экземпляра лучше использовать @cached_property или явно кэшировать через словарь. @singledispatch Реализует перегрузку функций по типу первого аргумента (single dispatch, аналог pattern matching по типу). from functools import singledispatch @singledispatch def process(value): raise TypeError(f"Неподдерживаемый тип: {type(value)}") @process.register(int) def _(value: int) -> str: return f"Целое: {value * 2}" @process.register(str) def _(value: str) -> str: return f"Строка: {value.upper()}" @process.register(list) @process.register(tuple) def _(value) -> str: return f"Последовательность длиной {len(value)}" print(process(5)) # Целое: 10 print(process("hello")) # Строка: HELLO print(process([1, 2, 3])) # Последовательность длиной 3 Для методов классов используется functools.singledispatchmethod (Python 3.8+). @total_ordering Если определить __eq__ и один из методов сравнения (__lt__, __le__, __gt__, __ge__), @total_ordering автоматически выведет остальные три. from functools import total_ordering @total_ordering class Version: def __init__(self, major: int, minor: int, patch: int): self.v = (major, minor, patch) def __eq__(self, other) -> bool: return self.v == other.v def __lt__(self, other) -> bool: return self.v < other.v v1 = Version(1, 2, 3) v2 = Version(2, 0, 0) print(v1 < v2) # True print(v1 >= v2) # False (сгенерировано @total_ordering) print(v2 > v1) # True (сгенерировано @total_ordering) Декораторы с параметрами Чтобы передать аргументы в декоратор, нужен ещё один уровень вложенности: функция, возвращающая декоратор. from functools import wraps import time def retry(max_attempts: int = 3, delay: float = 1.0, exceptions=(Exception,)): def decorator(func): @wraps(func) def wrapper(*args, **kwargs): last_exc = None for attempt in range(1, max_attempts + 1): try: return func(*args, **kwargs) except exceptions as e: last_exc = e print(f"Попытка {attempt}/{max_attempts} не удалась: {e}") if attempt < max_attempts: time.sleep(delay) raise last_exc return wrapper return decorator @retry(max_attempts=3, delay=0.5, exceptions=(ConnectionError,)) def fetch_data(url: str) -> str: # симулируем нестабильное соединение import random if random.random() < 0.7: raise ConnectionError("Нет соединения") return "data" Начиная с Python 3.8 можно сделать декоратор, работающий как с аргументами (@retry(3)), так и без (@retry), через параметр func=None и позиционно-ключевые аргументы: def retry(_func=None, *, max_attempts: int = 3): def decorator(func): @wraps(func) def wrapper(*args, **kwargs): for _ in range(max_attempts): try: return func(*args, **kwargs) except Exception: pass raise RuntimeError("Все попытки исчерпаны") return wrapper if _func is not None: # вызов без скобок: @retry return decorator(_func) return decorator # вызов со скобками: @retry(max_attempts=5) Стекирование декораторов Несколько декораторов применяются снизу вверх: ближайший к функции оборачивает первым. from functools import wraps def bold(func): @wraps(func) def wrapper(*args, **kwargs): return f"<b>{func(*args, **kwargs)}</b>" return wrapper def italic(func): @wraps(func) def wrapper(*args, **kwargs): return f"<i>{func(*args, **kwargs)}</i>" return wrapper @bold @italic def greet(name: str) -> str: return f"Привет, {name}!" # Эквивалентно: greet = bold(italic(greet)) print(greet("Alice")) # <b><i>Привет, Alice!</i></b> Порядок имеет значение. @bold @italic дают <b><i>...</i></b>, тогда как @italic @bold дадут <i><b>...</b></i>. Декораторы классов Декоратор может быть не только функцией, но и классом. В таком случае __call__ становится телом обёртки, а __init__ получает декорируемую функцию. from functools import wraps, update_wrapper import time class Timer: """Декоратор-класс: замеряет время выполнения.""" def __init__(self, func): self.func = func self.total_time = 0.0 self.call_count = 0 update_wrapper(self, func) # аналог @wraps для классов def __call__(self, *args, **kwargs): start = time.perf_counter() result = self.func(*args, **kwargs) elapsed = time.perf_counter() - start self.total_time += elapsed self.call_count += 1 print(f"{self.func.__name__}: {elapsed:.4f}с") return result def stats(self): avg = self.total_time / self.call_count if self.call_count else 0 return {"total": self.total_time, "calls": self.call_count, "avg": avg} @Timer def slow_sum(n: int) -> int: return sum(range(n)) slow_sum(1_000_000) slow_sum(500_000) print(slow_sum.stats()) Декоратор-класс удобен, когда нужно хранить состояние между вызовами (счётчик, накопленное время, кэш). Применение декоратора к классу целиком Декоратор можно применить и к классу: Python передаёт объект класса, а не функции. def add_repr(cls): """Добавляет __repr__, если его нет.""" if "__repr__" not in cls.__dict__: def __repr__(self): attrs = ", ".join( f"{k}={v!r}" for k, v in self.__dict__.items() ) return f"{cls.__name__}({attrs})" cls.__repr__ = __repr__ return cls @add_repr class Config: def __init__(self, host: str, port: int): self.host = host self.port = port print(Config("localhost", 8080)) # Config(host='localhost', port=8080) Практические паттерны Логирование import logging from functools import wraps def log_calls(logger=None, level=logging.DEBUG): _logger = logger or logging.getLogger(__name__) def decorator(func): @wraps(func) def wrapper(*args, **kwargs): _logger.log(level, "Вызов %s args=%s kwargs=%s", func.__name__, args, kwargs) try: result = func(*args, **kwargs) _logger.log(level, "%s вернул %r", func.__name__, result) return result except Exception as exc: _logger.exception("%s выбросил %s", func.__name__, exc) raise return wrapper return decorator logging.basicConfig(level=logging.DEBUG) @log_calls() def divide(a: float, b: float) -> float: return a / b Rate Limiter import time from collections import deque from functools import wraps def rate_limit(calls: int, period: float): """Не более `calls` вызовов за `period` секунд.""" def decorator(func): timestamps: deque = deque() @wraps(func) def wrapper(*args, **kwargs): now = time.monotonic() while timestamps and now - timestamps >= period: timestamps.popleft() if len(timestamps) >= calls: sleep_for = period - (now - timestamps) time.sleep(sleep_for) timestamps.append(time.monotonic()) return func(*args, **kwargs) return wrapper return decorator @rate_limit(calls=5, period=1.0) def call_api(endpoint: str) -> dict: return {"endpoint": endpoint, "ok": True} Singleton from functools import wraps import threading def singleton(cls): instances = {} lock = threading.Lock() @wraps(cls, updated=[]) def get_instance(*args, **kwargs): if cls not in instances: with lock: if cls not in instances: # double-checked locking instances[cls] = cls(*args, **kwargs) return instances[cls] return get_instance @singleton class DatabasePool: def __init__(self, dsn: str = "sqlite:///:memory:"): self.dsn = dsn print(f"Создан пул: {dsn}") a = DatabasePool("postgresql://localhost/db") b = DatabasePool() # "Создан пул" не печатается второй раз print(a is b) # True Валидация типов import inspect from functools import wraps def validate_types(func): sig = inspect.signature(func) hints = func.__annotations__ @wraps(func) def wrapper(*args, **kwargs): bound = sig.bind(*args, **kwargs) bound.apply_defaults() for name, value in bound.arguments.items(): if name in hints and name != "return": expected = hints[name] if not isinstance(value, expected): raise TypeError( f"Параметр '{name}': ожидался {expected.__name__}, " f"получен {type(value).__name__}" ) return func(*args, **kwargs) return wrapper @validate_types def power(base: float, exp: int) -> float: return base ** exp power(2.0, 3) # OK power(2.0, 3.5) # TypeError: Параметр 'exp': ожидался int, получен float Асинхронные декораторы Декоратор не знает заранее, синхронная функция или async. Для универсального декоратора нужно проверять это явно. import asyncio import time import inspect from functools import wraps def timeit(func): @wraps(func) async def async_wrapper(*args, **kwargs): start = time.perf_counter() result = await func(*args, **kwargs) print(f"{func.__name__}: {time.perf_counter() - start:.4f}с (async)") return result @wraps(func) def sync_wrapper(*args, **kwargs): start = time.perf_counter() result = func(*args, **kwargs) print(f"{func.__name__}: {time.perf_counter() - start:.4f}с (sync)") return result # Выбираем обёртку один раз при декорировании (не при каждом вызове) return async_wrapper if inspect.iscoroutinefunction(func) else sync_wrapper @timeit def cpu_task(n: int) -> int: return sum(range(n)) @timeit async def io_task(delay: float) -> str: await asyncio.sleep(delay) return "done" cpu_task(10_000_000) asyncio.run(io_task(0.1)) Проверка inspect.iscoroutinefunction выполняется один раз при декорировании, а не при каждом вызове, что исключает лишние расходы в рантайме. Декораторы в контексте Python 3.13 и 3.14 В Python 3.13 появился @typing.deprecated для явной пометки устаревшего кода прямо в системе типов. В Python 3.14 аннотации стали отложенными (PEP 649): они не вычисляются при определении функции. Это означает, что декораторы, читающие func.__annotations__ напрямую (например, validate_types выше), теперь получат объект AnnotateFunc, а не уже вычисленный словарь. Для надёжной работы с аннотациями используйте inspect.get_annotations(func, eval_str=True): import inspect def validate_types(func): sig = inspect.signature(func) # eval_str=True вычисляет строковые аннотации и отложенные (3.14+) hints = inspect.get_annotations(func, eval_str=True) ... Шпаргалка — когда что использовать Задача Декоратор Управляемый атрибут @property Метод без self/cls @staticmethod Альтернативный конструктор @classmethod Автогенерация boilerplate @dataclass Абстрактный интерфейс @abstractmethod Ленивое кэширование атрибута @cached_property Мемоизация чистых функций @lru_cache / @cache Перегрузка по типу @singledispatch Вывод методов сравнения @total_ordering Пометить как устаревший @deprecated (3.13+) Явное переопределение метода @override (3.12+) Сохранить метаданные функции @wraps Полезные источники Официальная документация functools — docs.python.org/3/library/functools.html “What’s New In Python 3.13” — docs.python.org/3/whatsnew/3.13.html (про @deprecated, @override) “What’s New In Python 3.14” — docs.python.org/3/whatsnew/3.14.html (про отложенные аннотации PEP 649) Real Python — Primer on Python Decorators — realpython.com/primer-on-python-decorators/ freeCodeCamp — The Python Decorator Handbook — freecodecamp.org/news/the-python-decorator-handbook/ asyncmove.com — The Comprehensive Guide to Python Decorators (2026) — asyncmove.com/blog/2026/01/the-comprehensive-guide-to-python-decorators/ PEP 318 — декораторы функций и методов PEP 614 — расслабление грамматических ограничений на декораторы (3.9+) PEP 649 — отложенные аннотации (3.14) References Fancy Decorators - In this tutorial, you’ll look at what Python decorators are and how you define and use them. Decorat… The Python Decorator Handbook - freeCodeCamp - Python decorators provide an easy yet powerful syntax for modifying and extending the behavior of fu… functools — Higher-order functions and operations on callable … - The functools module is for higher-order functions: functions that act on or return other functions… Python Standard Library | collections | itertools | functools - Dev Genius - Python’s functools module, part of the standard library, provides higher-order functions and operati… Handy Python Decorators. Implementing and Using Advanced… - The Python Standard Library contains four incredibly useful decorators: staticmethod , classmethod ,… What’s New In Python 3.13 — Python 3.14.4 documentation - The biggest changes include a new interactive interpreter, experimental support for running in a fre… What’s New In Python 3.13 — Python 3.14.0rc3 documentation - Editors, Adam Turner and Thomas Wouters,. This article explains the new features in Python 3.13, com… Mastering Python Decorators for Code Reusability and Optimization - Discover how Python decorators can help you write reusable, efficient, and maintainable code by modi… The Comprehensive Guide to Python Decorators - Decorators are one of Python’s most powerful metaprogramming tools, widely used in the industry to w… What’s new in Python 3.14 — Python 3.14.4 documentation - This article explains the new features in Python 3.14, compared to 3.13. … no_type_check_decorator…
  • 2D/3D, движки (Unity, Unreal, Godot), геймдизайн, анимация! Создавайте проекты под PC, мобильные, консоли. Решайте ошибки, делитесь лайфхаками, изучайте тренды (VR, мультиплеер). Помощь новичкам и экспертные кейсы

    0 0
    0 Темы
    0 Сообщения
    Нет новых сообщений
  • обсуждение SQL, NoSQL (MySQL, PostgreSQL, MongoDB), Redis, проектирования БД, оптимизации запросов, администрирования. Решение проблем, бэкапы, репликация, безопасность данных. Советы по настройке, кейсы, обмен опытом.

    33 36
    33 Темы
    36 Сообщения
    AladdinA
    PRAGMA - это SQL-расширение, специфичное для SQLite. Это команда-«рычаг управления» движком: она позволяет читать и менять внутренние параметры базы данных (режим журналирования, размер кэша, поведение fsync, целостность схемы и многое другое). Синтаксически PRAGMA выглядит как обычный SQL, но работает иначе: -- Чтение параметра PRAGMA journal_mode; -- Установка параметра (две эквивалентные формы) PRAGMA journal_mode = WAL; PRAGMA journal_mode(WAL); -- С указанием схемы (для ATTACH-баз) PRAGMA main.journal_mode = WAL; PRAGMA temp.cache_size; Чем PRAGMA отличается от обычного SQL Свойство Обычный SQL PRAGMA Переносимость Стандарт SQL Только SQLite Обратная совместимость Гарантирована Не гарантирована Ошибка при опечатке Выдаётся Молча игнорируется Момент выполнения sqlite3_step() Может быть в sqlite3_prepare() ️ Важно: если допустить опечатку в названии PRAGMA (PRAGMA jouranl_mode = WAL), SQLite не выдаст ошибку - команда просто не выполнится. Всегда проверяйте возвращаемое значение. PRAGMA как табличные функции Начиная с SQLite 3.16.0, PRAGMA без побочных эффектов можно использовать в SELECT как табличные функции с префиксом pragma_: -- Через PRAGMA PRAGMA table_info('users'); -- Через функцию (можно в JOIN, WHERE, агрегатах) SELECT name, type FROM pragma_table_info('users') WHERE pk = 1; -- Пример: все проиндексированные колонки во всех таблицах SELECT DISTINCT m.name || '.' || ii.name AS indexed_col FROM sqlite_schema AS m, pragma_index_list(m.name) AS il, pragma_index_info(il.name) AS ii WHERE m.type = 'table' ORDER BY 1; Ключевые PRAGMA: обзор Производительность и кэш -- Размер кэша: положительное = страницы, отрицательное = KiB PRAGMA cache_size = -8000; -- ~8 МБ кэша PRAGMA cache_size; -- читаем текущее значение (по умолч: -2000) -- Размер страницы (только до первой записи!) PRAGMA page_size = 4096; -- Временные таблицы в RAM вместо диска PRAGMA temp_store = MEMORY; -- Memory-mapped I/O (0 = выключено) PRAGMA mmap_size = 268435456; -- 256 МБ Целостность и безопасность -- Проверка целостности базы PRAGMA integrity_check; PRAGMA integrity_check(10); -- первые 10 ошибок PRAGMA integrity_check('orders'); -- только таблица orders -- Быстрая проверка (без некоторых тестов, зато быстрее) PRAGMA quick_check; -- Внешние ключи (по умолчанию ВЫКЛЮЧЕНЫ!) PRAGMA foreign_keys = ON; PRAGMA foreign_key_check; -- Версия приложения (для идентификации формата файла) PRAGMA user_version = 3; PRAGMA user_version; Информация о схеме -- Колонки таблицы PRAGMA table_info('orders'); -- Индексы таблицы PRAGMA index_list('orders'); -- Подробности по конкретному индексу PRAGMA index_info('idx_user_id'); -- Все присоединённые базы PRAGMA database_list; -- Список всех PRAGMA PRAGMA pragma_list; Таймаут при блокировке -- Ждать 5 секунд вместо немедленного SQLITE_BUSY PRAGMA busy_timeout = 5000; Режимы журналирования (journal_mode) SQLite обеспечивает атомарность транзакций через журнал. Всего режимов шесть: Режим Описание Когда использовать DELETE Журнал удаляется при коммите. По умолчанию Простые однопользовательские сценарии TRUNCATE Журнал обрезается до 0 (не удаляется). Быстрее DELETE на некоторых ОС Альтернатива DELETE PERSIST Заголовок журнала перезаписывается нулями Оптимизация на платформах, где удаление файла дорого MEMORY Журнал только в RAM, нет fsync. Быстро, но нет durability Тесты, временные операции WAL Write-Ahead Log - изменения пишутся в отдельный файл Конкурентный доступ, большинство реальных приложений OFF Нет журнала вообще. Нет атомарности! Только bulk-import с полным контролем PRAGMA journal_mode; -- узнать текущий PRAGMA journal_mode = WAL; -- включить WAL, возвращает 'wal' при успехе PRAGMA journal_mode = DELETE; -- вернуться к стандартному Как работает WAL - механика Rollback Journal vs WAL: принципиальное отличие Rollback Journal (DELETE-режим): Перед изменением страницы - скопировать оригинал в журнал Записать изменения прямо в .db файл Коммит = удалить журнал Откат = восстановить из журнала в .db WAL (Write-Ahead Log): Оригинал в .db - не трогать Изменения дописать в конец .wal файла Коммит = записать специальную commit-запись в .wal Читатели работают с .db + нужный «срез» .wal Checkpoint = перенести WAL → .db ┌─────────────────────────────────────────────────────────────┐ │ Файлы на диске при WAL-режиме │ │ │ │ mydb.db ← основная база (стабильные данные) │ │ mydb.db-wal ← новые изменения (дописываются в конец) │ │ mydb.db-shm ← shared-memory индекс (wal-index) │ └─────────────────────────────────────────────────────────────┘ Как читатели видят данные Когда читатель открывает транзакцию, он фиксирует «end mark» - позицию последней commit-записи в WAL на этот момент. Все его чтения используют только данные до этой метки: сначала WAL (в обратном порядке, берётся последняя версия страницы), затем .db. Это обеспечивает снапшотную изоляцию без блокировки писателя. Checkpoint: возврат данных из WAL в .db Checkpoint - это операция переноса страниц из WAL обратно в основную базу. Она происходит автоматически (каждые 1000 страниц по умолчанию) или вручную. Режимы checkpoint’а: Режим Поведение Блокирует? PASSIVE Делает что может, не мешая другим. По умолчанию Нет FULL Ждёт завершения всех текущих писателей, затем checkpoint Ждёт писателей RESTART FULL + ждёт читателей, чтобы сбросить WAL с начала Ждёт всех TRUNCATE RESTART + физически обрезает файл .wal до 0 байт Ждёт всех PRAGMA wal_checkpoint; -- PASSIVE (по умолчанию) PRAGMA wal_checkpoint(FULL); -- ждёт писателей PRAGMA wal_checkpoint(RESTART); -- ждёт всех PRAGMA wal_checkpoint(TRUNCATE); -- + обрезает файл -- Возвращает 3 числа: (busy, log_pages, checkpointed_pages) -- busy=0 → checkpoint прошёл без блокировок -- log_pages == checkpointed_pages → WAL полностью перенесён WAL: включение и настройка Минимальный старт import sqlite3 conn = sqlite3.connect("mydb.db") # Включаем WAL - настройка персистентна (сохраняется между перезапусками) result = conn.execute("PRAGMA journal_mode = WAL").fetchone() print(result) # → 'wal' при успехе, или прежний режим при неудаче Оптимальная конфигурация для production import sqlite3 def get_connection(db_path: str) -> sqlite3.Connection: conn = sqlite3.connect(db_path, timeout=30) # WAL - основной режим conn.execute("PRAGMA journal_mode = WAL") # NORMAL: fsync только при checkpoint, безопасно для WAL # FULL = fsync на каждый коммит (медленнее, максимальная стойкость) conn.execute("PRAGMA synchronous = NORMAL") # Кэш ~32 МБ conn.execute("PRAGMA cache_size = -32000") # Временные таблицы в памяти conn.execute("PRAGMA temp_store = MEMORY") # 256 МБ memory-mapped reads conn.execute("PRAGMA mmap_size = 268435456") # Checkpoint раз в 500 страниц вместо 1000 conn.execute("PRAGMA wal_autocheckpoint = 500") # Ждать до 5 сек при блокировке conn.execute("PRAGMA busy_timeout = 5000") # Включить внешние ключи (по умолчанию выключены!) conn.execute("PRAGMA foreign_keys = ON") return conn Конфигурация synchronous с WAL -- OFF: нет fsync вообще. Быстро, но риск порчи при сбое питания PRAGMA synchronous = OFF; -- NORMAL: fsync только при checkpoint. Рекомендуется для WAL -- Потеря данных возможна только при сбое ОС, не при сбое приложения PRAGMA synchronous = NORMAL; -- FULL: fsync при каждом коммите и checkpoint PRAGMA synchronous = FULL; -- EXTRA: FULL + extra fsync на директорию (максимальная защита) PRAGMA synchronous = EXTRA; В WAL-режиме при synchronous=NORMAL данные не теряются при сбое приложения, но возможны потери при сбое ОС или питания. Это приемлемый компромисс для большинства приложений. Конкурентный доступ: как это реально работает import sqlite3 import threading DB = "shared.db" def setup(): conn = sqlite3.connect(DB) conn.execute("PRAGMA journal_mode = WAL") conn.execute("PRAGMA busy_timeout = 3000") conn.execute(""" CREATE TABLE IF NOT EXISTS events ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, ts TEXT DEFAULT (datetime('now')) ) """) conn.commit() conn.close() def writer(thread_id: int): # Каждый поток открывает своё соединение conn = sqlite3.connect(DB, timeout=10) conn.execute("PRAGMA journal_mode = WAL") conn.execute("PRAGMA busy_timeout = 3000") for i in range(50): conn.execute("INSERT INTO events(name) VALUES (?)", (f"t{thread_id}-e{i}",)) conn.commit() conn.close() def reader(): conn = sqlite3.connect(DB, timeout=10) conn.execute("PRAGMA journal_mode = WAL") # В WAL-режиме: читатель НЕ блокирует писателя и наоборот rows = conn.execute("SELECT COUNT(*) FROM events").fetchone() print(f"Читатель видит: {rows} записей") conn.close() setup() # Запускаем 4 писателя одновременно writers = [threading.Thread(target=writer, args=(i,)) for i in range(4)] for w in writers: w.start() # Читатель работает параллельно с писателями reader_thread = threading.Thread(target=reader) reader_thread.start() for w in writers: w.join() reader_thread.join() Ручной checkpoint def manual_checkpoint(db_path: str, mode: str = "FULL"): conn = sqlite3.connect(db_path) conn.execute("PRAGMA journal_mode = WAL") result = conn.execute(f"PRAGMA wal_checkpoint({mode})").fetchone() busy, log_pages, checkpointed = result print(f"Busy: {busy}") print(f"Pages in WAL: {log_pages}") print(f"Pages checkpointed: {checkpointed}") if log_pages == checkpointed: print("✓ WAL полностью перенесён в .db") else: print(f"⚠ Не перенесено {log_pages - checkpointed} страниц (есть активные читатели)") conn.close() manual_checkpoint("mydb.db", "TRUNCATE") Преимущества и ограничения WAL Преимущества Быстрее для большинства сценариев - записи sequential, нет двойной записи Конкурентность - читатели не блокируют писателя, писатель не блокирует читателей Меньше fsync() - уязвимость к broken fsync снижена Снапшотная изоляция - каждый читатель видит согласованный срез Ограничения Только на одной машине - WAL требует общей памяти (.shm), сетевые ФС не поддерживаются Один писатель - конкурентная запись невозможна, только последовательная Нельзя менять page_size после перехода в WAL Читаемость снижается при большом WAL - каждый читатель сканирует WAL для поиска страниц Дополнительные файлы - .wal и .shm должны храниться рядом с .db ATTACH + несколько баз - атомарность только внутри одной базы, не между ними WAL-reset bug (CVE-подобная проблема) В SQLite 3.7.0–3.51.2 существовал редкий race condition при двух одновременных checkpoint’ах, который мог привести к порче базы. Исправлено в версии 3.51.3 (2026-03-13). Если вы используете WAL с многопроцессным доступом - обновитесь. Когда НЕ использовать WAL # WAL НЕ подходит если: # 1. Сетевая файловая система (NFS, SMB, CIFS) conn = sqlite3.connect("//nas/share/mydb.db") # ❌ WAL сломается # 2. База открывается в read-only режиме без .shm файла # (решается через PRAGMA locking_mode=EXCLUSIVE или флаг immutable) # 3. Нужно менять page_size conn.execute("PRAGMA page_size = 8192") # нужно делать ДО WAL conn.execute("PRAGMA journal_mode = WAL") # после этого page_size не сменить # 4. Транзакции > 100 МБ на старых версиях SQLite < 3.11.0 # (на 3.11.0+ это ограничение снято) Диагностика и мониторинг WAL import sqlite3 def wal_status(db_path: str): conn = sqlite3.connect(db_path) mode = conn.execute("PRAGMA journal_mode").fetchone() sync = conn.execute("PRAGMA synchronous").fetchone() cache = conn.execute("PRAGMA cache_size").fetchone() page_size = conn.execute("PRAGMA page_size").fetchone() page_count = conn.execute("PRAGMA page_count").fetchone() auto_cp = conn.execute("PRAGMA wal_autocheckpoint").fetchone() fk = conn.execute("PRAGMA foreign_keys").fetchone() # Статус WAL cp = conn.execute("PRAGMA wal_checkpoint(PASSIVE)").fetchone() print(f"journal_mode: {mode}") print(f"synchronous: {sync} (0=OFF 1=NORMAL 2=FULL 3=EXTRA)") print(f"cache_size: {cache} pages") print(f"page_size: {page_size} bytes") print(f"page_count: {page_count}") print(f"db_size: {page_size * page_count / 1024:.1f} KB") print(f"wal_autocheckpoint: {auto_cp} pages") print(f"foreign_keys: {'ON' if fk else 'OFF'}") print(f"WAL checkpoint: busy={cp}, log={cp[^1]}, checkpointed={cp[^2]}") conn.close() wal_status("mydb.db") Полный шаблон: production-ready SQLite + WAL import sqlite3 from contextlib import contextmanager from pathlib import Path class Database: def __init__(self, path: str | Path): self.path = str(path) self._init_db() def _make_conn(self) -> sqlite3.Connection: conn = sqlite3.connect(self.path, timeout=30) conn.row_factory = sqlite3.Row conn.execute("PRAGMA journal_mode = WAL") conn.execute("PRAGMA synchronous = NORMAL") conn.execute("PRAGMA cache_size = -32000") # ~32 MB conn.execute("PRAGMA temp_store = MEMORY") conn.execute("PRAGMA mmap_size = 134217728") # 128 MB conn.execute("PRAGMA foreign_keys = ON") conn.execute("PRAGMA busy_timeout = 5000") conn.execute("PRAGMA wal_autocheckpoint = 1000") return conn def _init_db(self): with self._make_conn() as conn: conn.execute(""" CREATE TABLE IF NOT EXISTS items ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, value REAL, created TEXT DEFAULT (datetime('now')) ) """) conn.commit() @contextmanager def connection(self): conn = self._make_conn() try: yield conn conn.commit() except Exception: conn.rollback() raise finally: conn.close() def checkpoint(self, mode: str = "PASSIVE") -> dict: with self.connection() as conn: busy, log, done = conn.execute( f"PRAGMA wal_checkpoint({mode})" ).fetchone() return {"busy": busy, "log_pages": log, "checkpointed": done} # Использование db = Database("app.db") with db.connection() as conn: conn.execute("INSERT INTO items(name, value) VALUES (?, ?)", ("test", 3.14)) print(db.checkpoint("FULL")) Шпаргалка: наиболее используемые PRAGMA -- === ОБЯЗАТЕЛЬНО при старте соединения === PRAGMA journal_mode = WAL; -- WAL-режим (персистентен) PRAGMA synchronous = NORMAL; -- баланс скорость/надёжность для WAL PRAGMA foreign_keys = ON; -- внешние ключи (выкл. по умолчанию!) PRAGMA busy_timeout = 5000; -- не падать сразу при блокировке -- === ПРОИЗВОДИТЕЛЬНОСТЬ === PRAGMA cache_size = -32000; -- 32 МБ кэша PRAGMA temp_store = MEMORY; -- временные таблицы в RAM PRAGMA mmap_size = 134217728; -- 128 МБ memory-mapped I/O -- === НАСТРОЙКА WAL === PRAGMA wal_autocheckpoint = 1000; -- авто-checkpoint каждые N страниц PRAGMA wal_checkpoint(PASSIVE); -- мягкий checkpoint PRAGMA wal_checkpoint(TRUNCATE); -- checkpoint + обрезать .wal файл -- === ДИАГНОСТИКА === PRAGMA integrity_check; -- полная проверка базы PRAGMA journal_mode; -- текущий режим PRAGMA page_size; -- размер страницы PRAGMA page_count; -- число страниц PRAGMA table_info('tbl'); -- колонки таблицы PRAGMA index_list('tbl'); -- индексы таблицы PRAGMA database_list; -- все attach'нутые базы References Pragma statements supported by SQLite PRAGMA - Using SQLite [Book] - NamePRAGMA - Look up or modify an SQLite configurationSyntaxCommon UsagePRAGMA page_size; PRAGMA cac… Pragma statements supported by SQLite PRAGMA System | sqlite/sqlite | DeepWiki - The PRAGMA system provides runtime configuration and introspection capabilities for SQLite databases… Write-Ahead Logging - SQLitesqlite.org › wal
  • WordPress, Joomla, MODX, Headelss CMS, Payload CMS, NodeBB! Создание сайтов, темы, плагины, SEO-оптимизация, безопасность, интеграция с API. Решайте ошибки, делитесь лайфхаками, изучайте обновления. Помощь новичкам и экспертные кейсы.

    10 22
    10 Темы
    22 Сообщения
    D
    Классный материал, читается как живой опыт, а не переведённая дока — прям чувствуется, что все эти команды реально прожиты в бою. Особенно понравились кейсы с проблемными плагинами и reset -p: как раз то, что обычно гуглишь в панике, когда форум уже лежит. После такого гайда хочется почти всё управление NodeBB унести в CLI и вообще не заходить в админку лишний раз.
  • обсуждение CI/CD, автоматизации, облаков (AWS, Azure), Docker, Kubernetes, мониторинга и IaC. Обмен опытом, решение задач, лучшие практики. Советы по инструментам (Ansible, Terraform), кейсы, оптимизация workflows

    33 76
    33 Темы
    76 Сообщения
    MugiwaraM
    Bash запускается в разных режимах — и от этого зависит какие файлы он читает при старте 4 режима bash Login shell (интерактивный, с входом) Как запускается: SSH-сессия без команды, su - user, bash -l Читает по порядку: /etc/profile └── ~/.bash_profile ← первый найденный из трёх: └── ~/.bash_login └── ~/.profile При выходе читает ~/.bash_logout. # Примеры: ssh user@server # интерактивная ssh-сессия bash -l # явно запустить login shell su - admin # переключиться с login Interactive shell (интерактивный, без входа) Как запускается: новое окно терминала, вкладка, просто набрать bash Читает: /etc/bash.bashrc (на Debian/Ubuntu) ~/.bashrc # Примеры: bash # запустить дочерний bash xterm # открыть новый терминал tmux / screen # новое окно Non-interactive, non-login ← самый частый источник проблем Как запускается: ssh user@host "команда", запуск скрипта через bash script.sh Читает: ничего # Примеры — ничего не работает: ssh user@host "pm2 restart app" # PATH пустой bash deploy.sh # nvm/fnm недоступны cron jobs # тоже сюда Non-interactive login shell Как запускается: bash -lc "команда", ssh user@host bash -lc "..." Читает: ~/.bash_profile (и цепочку из п.1) # Примеры — работает если настроен bash_profile: ssh user@host 'bash -lc "pm2 restart app"' # ✅ bash -lc "node --version" # ✅ Полная таблица Режим Пример запуска /etc/profile ~/.bash_profile ~/.bashrc Login interactive ssh user@host Non-login interactive Открыть терминал Non-interactive non-login ssh user@host "cmd" Non-interactive login bash -lc "cmd" Типичная схема настройки Именно поэтому рекомендуют делать так: ~/.bash_profile └── source ~/.bashrc ← подтягивает всё из bashrc в login-сессии Тогда и интерактивные терминалы (~/.bashrc), и SSH-деплой через bash -lc (~/.bash_profile) видят одно и то же окружение. Порядок чтения ~/.bash_profile — важный нюанс Bash ищет первый существующий файл из трёх и читает только его: 1. ~/.bash_profile ← если есть — читается, остальные игнорируются 2. ~/.bash_login ← если нет bash_profile 3. ~/.profile ← если нет двух предыдущих На Ubuntu ~/.bash_profile обычно отсутствует → читается ~/.profile. На macOS — есть ~/.bash_profile. Применительно к деплою # ❌ Не работает — режим 3, читает ничего ssh "$SERVER" "pm2 restart app" # ✅ Работает — режим 4, читает ~/.bash_profile ssh "$SERVER" 'bash -lc "pm2 restart app"' # ✅ Работает — если настроил ~/.bash_profile → source ~/.bashrc # и в ~/.bashrc прописан fnm/nvm
  • Операционные системы, кроссплатформенные программы, системы. Unix, Linux, Windows, MacOS и т д.

    52 112
    52 Темы
    112 Сообщения
    kirilljsxK
    Поддержка проекта: сервер + развитие https://t.tb.ru/pm_short/7AMOPf5D1a9
  • Всё о маркетинге: от SMM и контента до аналитики и продвижения. Практика, теория, свежие тренды — обмениваемся опытом!

    56 125
    56 Темы
    125 Сообщения
    kirilljsxK
    Дзен опять переписал правила игры, и на этот раз удар пришёлся по нишевым авторам и небольшим B2B-каналам. За последние недели я заметил в своём окружении волну жалоб: reach упал на 30-60%, монетизация встала, а алгоритм вообще не берёт новый контент. Не паника - это не ошибка платформы, это её эволюция. И она очень показательна для всех, кто зарабатывает на контенте про нишевые услуги. Что именно сломалось в алгоритмах Дзена Платформа окончательно отказалась от модели “много подписчиков = много охватов”. Теперь Дзен смотрит совсем на другие сигналы: 1. Глубина вовлечённости вместо кликов Ранее алгоритм радовался любому клику - пользователь открыл, посмотрел превью, ушёл. Теперь платформа считает время на странице, дочитывания до конца и самое важное - возвращается ли юзер к следующему материалу автора. Если вы пишете про установку мини-АТС для офиса, а читатели открыли, прочитали 15% и ушли - алгоритм отправляет материал в “морозилку”. 2. Поведенческие аномалии как красный флаг Видите скачок активности без исторической логики? Алгоритм видит. Если у вас обычно 2-3% дочитываний, но вдруг один материал привлёк 15% - система это заметит и отправит на ручную проверку. Для нишевых каналов это особенно опасно, потому что любой вирусный момент воспринимается как аномалия. 3. Контекстная релевантность перед количеством Дзен теперь показывает материал тестовой группе похожей аудитории. Если реакция хорошая - расширяет охват. Если плохая - замораживает. Для услуговых ниш (консультации, B2B-решения) это значит, что контент должен быть максимально заточен под точную боль целевой аудитории, а не просто “интересным”. Почему reach упал именно на нишевых сервисах Если вы пишете про SEO, коучинг, юридические услуги или IT-консультации, вот что произошло: Монетизация видео отключена (с 14 апреля). Если ваш канал в основном зарабатывал на видеороликах - сожалею. Нужно переходить на текст и микровидео в форме Reels. Алгоритм требует доказательства стабильности. Раньше можно было запустить канал, выложить 5 статей и уже зарабатывать. Теперь нужно минимум несколько месяцев системной работы, чтобы платформа включила вас в рекламную сеть. Рерайты и “потоковый контент” убиты. Если вы брали чужие идеи и переписывали под себя - алгоритм это видит и штрафует. Для B2B-ниш это особенно актуально, потому что все пишут про одно и то же. Как восстановить трафик: практическая схема Шаг 1: Переформатируй под поведенческие сигналы Твой материал про “5 способов оптимизировать логистику” должен быть написан так, чтобы читатель дочитал до конца. Вот структура, которая работает: Заголовок с острой болью (не общий, а конкретный: “Почему ваша логистика теряет 30% на холодной цепи”) Первые 2-3 абзаца - ответ на вопрос, а не теория Подзаголовки каждые 150-200 слов (алгоритм видит структуру) Практический пример или расчёт (конкретные цифры, а не размытые советы) Чек-лист в конце, который читатель может применить сейчас же Это увеличивает dwell time на 40-60% против стандартных “7 советов как…”. Шаг 2: Собери микроаудиторию из своей целевой ниши Не гонись за подписчиками. Вместо этого: Пиши 2-3 раза в неделю про острые проблемы вашей аудитории Оставляй вопрос в конце каждого материала, который провоцирует комментарии (не просто “что вы думаете?”, а конкретный: “А вы учитываете стоимость возврата товара при расчёте логистики? Напишите ваш процент в комментариях”) Отвечай на каждый комментарий в течение часа Это формирует сигнал “вовлечённая аудитория”, который алгоритм любит больше, чем пассивные подписки. Шаг 3: Тестируй форматы и копируй то, что работает На Дзене разные форматы резко отличаются по поведенческим сигналам: Формат Среднее время на странице Вероятность дочитывания Проблема для ниш Статья 1500+ слов 3-4 мин 35-45% Требует экспертизы, долгая раскачка Видео 3-5 мин 2-3 мин 60-70% Монетизация отключена, нужна воронка на услугу Микровидео (0:30-1:00) 45-60 сек 80%+ Идеально для нишевых лайфхаков, высокий reach Карусель (5-10 слайдов) 2-3 мин 50-60% Хороший баланс, но требует дизайна Для B2B-ниш рекомендую: микровидео (лайфхак/ошибка) + статья (глубокое погружение) + карусель (чек-лист). Так вы ловите разные типы поведения. Шаг 4: Оптимизируй под голосовой поиск и контекст Дзен сказал, что будет учитывать голосовые запросы. Для нишевых услуг это значит: Пиши заголовки так, как люди бы их спросили (не “Оптимизация затрат на доставку”, а “Как снизить расходы на логистику на 20%?”) Используй природный язык в первом абзаце - это помогает голосовому поиску и читаемости Включай 2-3 вопроса, на которые отвечает твой материал, в тексте Честная оценка: будет ли работать на российском рынке Да, будет. Но с оговоркой. Дзен сейчас напрямую конкурирует с Google и Яндексом за роль “поисковика для контента”. Этот алгоритмический поворот - признание того, что пользователи ищут не просто информацию, а решения. Для B2B-ниш (консультирование, SaaS, услуги) это даже выгодно - потому что такая аудитория более осознанная и готовая к конверсии. Проблема в том, что условиями игры теперь управляет платформа, а не авторы. Вчера отключили монетизацию видео - завтра вдруг могут потребовать верификацию или ID. Это риск для тех, кто сильно зависит от Дзена как от единственного источника трафика. Итог: если вы в нишевом сегменте, Дзен всё ещё инструмент, но он требует системности, экспертизы и готовности адаптироваться к его капризам. Быстрого заработка больше нет - только долгосрочная работа на репутацию. Вопрос для вас: как вы адаптировались под новые алгоритмы? Ваш reach упал или вырос? Может быть, вы заметили что-то, чего я пропустил в этой схеме?
  • 0 Темы
    0 Сообщения
    Нет новых сообщений
  • Сообщество, делимся опытом, работой, задачами для своих пет проектов

    1 2
    1 Темы
    2 Сообщения
    AladdinA
    Для nodebb искал плагины и библиотеки для SSO VK. Пришлось писать плагин без passport, Неплохо бы написать более универсальное решение
  • IT-приколы, мемы про разработчиков, программистские баги и гифки. Обсуждаем смешные кейсы, шутки про искусственный интеллект, криптовалюты, GitHub и Reddit. Делитесь своими мемами, находите единомышленников, отдыхайте с пользой

    9 79
    9 Темы
    79 Сообщения
    kirilljsxK
    [image: 1775489982781-chnsyynhvpwk1gut4iskwjintuqtc0f-gx2h2gctb1e.gif]