Не используйте диспетчеры транзакций повторно через соединения.Каждое соединение имеет свой собственный менеджер транзакций, используйте его .
Ваш код в настоящее время создает соединение, а затем фиксирует его.Вместо того чтобы создавать соединение, попросите базу данных создать для вас менеджер транзакций, который затем будет управлять своим собственным соединением.Менеджер транзакций может использоваться как менеджер контекста , что означает, что изменения в базе данных автоматически фиксируются по окончании контекста.
Более того, используя ZEO.connection()
для каждой транзакции, вы заставляете ZEO создать полностью новый объект клиента со свежим кешем и пулом соединений.Используя вместо этого ZEO.DB()
и кэшируя результат, создается один клиент, из которого можно объединять и повторно использовать соединения, и с локальным кэшем для ускорения транзакций.
Я бы изменил код на:
def get_db():
"""Access the ZEO database client.
The database client is cached to take advantage of caching and connection pooling
"""
db = getattr(get_db, 'db', None)
if db is None:
get_db.db = db = ZEO.DB(8092)
return db
async def _message_db_init_aux(self, channel, after=None, before=None):
with self.get_db().transaction() as conn:
root = conn.root()
messages = await some_function_which_return_a_list()
async for message in messages:
# If author.id doesn't exist on the data, let's initiate it as a Tree
if message.author.id not in root.data: # root.data is a BTrees.OOBTree.BTree()
root.data[message.author.id] = BTrees.OOBTree.BTree()
# Message is a defined classed inherited from persistant.Persistant
root.data[message.author.id][message.id] = Message(
message.id, message.author.id, message.created_at
)
Метод .transaction()
для объекта базы данных создает новое соединение под капотом, в момент ввода контекста (with
вызывает вызов __enter__
) и когда with
блокировка завершается, транзакция фиксируется и соединение снова устанавливается в пул.
Обратите внимание, что я использовал синхронный метод def get_db()
;подписи вызовов в коде клиента ZEO полностью синхронны.Их безопасно вызывать из асинхронного кода, потому что под капотом , реализация использует повсюду asyncio
, используя обратные вызовы и задачи в одном и том же цикле, а фактический ввод-вывод откладывается на отдельные задачи.