Stay Hungry,Stay Foolish!

SQLAlchemy scoped_session + 注册器

SQLAlchemy scoped_session

本身 session 不是线程安全的。

 

https://docs.sqlalchemy.org/en/14/orm/contextual.html

The object is the scoped_session object, and it represents a registry of Session objects. If you’re not familiar with the registry pattern, a good introduction can be found in Patterns of Enterprise Architecture.

引入注册器,所有线程都可以访问注册器, 注册器内部使用线程local存储 线程自身的session, 从而隔离不同线程

ScopedRegistry

A Registry that can store one or multiple instances of a single class on the basis of a “scope” function.

ThreadLocalRegistry

A ScopedRegistry that uses a threading.local() variable for storage.

 

注册器概念

https://martinfowler.com/eaaCatalog/registry.html

Registry

A well-known object that other objects can use to find common objects and services.

For a full description see P of EAA page 480

When you want to find an object you usually start with another object that has an association to it, and use the association to navigate to it. Thus, if you want to find all the orders for a customer, you start with the customer object and use a method on it to get the orders. However, in some cases you won't have an appropriate object to start with. You may know the customer's ID number but not have a reference. In this case you need some kind of lookup method - a finder - but the question remains: How do you get to the finder?

A Registry is essentially a global object, or at least it looks like one - even if it isn't as global as it may appear.

 

注册器实现代码

https://github.com/sqlalchemy/sqlalchemy/blob/main/lib/sqlalchemy/util/_collections.py#L663

class ThreadLocalRegistry(ScopedRegistry[_T]):
    """A :class:`.ScopedRegistry` that uses a ``threading.local()``
    variable for storage.

    """

    def __init__(self, createfunc: Callable[[], _T]):
        self.createfunc = createfunc
        self.registry = threading.local()

    def __call__(self) -> _T:
        try:
            return self.registry.value  # type: ignore[no-any-return]
        except AttributeError:
            val = self.registry.value = self.createfunc()
            return val

    def has(self) -> bool:
        return hasattr(self.registry, "value")

    def set(self, obj: _T) -> None:
        self.registry.value = obj

    def clear(self) -> None:
        try:
            del self.registry.value
        except AttributeError:
            pass

 

参考:

https://farer.org/2017/10/28/sqlalchemy_scoped_session/

https://juejin.cn/post/6844904164141580302

https://www.cnblogs.com/randysun/p/15518306.html

 

posted @ 2023-12-22 10:59  lightsong  阅读(13)  评论(0编辑  收藏  举报
Life Is Short, We Need Ship To Travel