• Как раздавать уникальные записи таблицы во многопоточном парсере?

    @Akina
    Сетевой и системный админ, SQL-программист.
    parsed - 0 - страница еще не спаршена, 1 - страница спаршена.

    Не так.

    NULL - не парсилась.
    0 - парсинг выполнен.
    >0 - взято на парсинг соединением (функция CONNECTION_ID()) номер N.

    Соответственно попробовать зарезервировать запись на парсинг:
    UPDATE urls 
    SET parsed = CONNECTION_ID()
    WHERE parsed IS NULL
    ORDER BY datetime_added LIMIT 1;

    Получить зарезервированную запись и начать её парсинг:
    SELECT *
    FROM urls
    WHERE parsed = CONNECTION_ID();

    Если вернётся более одной записи - в системе большие проблемы, надо звать администратора задачи. Если пустой набор - значит, запись перехватили, пробуем резервировать заново (тоже, кстати, повод позвать админа задачи - так не должно быть). Иначе - парсим полученную запись.

    По окончании парсинга соответственно
    UPDATE urls 
    SET parsed = 0
    WHERE parsed = CONNECTION_ID();

    Ну и периодически выполняется event procedure, который находит записи, формально помеченные как обрабатываемые, но, судя по времени, обработчик подвис. Такие записи возвращаются на обработку
    CREATE EVENT clear_parsing_flag
    ON SCHEDULE EVERY 1 MINUTE
    DO
    UPDATE urls
    SET parsed = NULL
    WHERE parsed > 0
        -- считаем, что 5 минут более чем достаточно
      AND datetime_start_parsed < CURRENT_TIMESTAMP - INTERVAL 5 MINUTE;


    Само собой никаких пулов соединений, никаких открыть-закрыть - все операции выполняются в рамках одного persistent connection. Автовосстановление соединения при обрыве также запрещено.

    Если соединение развалилось, неважно по какой причине, бросаем обрабатываемую запись (шедулер вернёт её в необработанные), соединяемся заново и начинаем с самого начала, с резервирования.

    Ну и предусмотреть случай, когда записей на парсинг просто нет. Например, если 5 резервирований подряд не смогли получить запись на обработку, то, чтобы не ставить сервер раком, вводим между попытками резервирования задержку, например, на 5 секунд... ну и вываливаем баннер, что, походу, парсить нечего.
    Ответ написан
    Комментировать
  • Как сделать decode только в mysql запросе?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    1 комментарий
  • Как правильно хранить дату в БД Laravel?

    delphinpro
    @delphinpro Куратор тега PHP
    frontend developer
    Вы храните дату в нулевом часовом поясе (Z в конце)
    Javascript приводит дату в ваше локальное время. То есть московское, плюс три часа от исходной даты. Всё правильно.

    UPD
    Уточню, что в timestamp все же хранится метка времени, простой int. Но извлекается из базы это значение уже с учетом часового пояса системы, на которой установлена БД, часового пояса заданного в настройках БД (SET time_zone) или для текущей сессии (set @@session.time_zone).
    Ну и php может поколдовать с поясами. У вас по-видимому в настройках указан нулевая таймзона, вот и время извлекается в ней.
    Ответ написан
    3 комментария
  • Как сделать так, чтобы если человек заходил с одного бразера - показывалось одно, а с другого браузера - другое?

    alexey-m-ukolov
    @alexey-m-ukolov Куратор тега PHP
    Давайте сделаем что-нибудь полезное. К примеру, определим, какой браузер использует тот, кто смотрит в данный момент нашу страницу. Для этого мы проверим строку с именем браузера, посылаемую нам в HTTP-запросе. Эта информация хранится в переменной. Переменные в PHP всегда предваряются знаком доллара. Интересующая нас в данный момент переменная называется $_SERVER['HTTP_USER_AGENT'].

    https://www.php.net/manual/ru/tutorial.useful.php
    Ответ написан
    Комментировать
  • Почему тут выдает ошибку: syntax error at or near "WITH"?

    rozhnev
    @rozhnev Куратор тега SQL
    Fullstack programmer, DBA, медленно, дорого
    WITH RECURSIVE tmp AS (
        SELECT REPORT_DATE rdate FROM ODK_INT_rep_p2 WHERE ODK_INT_rep_p2id IN ( 
        SELECT nvl((SELECT ODK_INT_rep_p2id FROM ODK_INT_rep_p2 WHERE TYPE = 2 AND report_date = (SELECT report_date FROM ODK_INT_rep_p2 WHERE ODK_INT_rep_p2id = (SELECT max(ODK_REP_P2ID) FROM odk_svodka_skc2))),
           (SELECT ODK_INT_rep_p2id FROM ODK_INT_rep_p2 WHERE TYPE = 2 AND report_date = (SELECT report_date 
            FROM ODK_INT_rep_p2 WHERE ODK_INT_rep_p2id = (SELECT max(ODK_INT_rep_p2id) AS ODK_INT_rep_p2id 
            FROM ODK_INT_rep_p2 WHERE TYPE = 1 AND trunc(report_date)= trunc(current_timestamp))))) AS id1
             FROM
     dual)),
     WITH cte_months (day) AS (	
    ...   
     )
    Ответ написан
    Комментировать
  • Как максимально оптимизировать (ужать) много картинок JPG (JPEG) с сохранением качества, особенно CMYK?

    hint000
    @hint000
    у админа три руки
    Если с удобным интерфейсом, то irfanView, в нём команда batch conversion (пакетная конвертация).
    Если не боитесь с консольным разбираться, то смотрите imageMagick.
    Ответ написан
    2 комментария
  • Запрещены ли вопросы с просьбами о code review?

    @mkone112
    Начинающий питонист.
    Хочется понять политику ресурса

    А она есть?
    Собственно, непонятна логика удаления.

    А ее нет, правила написаны таким образом что 99% вопросов в них не вписывается, а потому его удаление вопрос случая.
    Ответ написан
    Комментировать
  • Какие аналоги fetch есть в PHP?

    sergiks
    @sergiks Куратор тега PHP
    ♬♬
    Три популярных способа выполнять веб-запросы в PHP:
    1. file_get_contents() – не самый удобный, но не требует установки зависимостей т.к. является частью ядра PHP
    2. curl – PHP должен быть собран с этой библиотекой, чаще всего на хостингах так и есть по умолчанию.
    3. Guzzle HTTP – устанавливается через Composer и значительно упрощает работу с запросами


    В PHP запросы чаще выполняют синхронно, без событий-промисов, хотя такая возможность и появилась.
    Выполнили запрос – дождались ответа. В следующей строчке работаете с полученным ответом.
    Ответ написан
    Комментировать
  • Как отменить экранирование в python?

    drygdryg
    @drygdryg
    Python-разработчик
    Просто добавьте ещё один обратный слэш:
    if '/' not in msg.text or '\\' not in msg.text or '|' not in msg.text:

    или используйте "сырую" строку (raw string) — интерпретатор не будет обрабатывать экранирующие символы внутри неё:
    if '/' not in msg.text or r'\' not in msg.text or '|' not in msg.text:
    Ответ написан
    Комментировать
  • Как показывать свое сообщениe, когда команда psql завершается с ошибкой?

    CityCat4
    @CityCat4
    Внимание! Изменился адрес почты!
    В отдельных случаях не только можно, но и нужно.
    какая-то команда
         if [ $? -ne 0 ]; then
           echo "Что-то пошло не так"
         fi

    Разумеется, если выполненная "какая-то команда" выставляет код возврата
    Ответ написан
    2 комментария
  • Разработать REST API - как изучать?

    sergiks
    @sergiks Куратор тега PHP
    ♬♬
    1. понимать, как устроены веб запросы (чем GET принципиально отличается от POST и PUT)
    2. уметь спланировать и создать таблицу в базе данных
    3. работать с базой данных в PHP: подключаться, вставлять новые записи, находить существующие
    4. принимать и обрабатывать веб-запросы на PHP, фильтровать и валидировать данные. Возвращать ответы и сообщать о возможных ошибках.
    5. узнать, что все эти задачи – типовые, часто востребованные, и поэтому есть масса готовых решений – и научиться их находить и использовать
    Ответ написан
    9 комментариев
  • Как передать переменную из одной функции в другую?

    @dmshar
    Вопрос не имеет никакого отношения к написанию ботов вообще, ни к telegram в частности. Вопрос имеет отношения к Python, его основам, а так-же к необходимости его изучения.
    Для передачи значений между функциями ВСЕГДА И ВЕЗДЕ существует ТРИ способа.
    1. Классический: в общей вызывающей программе создаете переменную, которую передаете как параметр в обе функции. В одной из этих функций эта переменная заполняется значением, в другой - читается и используется.
    2. Нерекомендуемый: через глобальную переменную.
    3. Для очень сложных систем: через внешний файл.
    Все.
    Вот и выбирайте тот из них, который вам подходит больше.
    Ответ написан
    Комментировать
  • Зачем задавать приватный модификатор доступа для свойств класса?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    У вас очень логичный вопрос на счет сеттера: сеттер полностью уничтожает задумку с инкапсуляцией. Правильно это называется "семантическое нарушение инкапсуляции" — то есть как-бы мы инкапсулировали, но по факту назад открыли прямую запись в свойство напрямую. Все доводы "ну мы можем в сеттере валидировать" не корректны

    Правильным способом будет не использовать сеттеры. Вот моя статья на эту тему:
    https://habr.com/ru/post/469323/

    Более подробно: каждый класс нужно проектирвовать так, чтобы данные внутри были максимально связаны. Например каждый метод работать должен в хорошем случае с максимальным числом полей класса, тогда у него высокий cohesion... В тоже время снаружи наужно работать с максимальн омалым числом метода, тогда будет низкая связанность (coupling). Это пара принципов из GRASP.
    Когда вы делаете сеттеры и геттеры, то у вас данные внутри между собой почти никак не взаимодействут: с геттером работают снаружи, с сеттером работаю снаружи — весь класс нараспашку, а в нем в 100% случаев появляются данные, которые вместе не должны находиться и никак не связаны — анрушена и абстракция и инвариант и много чего еще...

    Про инвариант отдельно: например есть платеж, у него есть значение, с которым платеж инициирвоан (initValue), есть значение холда (holdAmount) и есть значение чарджа на списание (chargeAmount)
    Когда вы работаете с платежом, контролируя ивнариант в самом классе, то ваш каждый метод првоеряет др значения и позволяет перейти к др состоянию... методов будет 2-3, все инкапсулировано и безопасно.

    Например:
    class Payment {
         pub func charge(amount int) void {
              if (this.holdAmount < amount && this.initAmount < amount) {
                   throw new PaymentException('Unavailable charge amount')
              }
    
               if (this.status === PaymentStatus:finish) {
                   throw new PaymentException('Payment already fisnished')
              }
    
              this.chargeAmount = amount
              this.holdAmount -= amount
              this.status = PaymentStatus:finish
         }
    }


    Тут в одном методе полные проверки и класс сам контролирует все состояние внутри, также соблюдается закон Деметры. У даннго кода высокий cohesion (из GRASP), тк внутри идет плотная работа с внутр данными (значит они корректно тут закроекны) и низкий coupling ( с теми данными для данного кейса только один метод работы, все внутри)

    Когда вы раскроете сеттерами и геттерами, то ваше состояние становится непредсказуемо и полагается только на то, что снаружи точно подумали об инварианте (нет)
    Ответ написан
    23 комментария
  • Зачем задавать приватный модификатор доступа для свойств класса?

    Adamos
    @Adamos
    class VeryOpenOne
    {
    public $property;
    }
    $voo = new VeryOpenOne();
    $name = 'pro' . 'perty';
    $voo->$name = 'Пытаясь отрефакторить тот класс, ' .
      'ты хрен найдешь, что в этой строчке меняется эта переменная. ' .
      'Никакое самое умное IDE не поможет';
    Ответ написан
    1 комментарий
  • Возможно ли вывести ячейку mySQL по отрывку слова в ней через php?

    rozhnev
    @rozhnev Куратор тега PHP
    Fullstack programmer, DBA, медленно, дорого
    Для выбора строк по части строки используйте оператор LIKE.
    Для предотвращения SQL-инъекций используйте подготовленные операторы

    $gorod = 'Moscow';
    $query = "SELECT * FROM my WHERE gorod LIKE ?";
    
    // get DB data using PDO
    $stmt = $pdo->prepare($query);
    
    $filter = "%$gorod%";
    $stmt->execute([$filter]);
    
    $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
    
    print_r($rows);


    PHP editor online
    Ответ написан
    4 комментария
  • Как еще можно реализовать "внутреннее API" в веб-приложении, кроме как через ООП или HTTP?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Да, собственно, как угодно. Через очереди сообщений, сокеты Unix, вебсокеты, самописный протокол...
    Ответ написан
    4 комментария
  • Как отправить запрос по API, запустив скрипт из консоли?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Так у вас в скрипте ни чего не выводится, что он может вернуть?
    Ответ написан
    5 комментариев
  • Как вставлять картинки через код css?

    @alexalexes
    Вы пытаетесь работать с CSS как с шаблоном - для этого нужно использовать препроцессор CSS такие как Sass, Stylus, Less.
    Если у вас учебный проект, то это отдельная глава или даже раздел для набивания навыков и шишек.
    Если проект боевой и довольно простой, то можно не ввязываться в дебри динамической генерации стилей, условится, что статичные свойства стилей вы записываете в файлах CSS, а динамические - в html вставками:
    <style>
      .user-114__avatar
    {
       background-image: url({{thumbnail}});
    }
    </style>
    ...
    <!-- какие-то общие стили для аватара прописаны в классе user__avatar в файле css, а изменяемые прямо в HTML-->
    <div class="user__avatar user-114__avatar">
    </div>

    или инлайн-стилями:
    <!-- какие-то общие стили для аватара прописаны в классе user__avatar в файле css, а изменяемые прямо в инлайн-атрибуте тега-->
    <div class="user__avatar" style="background-image: url({{thumbnail}});">
    </div>

    PS: Тег img некорректно использовать без src, фон в нем может выступать только дополняющим свойством, например, закрывать прозрачные участки картинки src. И с фоновым изображением придется работать по-другому, чтобы привести в порядок адаптивность элемента.
    Ответ написан
    3 комментария
  • Как улучшить код, который проверяет наличие элемента в массиве и его значение?

    @Vitsliputsli
    Не нужно ничего сокращать. Код вполне краток и понятен. Дальнейшие сокращения лишь ухудшат читаемость.
    Но если хочется поговнокодить можно взять empty.
    Ответ написан
    5 комментариев