Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sqlalchemy object caching issue #83

Closed
dotX12 opened this issue Jul 23, 2022 · 13 comments
Closed

sqlalchemy object caching issue #83

dotX12 opened this issue Jul 23, 2022 · 13 comments
Assignees
Labels
bug Something isn't working enhancement New feature or request

Comments

@dotX12
Copy link

dotX12 commented Jul 23, 2022

Greetings! I ran into sqlalchemy object caching issues. From time to time I get errors like this:

"  File \"/home/boot/stellar/backend/./app/v1/security/auth.py\", line 127, in get_current_user\n    permissions_v2 = await service_permissions.get_permissions_by_role_cache(\n",
      "  File \"/home/boot/stellar/backend/.venv/lib/python3.10/site-packages/cashews/wrapper.py\", line 272, in _call\n    return await decorator(*args, **kwargs)\n",
      "  File \"/home/boot/stellar/backend/.venv/lib/python3.10/site-packages/cashews/decorators/cache/simple.py\", line 43, in _wrap\n    await backend.set(_cache_key, result, expire=ttl)\n",
      "  File \"/home/boot/stellar/backend/.venv/lib/python3.10/site-packages/cashews/validation.py\", line 62, in _invalidate_middleware\n    return await call(*args, key=key, **kwargs)\n",
      "  File \"/home/boot/stellar/backend/.venv/lib/python3.10/site-packages/cashews/wrapper.py\", line 34, in _auto_init\n    return await call(*args, **kwargs)\n",
      "  File \"/home/boot/stellar/backend/.venv/lib/python3.10/site-packages/cashews/disable_control.py\", line 12, in _is_disable_middleware\n    return await call(*args, **kwargs)\n",
      "  File \"/home/boot/stellar/backend/.venv/lib/python3.10/site-packages/cashews/backends/client_side.py\", line 132, in set\n    return await super().set(self._prefix + key, value, *args, **kwargs)\n",
      "  File \"/home/boot/stellar/backend/.venv/lib/python3.10/site-packages/cashews/serialize.py\", line 107, in set\n    value = pickle.dumps(value, protocol=pickle.HIGHEST_PROTOCOL, fix_imports=False)\n",
      "_pickle.PicklingError: Can't pickle <function __init__ at 0x7fc386fbb7f0>: it's not the same object as sqlalchemy.orm.instrumentation.__init__\n"

I found the answer that such objects should be serialized and deserialized differently:
https://docs.sqlalchemy.org/en/14/core/serializer.html

Tell me how good / bad idea it is to cache alchemy objects, and not the endpoint itself.

If this is not bad, what can you say about adding functionality that could fix this error?

@Krukov
Copy link
Owner

Krukov commented Jul 26, 2022

Hello,

I think objects like sqlalchemy orm is a good use case for caching, if it possible to pickle somehow.
So Yep, cashews should support it ( thanks for the link), I am going to fix this issue ASAP.

@Krukov Krukov added bug Something isn't working enhancement New feature or request labels Jul 26, 2022
@Krukov Krukov self-assigned this Jul 26, 2022
Krukov pushed a commit that referenced this issue Jul 26, 2022
Krukov pushed a commit that referenced this issue Jul 26, 2022
Krukov added a commit that referenced this issue Jul 28, 2022
@Krukov
Copy link
Owner

Krukov commented Aug 1, 2022

Hi @dotX12 , the release is ready to upload on pypi but I can't reproduce this issue. ) I tried with simple examples but with different types of sqlalchemy objects and can't get an error like you have.

import asyncio

from cashews import cache
cache.setup("redis://")

from sqlalchemy import Column, Integer, String
from sqlalchemy.orm import declarative_base, sessionmaker
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.future import select
from sqlalchemy.ext.asyncio import create_async_engine

Base = declarative_base()


class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    name = Column(String)
    fullname = Column(String)
    nickname = Column(String)


