24 |
24 |
25 This module should be considered as internal implementation details. Use |
25 This module should be considered as internal implementation details. Use |
26 with caution, as the API may change without notice. |
26 with caution, as the API may change without notice. |
27 """ |
27 """ |
28 |
28 |
29 #: A short-term cache for user clones. |
29 from repoze.lru import lru_cache |
30 #: used by cached_build_user to speed-up repetitive calls to build_user |
|
31 #: The expiration is handled in a dumb and brutal way: the whole cache is |
|
32 #: cleared every 5 minutes. |
|
33 _user_cache = {} |
|
34 |
30 |
35 |
31 |
36 def clone_user(repo, user): |
32 def clone_user(repo, user): |
37 """Clone a CWUser instance. |
33 """Clone a CWUser instance. |
38 |
34 |
57 entity._cw = cnx |
53 entity._cw = cnx |
58 if entity.cw_rset: |
54 if entity.cw_rset: |
59 entity.cw_rset.req = cnx |
55 entity.cw_rset.req = cnx |
60 |
56 |
61 |
57 |
|
58 @lru_cache(10) |
62 def cached_build_user(repo, eid): |
59 def cached_build_user(repo, eid): |
63 """Cached version of |
60 """Cached version of |
64 :meth:`cubicweb.server.repository.Repository._build_user` |
61 :meth:`cubicweb.server.repository.Repository._build_user` |
65 """ |
62 """ |
66 if eid in _user_cache: |
|
67 user, lang = _user_cache[eid] |
|
68 entity = clone_user(repo, user) |
|
69 return entity, lang |
|
70 |
|
71 with repo.internal_cnx() as cnx: |
63 with repo.internal_cnx() as cnx: |
72 user = repo._build_user(cnx, eid) |
64 user = repo._build_user(cnx, eid) |
73 lang = user.prefered_language() |
65 lang = user.prefered_language() |
74 user.cw_clear_relation_cache() |
66 user.cw_clear_relation_cache() |
75 _user_cache[eid] = (clone_user(repo, user), lang) |
67 return clone_user(repo, user), lang |
76 return user, lang |
|
77 |
|
78 |
|
79 def clear_cache(): |
|
80 """Clear the user cache""" |
|
81 _user_cache.clear() |
|
82 |
|
83 |
|
84 def includeme(config): |
|
85 """Start the cache maintenance loop task. |
|
86 |
|
87 Automatically included by :mod:`cubicweb.pyramid`. |
|
88 """ |
|
89 repo = config.registry['cubicweb.repository'] |
|
90 interval = int(config.registry.settings.get( |
|
91 'cubicweb.usercache.expiration_time', 60 * 5)) |
|
92 repo.looping_task(interval, clear_cache) |
|