Skip to content

Commit 077fd56

Browse files
committed
Fix CI: rewrite let-chains for MSRV 1.86, fix rocksdb bugs, add --locked to workflow
1 parent c3a47f1 commit 077fd56

11 files changed

Lines changed: 95 additions & 99 deletions

File tree

.github/workflows/ci.yml

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,36 +27,36 @@ jobs:
2727

2828
- name: Clippy (1.86 compatible crates)
2929
if: matrix.rust == '1.86'
30-
run: cargo clippy -p aegis-core -p aegis-cli -p aegis-test-utils -p aegis-ffi
30+
run: cargo clippy -p aegis-core -p aegis-cli -p aegis-test-utils -p aegis-ffi --locked
3131

3232
- name: Clippy (full workspace)
33-
if: matrix.rust != '1.85'
34-
run: cargo clippy --workspace --all-features -- -D warnings
33+
if: matrix.rust != '1.86'
34+
run: cargo clippy --workspace --all-features --locked -- -D warnings
3535
continue-on-error: ${{ matrix.rust == 'nightly' }}
3636

3737
- name: Build
38-
run: cargo build --workspace
38+
run: cargo build --workspace --locked
3939

4040
- name: Build with features
41-
run: cargo build --workspace --features postgres,mysql
41+
run: cargo build --workspace --features postgres,mysql --locked
4242

4343
- name: Test (default features)
44-
run: cargo test --workspace
44+
run: cargo test --workspace --locked
4545

4646
- name: Test (no default features)
47-
run: cargo test --workspace --no-default-features
47+
run: cargo test --workspace --no-default-features --locked
4848

4949
- name: Test (sqlite)
50-
run: cargo test --workspace --features sqlite
50+
run: cargo test --workspace --features sqlite --locked
5151

5252
- name: Test (postgres)
53-
run: cargo test --workspace --features postgres
53+
run: cargo test --workspace --features postgres --locked
5454

5555
- name: Test (mysql)
56-
run: cargo test --workspace --features mysql
56+
run: cargo test --workspace --features mysql --locked
5757

5858
- name: Test (rocksdb)
59-
run: cargo test --workspace --features rocksdb
59+
run: cargo test --workspace --features rocksdb --locked
6060

6161
- name: Install wasm-pack
6262
uses: taiki-e/install-action@v2

