Create a WEB API with Django called business improvement In-house, partly using mechanize to convert intra login and intra operations to API I was having a good time.
Since it is a WEB API, access is basically stateless, and an instance of mechanize is created each time for intra-operation. Therefore, from the perspective of the intranet, it was ** a new login ** for each request to the API. In the near future, I will be angry with the information system and want to improve.
Instead of creating an instance of mechanize every time, I decided to pool it.
Original caller
worker = IntraWorker(USER,PASS)
worker.do_something()
IntraWoker is a class that uses mechanize. I log in every time with  __init__. I made this below.
New caller
# get from pool
worker = IntraWorkerPool().get(USER,PASS)
worker.do_something()
# back to pool
worker.close()
Add a class called IntraWorkerPool and let it manage the pool.
IntraWorkerPool
from threading import Lock
class IntraWorkerPool(object):
    """
Mechanize pooling management
    """
    #Worker being pooled
    # user,Use the pass tuple as a key
    pooled_workers = {}
    def __init__(self):
        self.lock = Lock()
    def get(self, user, password):
        """
Remove a Worker instance from the pool
        """
        ret_aw = None
        pool = IntraWorkerPool.pooled_workers
        key = (hashed(user), password)
        with self.lock:
            if key in pool:
                #Make if not available
                if len(pool[key]) == 0:
                    pool[key].append(IntraWorker(*key, pool_control=self))
            else:
                pool[key] = []
                pool[key].append(IntraWorker(*key, pool_control=self)
            
            #Check if the worker is still able to log in
            while (ret_aw is None) or (not ret_aw.is_login()):
                ret_aw = pool[key].pop()
        return ret_aw
    def back_to_pool(self, aw_inst):
        """
Return the instance to pool
You don't actually call this directly. Call with close on the worker side
        """
        key = (hashed(aw_inst.user_no), aw_inst.user_password)
        pool = IntraWorkerPool.pooled_workers
        with self.lock:
            pool.setdefault(key, [])
            pool[key].append(aw_inst)
What we are doing is managing a tuple of usernames and passwords and a list of Worker instances with a dictionary called pooled_workers as a class variable. Also, list operations should be thread-safe, so I'm serializing them using threading.Lock (). To return to the pool, a method called  back_to_pool is prepared, which is also protected by Lock, but in reality, back_to_pool is executed when the Close method on the Worker instance side is executed.
To be honest, I don't like the fact that the Pool management class and the managed class are interdependent, but I can't think of a smart implementation and the tea is muddy in this way.
I would appreciate it if anyone could tell me if there is something smarter.
Recommended Posts