uralbash / sqlalchemy_mptt

SQLAlchemy nested sets mixin (MPTT)
http://sqlalchemy-mptt.readthedocs.io
MIT License
196 stars 32 forks source link

Support mptt_sessionmaker with async session #76

Open xykylikuf001 opened 2 years ago

xykylikuf001 commented 2 years ago

Simple steps for reproduce:

from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker
from sqlalchemy_mptt import mptt_sessionmaker

async_engine = create_async_engine("postgresql+asyncpg://scott:tiger@localhost/test", pool_pre_ping=True, echo=settings.DEBUG)
AsyncSessionLocal = mptt_sessionmaker(sessionmaker(
    class_=AsyncSession,
    expire_on_commit=False,
    autocommit=False,
    autoflush=False,
    bind=async_engine,
    future=True,
), )
xykylikuf001 commented 2 years ago

That raise this error:

Process SpawnProcess-1:
Traceback (most recent call last):
  File "/usr/local/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap
    self.run()
  File "/usr/local/lib/python3.10/multiprocessing/process.py", line 108, in run
    self._target(*self._args, **self._kwargs)
  File "/media/vip/FE94893A9488F685/projects/akat_market_platform/src/version_2/.venv/lib/python3.10/site-packages/uvicorn/subprocess.py", line 76, in subprocess_started
    target(sockets=sockets)
  File "/media/vip/FE94893A9488F685/projects/akat_market_platform/src/version_2/.venv/lib/python3.10/site-packages/uvicorn/server.py", line 60, in run
    return asyncio.run(self.serve(sockets=sockets))
  File "/usr/local/lib/python3.10/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/usr/local/lib/python3.10/asyncio/base_events.py", line 646, in run_until_complete
    return future.result()
  File "/media/vip/FE94893A9488F685/projects/akat_market_platform/src/version_2/.venv/lib/python3.10/site-packages/uvicorn/server.py", line 67, in serve
    config.load()
  File "/media/vip/FE94893A9488F685/projects/akat_market_platform/src/version_2/.venv/lib/python3.10/site-packages/uvicorn/config.py", line 458, in load
    self.loaded_app = import_from_string(self.app)
  File "/media/vip/FE94893A9488F685/projects/akat_market_platform/src/version_2/.venv/lib/python3.10/site-packages/uvicorn/importer.py", line 21, in import_from_string
    module = importlib.import_module(module_str)
  File "/usr/local/lib/python3.10/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 883, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "/media/vip/FE94893A9488F685/projects/akat_market_platform/src/version_2/./app/main.py", line 25, in <module>
    from app.routers import dependency
  File "/media/vip/FE94893A9488F685/projects/akat_market_platform/src/version_2/./app/routers/dependency.py", line 17, in <module>
    from app.db.session import AsyncSessionLocal
  File "/media/vip/FE94893A9488F685/projects/akat_market_platform/src/version_2/./app/db/session.py", line 17, in <module>
    AsyncSessionLocal = mptt_sessionmaker(sessionmaker(
 File "/media/vip/FE94893A9488F685/projects/akat_market_platform/src/version_2/./app/db/mptt/events.py", line 567, in register_factory
    event.listen(sessionmaker, 'after_flush_postexec',
  File "/media/vip/FE94893A9488F685/projects/akat_market_platform/src/version_2/.venv/lib/python3.10/site-packages/sqlalchemy/event/api.py", line 115, in listen
    _event_key(target, identifier, fn).listen(*args, **kw)
  File "/media/vip/FE94893A9488F685/projects/akat_market_platform/src/version_2/.venv/lib/python3.10/site-packages/sqlalchemy/event/registry.py", line 232, in listen
    self.dispatch_target.dispatch._listen(self, *args, **kw)
  File "/media/vip/FE94893A9488F685/projects/akat_market_platform/src/version_2/.venv/lib/python3.10/site-packages/sqlalchemy/ext/asyncio/events.py", line 44, in _listen
    cls._no_async_engine_events()
  File "/media/vip/FE94893A9488F685/projects/akat_market_platform/src/version_2/.venv/lib/python3.10/site-packages/sqlalchemy/ext/asyncio/events.py", line 37, in _no_async_engine_events
    raise NotImplementedError(
NotImplementedError: asynchronous events are not implemented at this time.  Apply synchronous listeners to the AsyncSession.sync_session.
xykylikuf001 commented 2 years ago

Somethind need to do when register listener: ~/sqlalchemy_mptt/events.py - 530 line

    def register_factory(self, sessionmaker):
        """
        Registers this TreesManager instance to respond on
        `after_flush_postexec` events on the given session or session factory.
        This method returns the original argument, so that it can be used by
        wrapping an already exisiting instance:

        .. code-block:: python
            :linenos:

            from sqlalchemy import create_engine
            from sqlalchemy.orm import sessionmaker, mapper
            from sqlalchemy_mptt.mixins import BaseNestedSets

            engine = create_engine('...')

            trees_manager = TreesManager(BaseNestedSets)
            trees_manager.register_mapper(mapper)

            Session = tree_manager.register_factory(
                sessionmaker(bind=engine)
            )

        A reference to this method, bound to a default instance of this class
        and already registered to a mapper, is importable directly from
        `sqlalchemy_mptt`:

        .. code-block:: python
            :linenos:

            from sqlalchemy import create_engine
            from sqlalchemy.orm import sessionmaker
            from sqlalchemy_mptt import mptt_sessionmaker

            engine = create_engine('...')
            Session = mptt_sessionmaker(sessionmaker(bind=engine))
        """
        event.listen(sessionmaker, 'after_flush_postexec',
                     self.after_flush_postexec)
        return sessionmaker
xykylikuf001 commented 2 years ago

Please help how to solve this problem?