RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / user-633777

Sovok's questions

Martin Hope
Sovok
Asked: 2024-10-08 17:40:20 +0000 UTC

为什么apscheduler长时间不工作?

  • 5

我正在 aiogram 3 上制作一个电报机器人。注册用户后,我需要在 3 天后延迟向用户发送消息。在测试期间,我将时间增量设置为 10 秒,然后在生产中一切正常;当我将时间增量设置为 3 天时,调度程序根本不工作,并且任务从 redis 作业存储中完全删除。应该执行该函数的时间。

初始化调度程序:

# Внешние библиотеки
from apscheduler.jobstores.redis import RedisJobStore
from apscheduler.schedulers.asyncio import AsyncIOScheduler

# Инициализация редис, куда будет сохраняться рассылки
jobstores = {"default": RedisJobStore(host="localhost", port=6379, db=3)}

调度器模块:

# Стандартные библиотеки
import asyncio
from datetime import datetime
import json

# Внешние библиотеки
from aiogram.fsm.storage.base import StorageKey
from aiogram import F, Router
from aiogram.fsm.context import FSMContext
from aiogram.types import FSInputFile

router = Router() 
message_queue = asyncio.Queue()

# Функция-работник для отправки сообщений из очереди
async def message_sender_worker(redis_middleware):
    while True:
        user_id = await message_queue.get()
        try:
            # Создаем ключ и контекст состояния для пользователя
            key = StorageKey(bot_id=bot.id, chat_id=user_id, user_id=user_id)
            state = FSMContext(storage=dp.storage, key=key)

            # Получаем язык пользователя из Redis
            user_lang = await redis_middleware.get(f"user_lang:{user_id}")
            user_lang = user_lang if user_lang else "ru"  # По умолчанию русский
            
            # Отправляем сообщение, передавая актуальный язык пользователя
            await send_scheduled_message(user_id, state=state, user_lang=user_lang)
        except Exception as e:
            logger.error(f"Ошибка при отправке сообщения пользователю {user_id}: {e}")
        finally:
            message_queue.task_done()
        
        # Задержка для соблюдения лимитов Telegram
        await asyncio.sleep(0.05)


# Функция для отправки запланированного сообщения пользователю
async def send_scheduled_message(user_id, state: FSMContext, user_lang):
    print("Функция отправки через 3 дня запущена")

    # Получаем данные пользователя из базы данных
    role = await db.get_role_user(user_id)
    role = role[0]

    country = await db.get_country_user(user_id)
    country = country[0]

    await state.update_data(country_delay = country)
    await state.update_data(role_delay = role)

    if not role and country:
            logger.warning(f"Не найдены данные для пользователя {user_id}")
            return

    # Отправляем первоначальное сообщение
    await bot.send_message(chat_id=user_id, text=post_msg.after_3_days[user_lang])
    logger.info(f"Отправлено сообщение через 3 дня - {user_id}")
    await asyncio.sleep(2)

    # Обрабатываем страну, если нужно
    country_processed = await wrap_half_words_in_percent(country)
    if role in ["Роль1", "Роль2", "Роль3", "Роль4",]:
        await asyncio.sleep(1)
        await bot.send_message(
            chat_id=user_id,
            text=post_msg.get_photo_form["region"][user_lang],
            reply_markup = await reply_regions(country_processed)
        )
        await asyncio.sleep(3)
        # Устанавливаем состояние пользователя
        # state = FSMContext(storage=dp.storage, user=user_id, chat=user_id)
        await state.set_state(GetPhotoRegion.polling_station)
    else:
        await asyncio.sleep(1)
        # doc_path = "send_docs/Права избирателя.docx"
        doc_path = service_msg.agitator_patch_doc[user_lang]
        doc_file = FSInputFile(path=doc_path)
        await bot.send_document(chat_id=user_id, document=doc_file)
        await asyncio.sleep(1)
        await bot.send_message(chat_id=user_id, text=post_msg.agitator_form["send_link"][user_lang])
        
        # Устанавливаем состояние пользователя
        # state = FSMContext(storage=dp.storage, user=user_id, chat=user_id)
        await state.set_state(AgitatorForm.waiting_for_links)
        await asyncio.sleep(2)


# Функция для планирования добавления пользователя в очередь сообщений
def schedule_message(user_id, send_time):
    scheduler.add_job(
        add_user_to_queue,
        'date',
        run_date=send_time,
        args=[user_id]
    )

# Функция для добавления пользователя в очередь сообщений
async def add_user_to_queue(user_id):
    await message_queue.put(user_id)

一段带有注册的代码。这里我向调度程序添加一个任务:

@router.callback_query(
    UserStates.FINISH_AUTH, F.data.in_(["confirm_yes", "confirm_no"])
)
async def finish_auth(callback_query: CallbackQuery, state: FSMContext, user_lang):
    if callback_query.data == "confirm_yes":
        # Добавляем данные в базу данных
        data = await state.get_data()
        tg_id = str(callback_query.from_user.id)
        await add_user_db(
            data["name"], data["phone"], tg_id,
            data["email"], data["country"], data["locality"], data["role"]
        )

        # Планируем отправку сообщения через 3 дня
        send_time = datetime.now() + timedelta(days=3)
        #send_time = datetime.now() + timedelta(seconds=10)
        schedule_message(tg_id, send_time)
        logger.info("Запланировано отправление сообщения через 3 дня")

        # Отправляем подтверждение пользователю
        await callback_query.message.answer(
            reg_msg.finish_msg[user_lang], reply_markup=await keyboard.start_quiz(user_lang)
        )
        logger.info(f"Пользователь с TG_ID - {tg_id} зарегистрировался")
        await state.clear()
    else:
        await callback_query.message.answer(reg_msg.name[user_lang])
        await state.set_state(UserStates.WAITING_FOR_NAME)
    await callback_query.answer()
python
  • 1 个回答
  • 33 Views

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5