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 секунд)

→ Ссылка