@cache(ttl="1m", key="user:{id}")
async def get_user(session, id):
    user = await session.get(User, id)
    return user


async def main():
    engine = create_async_engine('sqlite+aiosqlite:///:memory:', echo=False)
    async with engine.begin() as conn:
        await conn.run_sync(Base.metadata.create_all)

    async_session = sessionmaker(
        engine, expire_on_commit=False, class_=AsyncSession
    )
    async with async_session() as session:
        async with session.begin():
            session.add_all(
                [
                    User(name="test", id=11, fullname="10 th", nickname="test10"),
                ]
            )
        user = await get_user(session, 11)
        print(user.fullname)


asyncio.run(main())
    

@dotX12
Copy link
Author

dotX12 commented Aug 1, 2022

Привет, @dotX12, релиз готов к загрузке на pypi, но я не могу воспроизвести эту проблему. ) Я попробовал с простыми примерами, но с разными типами объектов sqlalchemy и не могу получить ошибку, как у вас.

import asyncio

from cashews import cache
cache.setup("redis://")

from sqlalchemy import Column, Integer, String
from sqlalchemy.orm import declarative_base, sessionmaker
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.future import select
from sqlalchemy.ext.asyncio import create_async_engine

Base = declarative_base()


class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    name = Column(String)
    fullname = Column(String)
    nickname = Column(String)


@cache(ttl="1m", key="user:{id}")
async def get_user(session, id):
    user = await session.get(User, id)
    return user


async def main():
    engine = create_async_engine('sqlite+aiosqlite:///:memory:', echo=False)
    async with engine.begin() as conn:
        await conn.run_sync(Base.metadata.create_all)

    async_session = sessionmaker(
        engine, expire_on_commit=False, class_=AsyncSession
    )
    async with async_session() as session:
        async with session.begin():
            session.add_all(
                [
                    User(name="test", id=11, fullname="10 th", nickname="test10"),
                ]
            )
        user = await get_user(session, 11)
        print(user.fullname)


asyncio.run(main())
    

Hi, I'm not at home right now, I'll test it tomorrow evening, thanks!

@Krukov
Copy link
Owner

Krukov commented Aug 2, 2022

OK but you can test it only on master branch - release postponed. It will be nice to have and example of code with this bug

@dotX12
Copy link
Author

dotX12 commented Aug 3, 2022

@Krukov, indeed, your example doesn't cause this problem.
I can't share my example that causes this problem (the problem persists and hasn't been fixed :c), as it is the project with NDA.
but I'll try to make a test case that reproduces it.

@Krukov
Copy link
Owner

Krukov commented Aug 8, 2022

@dotX12 Hello
Do you have some examples?

@dotX12
Copy link
Author

dotX12 commented Aug 10, 2022

@Krukov
Hello, I have now gone to the sea, I think I should not have opened this issue so early :) I think I can only answer the august 20 to you :)
Sry

@Krukov
Copy link
Owner

Krukov commented Aug 11, 2022

Don't worry, it is OK. Have a good weekend!

@Krukov
Copy link
Owner

Krukov commented Aug 28, 2022

Hi @dotX12 . Do you have any updates? )

@dotX12
Copy link
Author

dotX12 commented Aug 30, 2022

Hi @dotX12 . Do you have any updates? )

Hello, now I sit down to reproduce the bug, I think tomorrow or after tomorrow I will send it!

@dotX12
Copy link
Author

dotX12 commented Sep 3, 2022

@Krukov, pickletype="sqlalchemy" really solved my problem, I don't know why it didn't work last time, maybe I didn't update the library version to master, but now the problem is gone!

solved :)

@Krukov
Copy link
Owner

Krukov commented Sep 3, 2022

Great, than I will release new version soon

@Krukov
Copy link
Owner

Krukov commented Sep 30, 2022

released with 4.7.1

@Krukov Krukov closed this as completed Sep 30, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants