pyramid_cubicweb/tools.py
author Christophe de Vienne <christophe@unlish.com>
Mon, 26 Jan 2015 17:59:10 +0100
changeset 11550 38ed4c3ac3de
child 11551 444cd2bba89d
permissions -rw-r--r--
[tools] Provide a faster build_user The main trick is to use a cache of user entities. To do so, a few tools are needed since the entities are not supposed to be copied around between connexions. Related to #4870347
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
11550
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
     1
"""Various tools"""
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
     2
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
     3
#: A short-term cache for user clones.
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
     4
#: used by cached_build_user to speed-up repetitive calls to build_user
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
     5
#: The expiration is handled in a dumb and brutal way: the whole cache is
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
     6
#: cleared every 5 minutes.
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
     7
_user_cache = {}
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
     8
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
     9
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    10
def clone_user(repo, user):
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    11
    """Clone a CWUser instance.
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    12
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    13
    .. warning::
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    14
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    15
        The returned clone is detached from any cnx.
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    16
        Before using it in any way, it should be attached to a cnx that has not
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    17
        this user already loaded.
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    18
    """
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    19
    CWUser = repo.vreg['etypes'].etype_class('CWUser')
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    20
    clone = CWUser(
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    21
        None,
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    22
        rset=user.cw_rset.copy(),
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    23
        row=user.cw_row,
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    24
        col=user.cw_col,
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    25
        groups=set(user._groups) if hasattr(user, '_groups') else None,
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    26
        properties=dict(user._properties)
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    27
        if hasattr(user, '_properties') else None)
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    28
    clone.cw_attr_cache = dict(user.cw_attr_cache)
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    29
    return clone
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    30
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    31
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    32
def cnx_attach_entity(cnx, entity):
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    33
    """Attach an entity to a cnx."""
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    34
    entity._cw = cnx
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    35
    if entity.cw_rset:
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    36
        entity.cw_rset.req = cnx
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    37
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    38
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    39
def cached_build_user(repo, eid):
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    40
    """Cached version of
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    41
    :meth:`cubicweb.server.repository.Repository._build_user`
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    42
    """
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    43
    with repo.internal_cnx() as cnx:
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    44
        if eid in _user_cache:
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    45
            entity = clone_user(repo, _user_cache[eid])
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    46
            cnx_attach_entity(cnx, entity)
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    47
            return entity
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    48
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    49
        user = repo._build_user(cnx, eid)
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    50
        user.cw_clear_relation_cache()
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    51
        _user_cache[eid] = clone_user(repo, user)
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    52
        return user
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    53
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    54
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    55
def clear_cache():
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    56
    """Clear the user cache"""
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    57
    _user_cache.clear()
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    58
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    59
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    60
def includeme(config):
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    61
    repo = config.registry['cubicweb.repository']
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    62
    interval = int(config.registry.settings.get(
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    63
        'cubicweb.usercache.expiration_time', 60*5))
38ed4c3ac3de [tools] Provide a faster build_user
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    64
    repo.looping_task(interval, clear_cache)