greenlet_spawn has not been called
greenlet_spawn has not been called; can't call await_only() here. Was IO attempted in an unexpected place? (Background on this error at: https://sqlalche.me/e/20/xd2s)
вот так выглядит ошибка а вот код
@connection
async def check_subscriptions(session, bot: Bot):
while True:
now = datetime.now()
seven_days_ago = now - timedelta(days=7)
print(f"\n--- Проверка подписок начата. Время: {now} ---")
try:
# Получаем все записи TaskCompletion
task_completions = await session.execute(
select(TaskCompletion)
.where(TaskCompletion.completed >= seven_days_ago)
)
task_completions = task_completions.scalars().all()
print(f"Найдено записей для проверки: {len(task_completions)}")
for task_completion in task_completions:
user_id = task_completion.tg_id
task = await session.scalar(select(Task).where(Task.id == task_completion.task_id))
if not task:
print(f"Задание с ID {task_completion.task_id} не найдено.")
continue
print(f"\nПроверка пользователя {user_id} на подписку на канал {task.link}")
try:
is_subscribed = await is_user_subscribed(bot, user_id, task.link)
print(f"Результат проверки подписки: {is_subscribed}")
except Exception as e:
print(f"Ошибка при проверке подписки пользователя {user_id}: {e}")
continue
#task_completion.last_checked = now
if not is_subscribed and task_completion.is_subscribed:
user = await session.scalar(select(User).where(User.tg_id == user_id))
if user:
user.balance -= task.reward
task_completion.is_subscribed = False
await session.commit()
print(f"Баланс пользователя {user_id} уменьшен на {task.reward}.")
await bot.send_message(chat_id=user_id, text=f"Вы отписались от канала {task.link}. Ваш баланс уменьшен на {task.reward}.")
print(f"Уведомление отправлено пользователю {user_id}.")
elif is_subscribed and not task_completion.is_subscribed:
user = await session.scalar(select(User).where(User.tg_id == user_id))
if user:
user.balance += task.reward
task_completion.is_subscribed = True
await session.commit()
print(f"Баланс пользователя {user_id} увеличен на {task.reward}.")
await bot.send_message(chat_id=user_id, text=f"Спасибо за повторную подписку на канал {task.link}. Ваш баланс увеличен на {task.reward}.")
print(f"Уведомление отправлено пользователю {user_id}.")
except Exception as e:
print(f"Ошибка при выполнении запроса к БД: {e}")
print(f"--- Проверка подписок завершена. Ожидание 24 часа. ---")
await asyncio.sleep(86400) # Проверяем каждые 24 часа (86400 секунд)
Ответы (1 шт):
Автор решения: Рустам Рысаев
→ Ссылка
Ошибка greenlet_spawn has not been called в SQLAlchemy возникает, когда вы пытаетесь выполнить асинхронные операции с базой данных, но асинхронный движок SQLAlchemy не настроен должным образом или используется в неподходящем контексте
Если session.scalar(select(...)) вызывает ошибку, попробуйте выполнять его через run_sync:
task = await session.run_sync(lambda s: s.scalar(select(Task).where(Task.id == task_completion.task_id)))
можно попробовать выполнять операции с базой данных внутри блока async with session.begin()
@connection
async def check_subscriptions(session, bot: Bot):
while True:
now = datetime.now()
seven_days_ago = now - timedelta(days=7)
print(f"\n--- Проверка подписок начата. Время: {now} ---")
try:
# Используем контекстный менеджер для сессии
async with session.begin():
result = await session.execute(
select(TaskCompletion).where(TaskCompletion.completed >= seven_days_ago)
)
task_completions = result.scalars().all()
print(f"Найдено записей для проверки: {len(task_completions)}")
for task_completion in task_completions:
user_id = task_completion.tg_id
async with session.begin():
task = await session.scalar(select(Task).where(Task.id == task_completion.task_id))
if not task:
print(f"Задание с ID {task_completion.task_id} не найдено.")
continue
print(f"\nПроверка пользователя {user_id} на подписку на канал {task.link}")
try:
is_subscribed = await is_user_subscribed(bot, user_id, task.link)
print(f"Результат проверки подписки: {is_subscribed}")
except Exception as e:
print(f"Ошибка при проверке подписки пользователя {user_id}: {e}")
continue
if not is_subscribed and task_completion.is_subscribed:
async with session.begin():
user = await session.scalar(select(User).where(User.tg_id == user_id))
if user:
user.balance -= task.reward
task_completion.is_subscribed = False
print(f"Баланс пользователя {user_id} уменьшен на {task.reward}.")
await bot.send_message(
chat_id=user_id,
text=f"Вы отписались от канала {task.link}. Ваш баланс уменьшен на {task.reward}."
)
print(f"Уведомление отправлено пользователю {user_id}.")
elif is_subscribed and not task_completion.is_subscribed:
async with session.begin():
user = await session.scalar(select(User).where(User.tg_id == user_id))
if user:
user.balance += task.reward
task_completion.is_subscribed = True
print(f"Баланс пользователя {user_id} увеличен на {task.reward}.")
await bot.send_message(
chat_id=user_id,
text=f"Спасибо за повторную подписку на канал {task.link}. Ваш баланс увеличен на {task.reward}."
)
print(f"Уведомление отправлено пользователю {user_id}.")
except Exception as e:
print(f"Ошибка при выполнении запроса к БД: {e}")
print(f"--- Проверка подписок завершена. Ожидание 24 часа. ---")
await asyncio.sleep(86400) # Проверяем каждые 24 часа (86400 секунд)