crates/aegis-core/src/engine/analysis/graph.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ impl GraphEngine {
2020
) -> AegisResult<ReachabilityReport> {
2121
// Cache check
2222
let cache_key = format!("reach:{}:{}:{}", resource.as_str(), max_depth, max_nodes);
23-
if let Some(ttl) = cache_ttl_ms
24-
&& let Some(cached) = self.get_cached_analysis(&cache_key, ttl)
25-
{
26-
return Ok(cached);
23+
if let Some(ttl) = cache_ttl_ms {
24+
if let Some(cached) = self.get_cached_analysis(&cache_key, ttl) {
25+
return Ok(cached);
26+
}
2727
}
2828

2929
let start = Instant::now();
@@ -210,10 +210,10 @@ impl GraphEngine {
210210
}
211211

212212
fn set_cached_analysis(&self, key: &str, value: &impl serde::Serialize, ttl_ms: u64) {
213-
if let Ok(mut cache) = self.analysis_cache.lock()
214-
&& let Ok(json) = serde_json::to_string(value)
215-
{
216-
cache.insert(key.to_string(), (Instant::now(), ttl_ms, json));
213+
if let Ok(mut cache) = self.analysis_cache.lock() {
214+
if let Ok(json) = serde_json::to_string(value) {
215+
cache.insert(key.to_string(), (Instant::now(), ttl_ms, json));
216+
}
217217
}
218218
}
219219
}

crates/aegis-core/src/engine/cache.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -108,10 +108,10 @@ impl DecisionCache {
108108
self.access_order.retain(|k| k != &key);
109109

110110
// Evict LRU entry if at capacity
111-
if self.entries.len() >= self.capacity
112-
&& let Some(lru_key) = self.access_order.pop_front()
113-
{
114-
self.entries.remove(&lru_key);
111+
if self.entries.len() >= self.capacity {
112+
if let Some(lru_key) = self.access_order.pop_front() {
113+
self.entries.remove(&lru_key);
114+
}
115115
}
116116

117117
self.access_order.push_back(key.clone());
@@ -228,10 +228,10 @@ impl TraversalCache {
228228
self.access_order.retain(|k| k != &key);
229229

230230
// Evict LRU entry if at capacity
231-
if self.entries.len() >= self.capacity
232-
&& let Some(lru_key) = self.access_order.pop_front()
233-
{
234-
self.entries.remove(&lru_key);
231+
if self.entries.len() >= self.capacity {
232+
if let Some(lru_key) = self.access_order.pop_front() {
233+
self.entries.remove(&lru_key);
234+
}
235235
}
236236

237237
self.access_order.push_back(key.clone());

crates/aegis-core/src/engine/enforcement_history.rs

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -240,17 +240,18 @@ impl GraphEngine {
240240
}
241241

242242
// Periodically purge expired events (every ~1000 records)
243-
if cfg.max_days > 0
244-
&& let Ok(mut events) = self.enforcement_events.lock()
245-
&& events.len() % 1000 == 0
246-
{
247-
let cutoff = chrono::Utc::now() - chrono::Duration::days(cfg.max_days as i64);
248-
let cutoff_str = cutoff.to_rfc3339();
249-
while let Some(front) = events.front() {
250-
if front.timestamp < cutoff_str {
251-
events.pop_front();
252-
} else {
253-
break;
243+
if cfg.max_days > 0 {
244+
if let Ok(mut events) = self.enforcement_events.lock() {
245+
if events.len() % 1000 == 0 {
246+
let cutoff = chrono::Utc::now() - chrono::Duration::days(cfg.max_days as i64);
247+
let cutoff_str = cutoff.to_rfc3339();
248+
while let Some(front) = events.front() {
249+
if front.timestamp < cutoff_str {
250+
events.pop_front();
251+
} else {
252+
break;
253+
}
254+
}
254255
}
255256
}
256257
}

crates/aegis-core/src/engine/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -265,10 +265,10 @@ impl GraphEngine {
265265

266266
/// Emit a structured log event through the registered callback (if any).
267267
fn emit_log(&self, level: hooks::LogLevel, message: &str, context: &str) {
268-
if let Ok(guard) = self.logger.lock()
269-
&& let Some(ref logger) = *guard
270-
{
271-
logger(level, message, context);
268+
if let Ok(guard) = self.logger.lock() {
269+
if let Some(ref logger) = *guard {
270+
logger(level, message, context);
271+
}
272272
}
273273
}
274274

crates/aegis-core/src/engine/partition.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,10 @@ impl PartitionManager {
5353

5454
pub fn check_rate_limit(&self, partition_id: &PartitionId) -> AegisResult<()> {
5555
let key = partition_id.to_string();
56-
if let Ok(map) = self.partitions.lock()
57-
&& let Some(state) = map.get(&key)
58-
{
59-
return state.rate_limiter.check(&key, RateLimitOp::Check);
56+
if let Ok(map) = self.partitions.lock() {
57+
if let Some(state) = map.get(&key) {
58+
return state.rate_limiter.check(&key, RateLimitOp::Check);
59+
}
6060
}
6161
// If no partition-specific state, use default
6262
self.default_partition

crates/aegis-core/src/engine/ratelimit.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,14 +75,14 @@ impl TokenBucketRateLimiter {
7575

7676
// Evict the least-recently-accessed entry if we need to insert a new key
7777
// and the map is at capacity.
78-
if !buckets.contains_key(key)
79-
&& buckets.len() >= self.config.max_keys
80-
&& let Some(oldest_key) = buckets
78+
if !buckets.contains_key(key) && buckets.len() >= self.config.max_keys {
79+
if let Some(oldest_key) = buckets
8180
.iter()
8281
.min_by_key(|(_, state)| state.last_accessed)
8382
.map(|(k, _)| k.clone())
84-
{
85-
buckets.remove(&oldest_key);
83+
{
84+
buckets.remove(&oldest_key);
85+
}
8686
}
8787

8888
let state = buckets.entry(key.to_string()).or_insert_with(|| {

crates/aegis-core/src/schema/parser.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -209,16 +209,16 @@ pub fn lint_schema(schema: &Schema) -> LintResult {
209209

210210
// Check condition syntax on permissions
211211
for (perm_name, perm_def) in &type_def.permissions {
212-
if let Some(ref cond) = perm_def.condition
213-
&& let Err(e) = crate::engine::condition::parse_condition(cond)
214-
{
215-
diagnostics.push(LintDiagnostic {
212+
if let Some(ref cond) = perm_def.condition {
213+
if let Err(e) = crate::engine::condition::parse_condition(cond) {
214+
diagnostics.push(LintDiagnostic {
216215
severity: LintSeverity::Error,
217216
message: format!(
218217
"permission '{perm_name}' on type '{type_name}' has invalid condition syntax: {e}"
219218
),
220219
location: Some(format!("types.{type_name}.permissions.{perm_name}.condition")),
221220
});
221+
}
222222
}
223223
}
224224

crates/aegis-core/src/schema/validator.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -100,16 +100,16 @@ pub fn lint_schema(schema: &Schema, strict: bool) -> LintReport {
100100

101101
// Check condition syntax validity on permissions
102102
for (perm_name, perm_def) in &type_def.permissions {
103-
if let Some(ref cond) = perm_def.condition
104-
&& let Err(e) = crate::engine::condition::parse_condition(cond)
105-
{
106-
let msg = format!(
107-
"permission '{perm_name}' on type '{type_name}' has invalid condition syntax: {e}"
108-
);
109-
if strict {
110-
errors.push(msg);
111-
} else {
112-
warnings.push(msg);
103+
if let Some(ref cond) = perm_def.condition {
104+
if let Err(e) = crate::engine::condition::parse_condition(cond) {
105+
let msg = format!(
106+
"permission '{perm_name}' on type '{type_name}' has invalid condition syntax: {e}"
107+
);
108+
if strict {
109+
errors.push(msg);
110+
} else {
111+
warnings.push(msg);
112+
}
113113
}
114114
}
115115
}

crates/aegis-core/src/storage/rocksdb.rs

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
use crate::engine::enforcement_history::EnforcementEvent;
2-
use crate::engine::policy_lifecycle::PolicyDraft;
3-
use crate::engine::scheduler::{AnalysisRun, AnalysisSchedule};
41
use crate::error::{AegisError, AegisResult};
52
use crate::storage::traits::{
63
BackendType, IntegrityReport, PolicyVersion, StorageBackend, StorageMeta, StorageTransaction,
@@ -12,12 +9,9 @@ use crate::types::{
129
TupleMutation,
1310
};
1411
use chrono::{DateTime, Utc};
15-
use rocksdb::{
16-
BlockBasedOptions, Cache, ColumnFamily, ColumnFamilyDescriptor, DB, DBIterator, Direction,
17-
IteratorMode, Options,
18-
};
19-
use serde_json;
12+
use rocksdb::{BlockBasedOptions, Cache, ColumnFamily, DB, Direction, IteratorMode, Options};
2013
use std::collections::HashMap;
14+
use std::sync::Arc;
2115
use uuid::Uuid;
2216

2317
const CF_META: &str = "meta";
@@ -59,7 +53,7 @@ fn tuple_from_value(value: &[u8]) -> AegisResult<RelationshipTuple> {
5953
}
6054

6155
pub struct RocksDbStorage {
62-
db: DB,
56+
db: Arc<DB>,
6357
node_id: Uuid,
6458
revision_mutex: std::sync::Mutex<()>,
6559
actor_identity: std::sync::Mutex<Option<String>>,
@@ -91,8 +85,10 @@ impl RocksDbStorage {
9185
CF_ENFORCEMENT_EVENTS,
9286
];
9387

94-
let db = DB::open_cf(&opts, path, cfs)
95-
.map_err(|e| AegisError::StorageConnection(e.to_string()))?;
88+
let db = Arc::new(
89+
DB::open_cf(&opts, path, cfs)
90+
.map_err(|e| AegisError::StorageConnection(e.to_string()))?,
91+
);
9692

9793
// Initialize revision if not present
9894
let cf_meta = db
@@ -123,7 +119,7 @@ impl RocksDbStorage {
123119

124120
Ok(Self {
125121
db,
126-
node_id,
122+
node_id: Uuid::new_v4(),
127123
revision_mutex: std::sync::Mutex::new(()),
128124
actor_identity: std::sync::Mutex::new(None),
129125
})
@@ -276,7 +272,7 @@ impl RocksDbStorage {
276272
&self,
277273
partition_id: &PartitionId,
278274
tuple: &RelationshipTuple,
279-
revision: Revision,
275+
_revision: Revision,
280276
) -> AegisResult<()> {
281277
let cf_tuples = self
282278
.db
@@ -315,7 +311,7 @@ impl RocksDbStorage {
315311
&self,
316312
partition_id: &PartitionId,
317313
key: &TupleKey,
318-
revision: Revision,
314+
_revision: Revision,
319315
) -> AegisResult<()> {
320316
let cf_tuples = self
321317
.db
@@ -1092,7 +1088,7 @@ impl StorageBackend for RocksDbStorage {
10921088

10931089
let next_cursor = if (offset as usize + tuples.len()) < total {
10941090
Some(PaginationCursor {
1095-
offset: offset + limit,
1091+
offset: offset + limit as u64,
10961092
revision,
10971093
})
10981094
} else {
@@ -1111,7 +1107,7 @@ impl StorageBackend for RocksDbStorage {
11111107
}
11121108

11131109
fn current_token(&self) -> AegisResult<RevisionToken> {
1114-
let revision = self.current_revision()?;
1110+
let revision = self.current_revision(&PartitionId::default())?;
11151111
Ok(RevisionToken::new(revision, self.node_id))
11161112
}
11171113

@@ -1220,8 +1216,8 @@ impl StorageBackend for RocksDbStorage {
12201216
break;
12211217
}
12221218

1219+
let event_obj = event["object"].as_str().unwrap_or("").to_string();
12231220
if let Some(obj) = object {
1224-
let event_obj = event["object"].as_str().unwrap_or("");
12251221
if event_obj != obj.as_str() {
12261222
continue;
12271223
}
@@ -1250,7 +1246,7 @@ impl StorageBackend for RocksDbStorage {
12501246
action,
12511247
subject: event["subject"].as_str().unwrap_or("").to_string(),
12521248
relation: event["relation"].as_str().unwrap_or("").to_string(),
1253-
object: event_obj.to_string(),
1249+
object: event_obj,
12541250
timestamp,
12551251
metadata,
12561252
identity,
@@ -1733,7 +1729,7 @@ impl StorageBackend for RocksDbStorage {
17331729
while iter.valid() {
17341730
if let (Some(key), Some(value)) = (iter.key(), iter.value()) {
17351731
let key_str = String::from_utf8_lossy(key);
1736-
if let Ok(version_num) = key_str.parse::<u32>() {
1732+
if key_str.parse::<u32>().is_ok() {
17371733
if let Ok(pv) = serde_json::from_slice::<PolicyVersion>(value) {
17381734
versions.push(pv);
17391735
}
@@ -1904,7 +1900,7 @@ impl StorageBackend for RocksDbStorage {
19041900

19051901
/// A RocksDB transaction using WriteBatch for atomicity.
19061902
pub struct RocksDbTransaction {
1907-
db: DB,
1903+
db: Arc<DB>,
19081904
partition_id: String,
19091905
batch: rocksdb::WriteBatch,
19101906
cf_tuples: rocksdb::ColumnFamily,

0 commit comments

Comments
 (0)