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

RBAC: cache items #3168

Closed
evgen-d opened this issue Apr 18, 2014 · 9 comments
Closed

RBAC: cache items #3168

evgen-d opened this issue Apr 18, 2014 · 9 comments

Comments

@evgen-d
Copy link
Contributor

evgen-d commented Apr 18, 2014

Caching auth items and etc.
Discussion - #3166

@qiangxue qiangxue added this to the 2.0 RC milestone Apr 18, 2014
@cebe
Copy link
Member

cebe commented Apr 18, 2014

Another use case for calling checkAccess() multiple times is building a navigation where most of the links need permission check to ensure user is allowed to access the corresponding action.
Current implementation I have results in about 100 db queries to build the navigation.

@qiangxue
Copy link
Member

Some ideas here:

  • Add DbManager::cache to indicate the cache ID being used. If not set, it means no caching.
  • Only cache auth_item, auth_rule and auth_item_child data. All these data are cached as a single entry in cache. Note that auth_assignment is too big to be cached (imagine a system with millions of users).
  • When DbManager is called to modify the auth data (e.g. add a new role, update a permission), it should invalidate the cache. It should also store the update timestamp in the cache.
  • When DbManager is used to query auth data (e.g. checkAccess, get permission list), it should try to fetch data from three places:
    • memory: if expired (by checking the timestamp) or not found, try cache;
    • cache: if expired (by checking the timestamp) or not found, try DB
    • DB: save the fetched in cache and memory.

@cebe
Copy link
Member

cebe commented Apr 18, 2014

Looks good to me. Assignment may be stored in web\User as a private property to ensure it only gets loaded once per request.

@qiangxue
Copy link
Member

Another solution is to build a NoSQL-backed RBAC manager.

@samdark
Copy link
Member

samdark commented Jun 2, 2014

@evgen-d
Copy link
Contributor Author

evgen-d commented Jun 3, 2014

This extension caches checkAccess result. This is not solution of multiple querying in checkAccessRecursive. And when result is cached rbac may no longer be actual.

@mdmunir
Copy link
Contributor

mdmunir commented Jun 8, 2014

My proposal for cached rbac dbmanager
https://github.com/mdmsoft/yii2-admin/blob/master/components/DbManager.php
Each table load only once per request (except assigment when applied to more than one user). After loaded, data saved to memory. Then all process using data from memory.
To save memory. Children and assigment, only saved as the name.

$this->_children = [
    'parent_name1' => ['child1', 'child2', 'child3', ...],
    'parent_name2' => ['child1', 'child2', 'child3', ...],
];

$this->_assigments = [
    'userId1' => ['role1', 'role2', 'role3', ...],
];

@gimox
Copy link
Contributor

gimox commented Jun 8, 2014

Usiing rbac, i notice same problem that cebe wrote.... A large number of db query that solwly the app.
So for now i rewrote some code to use with an other db. But the best solution for me is use cache components with a nosql db. (Redis or mongo)

@cebe cebe modified the milestones: 2.0 GA, 2.0 RC Jun 25, 2014
@qiangxue qiangxue added severity:important and removed status:ready for adoption Feel free to implement this issue. labels Sep 27, 2014
@qiangxue qiangxue modified the milestones: 2.0.1, 2.0 GA Sep 27, 2014
@qiangxue qiangxue self-assigned this Nov 16, 2014
@qiangxue qiangxue modified the milestones: 2.0.2, 2.0.1 Dec 2, 2014
@qiangxue qiangxue modified the milestones: 2.0.2, 2.0.3 Jan 11, 2015
@RomeroMsk
Copy link
Contributor

@cebe wrote:

Another use case for calling checkAccess() multiple times is building a navigation where most of the links need permission check to ensure user is allowed to access the corresponding action.
Current implementation I have results in about 100 db queries to build the navigation.

What about this case? Why not to cache assignments in memory to avoid duplicated queries in one request? I understand, why we can't use cache engine for this by default, but saving results of SELECT * FROM auth_assignment WHERE user_id='...' in instance is must have: now Yii2 generates this query N times for N Yii::$app->user->can() calls on the page (when building navigation, for example).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants