Skip to content

Commit b39498c

Browse files
committed
add basic ref counting
1 parent 68ccdd9 commit b39498c

File tree

1 file changed

+22
-13
lines changed

1 file changed

+22
-13
lines changed

proxy/src/cache/project_info.rs

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::convert::Infallible;
2-
use std::sync::Arc;
2+
use std::sync::{Arc, Mutex};
33

4-
use crossbeam_skiplist::SkipSet;
4+
use crossbeam_skiplist::SkipMap;
55
use crossbeam_skiplist::equivalent::{Comparable, Equivalent};
66
use moka::sync::Cache;
77
use tracing::{debug, info};
@@ -12,6 +12,7 @@ use crate::cache::common::{
1212
use crate::config::ProjectInfoCacheOptions;
1313
use crate::control_plane::messages::{ControlPlaneErrorMessage, Reason};
1414
use crate::control_plane::{EndpointAccessControl, RoleAccessControl};
15+
use crate::ext::LockExt;
1516
use crate::intern::{AccountIdInt, EndpointIdInt, ProjectIdInt, RoleNameInt};
1617
use crate::metrics::{CacheKind, Metrics};
1718
use crate::types::{EndpointId, RoleName};
@@ -28,16 +29,18 @@ pub struct ProjectInfoCache {
2829
Cache<(EndpointIdInt, RoleNameInt), ControlPlaneResult<Entry<RoleAccessControl>>>,
2930
ep_controls: Cache<EndpointIdInt, ControlPlaneResult<Entry<EndpointAccessControl>>>,
3031

31-
project2ep: Arc<MultiSet<ProjectIdInt, EndpointIdInt>>,
32-
account2ep: Arc<MultiSet<AccountIdInt, EndpointIdInt>>,
32+
project2ep: Arc<RefCountMultiSet<ProjectIdInt, EndpointIdInt>>,
33+
account2ep: Arc<RefCountMultiSet<AccountIdInt, EndpointIdInt>>,
3334

3435
config: ProjectInfoCacheOptions,
3536
}
3637

38+
type RefCount = Mutex<usize>;
3739
// This is rather hacky.
38-
// We use an ordered set of (K, V).
40+
// We use an ordered map of (K, V) -> RefCount.
3941
// We use range queries over `(K, _)..(K+1, _)` to do the invalidation.
40-
type MultiSet<K, V> = SkipSet<KeyValue<K, V>>;
42+
// We use the RefCount to know when to remove the mappings.
43+
type RefCountMultiSet<K, V> = SkipMap<KeyValue<K, V>, RefCount>;
4144

4245
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug)]
4346
struct KeyValue<K, V>(K, V);
@@ -77,15 +80,15 @@ impl ProjectInfoCache {
7780
info!("invalidating endpoint access for project `{project_id}`");
7881

7982
for entry in self.project2ep.range(Key::prefix(&project_id)) {
80-
self.ep_controls.invalidate(&entry.1);
83+
self.ep_controls.invalidate(&entry.key().1);
8184
}
8285
}
8386

8487
pub fn invalidate_endpoint_access_for_org(&self, account_id: AccountIdInt) {
8588
info!("invalidating endpoint access for org `{account_id}`");
8689

8790
for entry in self.account2ep.range(Key::prefix(&account_id)) {
88-
self.ep_controls.invalidate(&entry.1);
91+
self.ep_controls.invalidate(&entry.key().1);
8992
}
9093
}
9194

@@ -100,7 +103,7 @@ impl ProjectInfoCache {
100103
);
101104

102105
for entry in self.project2ep.range(Key::prefix(&project_id)) {
103-
self.role_controls.invalidate(&(entry.1, role_name));
106+
self.role_controls.invalidate(&(entry.key().1, role_name));
104107
}
105108
}
106109
}
@@ -116,8 +119,8 @@ impl ProjectInfoCache {
116119
.capacity
117120
.set(CacheKind::ProjectInfoEndpoints, config.size as i64);
118121

119-
let project2ep = Arc::new(MultiSet::new());
120-
let account2ep = Arc::new(MultiSet::new());
122+
let project2ep = Arc::new(RefCountMultiSet::new());
123+
let account2ep = Arc::new(RefCountMultiSet::new());
121124

122125
// we cache errors for 30 seconds, unless retry_at is set.
123126
let expiry = CplaneExpiry::default();
@@ -254,11 +257,17 @@ impl ProjectInfoCache {
254257
}
255258

256259
fn insert_project2endpoint(&self, project_id: ProjectIdInt, endpoint_id: EndpointIdInt) {
257-
self.project2ep.insert(KeyValue(project_id, endpoint_id));
260+
let entry = self
261+
.project2ep
262+
.get_or_insert(KeyValue(project_id, endpoint_id), Mutex::new(0));
263+
*entry.value().lock_propagate_poison() += 1;
258264
}
259265

260266
fn insert_account2endpoint(&self, account_id: AccountIdInt, endpoint_id: EndpointIdInt) {
261-
self.account2ep.insert(KeyValue(account_id, endpoint_id));
267+
let entry = self
268+
.account2ep
269+
.get_or_insert(KeyValue(account_id, endpoint_id), Mutex::new(0));
270+
*entry.value().lock_propagate_poison() += 1;
262271
}
263272

264273
pub fn maybe_invalidate_role_secret(&self, _endpoint_id: &EndpointId, _role_name: &RoleName) {

0 commit comments

Comments
 (0)