refactor(permission): simplify permission cache invalidation and update cache key format
ZhenYi committed
Modified lib/service/space/src/services/join_rules.rs lib/service/space/src/services/join_rules.rs +1 −1 View lib/service/space/src/services/join_rules.rs
@@ -134,7 +134,7 @@
134134 }
135135 txn.commit().await?;
136136 if bound {
137 crate::services::permission::invalidate(&access.database, &access.cache, space_id).await?;
137 crate::services::permission::invalidate(&access.cache, space_id).await?;
138138 }
139139 Ok(())
140140}
Modified lib/service/space/src/services/permission.rs lib/service/space/src/services/permission.rs +5 −22 View lib/service/space/src/services/permission.rs
@@ -159,7 +159,7 @@
159159 version: i32,
160160 membership: &space_members::Model,
161161) -> SpaceResult<Kernel> {
162 let key = service::perm_cache_prefix(organization_id, user_id);
162 let key = service::perm_cache_prefix(organization_id, user_id, version);
163163 if let Ok(Some(bytes)) = cache.get_bytes(&key).await
164164 && let Ok(kernel) = serde_json::from_slice::<Kernel>(&bytes)
165165 && kernel.version == version
@@ -384,30 +384,13 @@
384384 }
385385}
386386
387pub(crate) async fn invalidate(
388 db: &db::DbConn,
389 cache: &cache::Cache,
390 organization_id: Uuid,
391) -> SpaceResult<()> {
392 let members = space_members::Entity::find()
393 .select_only()
394 .column(space_members::Column::UserId)
395 .filter(space_members::Column::OrganizationId.eq(organization_id))
396 .into_tuple::<i64>()
397 .all(db.read())
398 .await?;
399 let mut keys = vec![
387pub(crate) async fn invalidate(cache: &cache::Cache, organization_id: Uuid) -> SpaceResult<()> {
388 for key in [
400389 format!("auth:org:{organization_id}"),
401390 format!("auth:org:summary:{organization_id}"),
402 ];
403 keys.extend(
404 members
405 .into_iter()
406 .map(|user| service::perm_cache_prefix(organization_id, user)),
407 );
408 for key in keys {
391 ] {
409392 if let Err(error) = cache.delete(&key).await {
410 tracing::warn!(%error, %organization_id, "failed to invalidate permission cache");
393 tracing::warn!(%error, %organization_id, "failed to invalidate organization cache");
411394 }
412395 }
413396 Ok(())
Modified lib/service/space/src/services/service.rs lib/service/space/src/services/service.rs +6 −46 View lib/service/space/src/services/service.rs
@@ -83,46 +83,15 @@
8383 space_roles, spaces,
8484};
8585
86pub(crate) fn perm_cache_prefix(organization_id: Uuid, user_id: i64) -> String {
87 format!("auth:org:perm:{organization_id}:{user_id}")
86pub(crate) fn perm_cache_prefix(organization_id: Uuid, user_id: i64, version: i32) -> String {
87 format!("auth:org:perm:{organization_id}:v{version}:{user_id}")
8888}
8989
9090impl SpaceService {
91 /// 组织写操作的统一收尾:推进 version,然后清掉本组织全部派生缓存。
92 /// version 同时是权限缓存的版本键与乐观锁基准,必须与写操作同事务推进。
91 /// 组织写操作提交后的统一收尾:清掉本组织非版本化的派生缓存。
92 /// 权限缓存 key 已编入 version,写操作只需在事务内推进 version,旧 key 自然失活。
9393 pub(crate) async fn invalidate_org(&self, organization_id: Uuid) -> SpaceResult<()> {
94 crate::services::permission::invalidate(
95 &self.access.database,
96 &self.access.cache,
97 organization_id,
98 )
99 .await
100 }
101
102 /// 成员行已随事务删除时用这一版:user_id 由调用方在事务内收集后传入。
103 pub(crate) async fn drop_org_cache(
104 &self,
105 organization_id: Uuid,
106 members: Vec<i64>,
107 ) -> SpaceResult<()> {
108 let cache = &self.access.cache;
109 for key in [
110 format!("auth:org:{organization_id}"),
111 format!("auth:org:summary:{organization_id}"),
112 ] {
113 if let Err(error) = cache.delete(&key).await {
114 tracing::warn!(%error, %organization_id, "failed to drop the organization cache");
115 }
116 }
117 for user_id in members {
118 if let Err(error) = cache
119 .delete(&perm_cache_prefix(organization_id, user_id))
120 .await
121 {
122 tracing::warn!(%error, %organization_id, user_id, "failed to drop the permission cache");
123 }
124 }
125 Ok(())
94 crate::services::permission::invalidate(&self.access.cache, organization_id).await
12695 }
12796
12897 pub(crate) async fn peek_org_version(&self, organization_id: Uuid) -> SpaceResult<Option<i32>> {
@@ -713,14 +682,6 @@
713682 .into_tuple::<Uuid>()
714683 .all(&txn)
715684 .await?;
716 // 权限缓存键依赖 user_id,而成员行在本事务里会被物理删除,所以先把 user_id 取出来。
717 let member_user_ids = space_members::Entity::find()
718 .select_only()
719 .column(space_members::Column::UserId)
720 .filter(space_members::Column::OrganizationId.eq(organization_id))
721 .into_tuple::<i64>()
722 .all(&txn)
723 .await?;
724685 if !member_ids.is_empty() {
725686 space_member_permissions::Entity::delete_many()
726687 .filter(space_member_permissions::Column::MemberId.is_in(member_ids.clone()))
@@ -783,8 +744,7 @@
783744 .await?;
784745 txn.commit().await?;
785746
786 self.drop_org_cache(organization_id, member_user_ids)
787 .await?;
747 self.invalidate_org(organization_id).await?;
788748 Ok(true)
789749 }
790750