Есть класс SocketServer. В нем есть метод self.__room_thread(). Также в нем есть экземпляр планировщика BackgroundScheduler(). Этот класс имеет доступ к БД PostgreSQL. Мне нужно, сохранять и загружать в/из базы данных запланированные события. Но эти события обрабатываются методом self.__room_thread(). И тут начинаются проблемы. Во-первых, класс, чей метод используется в качестве обработчика, не должен содержать в себе экземпляр планировщика. Окей, это не проблема. Убрал. Заработало, но не надолго. Дальше посыпались ошибки по типу запрещенной ссылки на метод. Т.е. из-за того, что self.__room_thread() объявлен как "private", планировщик не может его запустить. Окей. Сделал "public". Дальше посыпались ошибки на каждый используемый внутри объект класса. Т.е. по сути та же ошибка, что и с self.__room_thread(), только теперь с каждый из других полей/методов класса. В общем, очень сильно прошу вашей помощи, как же мне все-таки реализовать данную, на мой взгляд, тривиальную задачу через APScheduler?
Код:
class SocketServer:
"""
Класс сокетного сервера.
Обрабатывает все запросе пользователей к серверу через сокеты.
Обеспечивает трансляцию игр пользователям.
"""
def __init__(self, socket: SocketIO, db_connector: DatabaseConnector, scheduler):
"""
Инициализатор класса.
:param socket: Серверный сокет для общения с клиентами.
:param db_connector: Ссылка на коннектор базы данных.
"""
############################ ТЕСТОВЫЙ КОД ##########################
self.__ex = [
Event(0, "event_0", datetime.datetime(2021, 4, 14, 21, 54, 0),
GameSnake(), [], "room_0", False),
Event(1, "event_1", datetime.datetime(2021, 4, 14, 21, 54, 20),
GameSnake(), [], "room_1", False),
Event(2, "event_2", datetime.datetime(2021, 4, 14, 21, 54, 30),
GameSnake(), [], "room_2", False)
]
for e in self.__ex:
scheduler.add_job(self.__room_thread, "date",
run_date=e.get_run_date(), args=[e])
###################################################################
# Коннектор бд.
self.__db_connector = db_connector
# Наш серверный сокет.
self.__socket_io = socket
# Список комнат.
self.__list_rooms = []
# Запускаем обработчики.
self.connect_client = self.__socket_io.on("connect")(self.__connect_client)
self.disconnect_client = self.__socket_io.on("disconnect")(self.__disconnect_client)
self.client_join_room = self.__socket_io.on("join")(self.__client_join_room)
self.client_leave_room = self.__socket_io.on("leave")(self.__client_leave_room)
def __room_thread(self, event: Event):
"""
Метод запуска комнаты в потоке.
:param event: Обрабатываемое событие в потоке.
:return:
"""
with Lock():
self.__list_rooms.append(event.get_room())
# Скорость трансляции.
broadcast_delay = 0.4
# Рассчитываем всю игру.
# После этого у нас есть готовая история игры в game.
event.get_game().calculation_game()
# Транслируем историю пошагово.
for game_step in event.get_game().get_history():
self.__socket_io.emit("message", game_step, room=event.get_room())
time.sleep(broadcast_delay)
# Если записи не должно быть - удаляем.
if not event.get_record_avail():
event.get_game().delete_history()
else:
# Если запись есть, сохраняем.
pass
# Используем мьютекс для синхронизации потоков.
with Lock():
# По окончании трансляции удаляем комнату и поток.
for i, room in enumerate(self.__list_rooms):
if room == event.get_room():
self.__list_rooms.pop(i)
print(f"{room} deleted")
break
@staticmethod
def __connect_client():
"""Подключение клиента"""
print("Client connected")
@staticmethod
def __disconnect_client():
"""Отключение клиента"""
print("Client disconnected")
def __client_join_room(self, data: Dict[str, str]):
"""
Метод подключения клиента в комнату.
:param data: Данные пользователя. Приходят с клиента.
:return:
"""
username = data["username"]
name_room = data["room"]
if name_room not in self.__list_rooms:
print(f"{name_room} not started")
else:
join_room(name_room)
print(f"{username}'s connected to {name_room}")
def __client_leave_room(self, data: Dict):
"""
Метод отключения клиента от комнаты.
:param data: Данные пользователя. Приходят с клиента.
:return:
"""
username = data["username"]
name_room = data["room"]
if name_room not in self.__list_rooms:
print(f"{name_room} not exist")
else:
leave_room(name_room)
print(f"{username}'s disconnected from {name_room}")