Implementation already complete. All 9 integration tests pass: - Self-cycle detection returns PdfNull + STRUCT_CIRCULAR_REF - 3-cycle (A->B->C->A) detection - Legitimate objects cache after cycle - 90%+ cache hit ratio - LRU eviction at 4097 entries - Random sequences terminate Closes pdftract-4ij2.
3.4 KiB
3.4 KiB
pdftract-4ij2: Per-thread cycle detection + LRU object cache
Summary
This bead's implementation was already complete in the codebase. The per-thread cycle detection and LRU object cache features have been fully implemented with comprehensive tests.
Implementation Verification
Files Modified (already exist)
| File | Purpose |
|---|---|
crates/pdftract-core/src/parser/object/cycle.rs |
Per-thread cycle detection with thread_local! RefCell<HashSet<ObjRef>> |
crates/pdftract-core/src/parser/object/cache.rs |
LRU cache with Mutex<LruCache<ObjRef, Arc<PdfObject>>>, 4096 capacity |
crates/pdftract-core/src/parser/object/types.rs |
ObjRef, PdfObject types |
crates/pdftract-core/tests/test_cycle_detection.rs |
Integration tests |
Acceptance Criteria Status
| Criterion | Status | Test |
|---|---|---|
| Self-cycle returns PdfNull + STRUCT_CIRCULAR_REF, no stack overflow | ✅ PASS | test_self_cycle_returns_null_with_diagnostic |
| 3-cycle (A->B->C->A) detection | ✅ PASS | test_three_cycle_abc_detected |
| Legitimate objects cached after cycle detection | ✅ PASS | test_legitimate_object_after_cycle |
| Cache hit ratio >= 90% (1000 accesses of 100 objects) | ✅ PASS | test_cache_hit_ratio_90_percent |
| LRU eviction at 4097 entries (4096 capacity) | ✅ PASS | test_lru_eviction_4097_entries |
| Random resolution sequences terminate | ✅ PASS | test_random_resolution_sequences_terminate |
Implementation Details Verified
Per-thread Cycle Detection (cycle.rs)
- ✅
thread_local! { static RESOLVING: RefCell<HashSet<ObjRef>> ... } - ✅
ResolutionGuardRAII guard for automatic cleanup - ✅
is_resolving(obj_ref)function for cycle checking - ✅ Thread-local isolation for rayon parallelism
LRU Object Cache (cache.rs)
- ✅
lru = "0.12"crate inCargo.toml - ✅
Mutex<LruCache<ObjRef, Arc<PdfObject>>>with 4096 capacity - ✅
CacheStats { hits: u64, misses: u64 }tracking - ✅
MAX_RESOLUTION_DEPTH: u16 = 256depth limiting - ✅ Thread-local depth counter with
RESOLUTION_DEPTH - ✅ PdfNull NOT cached (prevents poisoning)
- ✅
CacheResolutionGuardcombining cycle + depth tracking
Test Results
$ cargo test --package pdftract-core --test test_cycle_detection
running 9 tests
test test_self_cycle_returns_null_with_diagnostic ... ok
test test_three_cycle_abc_detected ... ok
test test_legitimate_object_after_cycle ... ok
test test_cache_hit_ratio_90_percent ... ok
test test_lru_eviction_4097_entries ... ok
test test_resolution_depth_limit_256 ... ok
test test_thread_local_cycle_detection ... ok
test test_null_not_cached ... ok
test test_random_resolution_sequences_terminate ... ok
test result: ok. 9 passed; 0 failed; 0 ignored
Unit Tests (cache.rs)
All 21 unit tests in cache.rs pass:
- Cache hit/miss tracking
- Hit ratio calculation
- Null not cached
- LRU eviction
- Cycle detection
- Depth limit enforcement
- Thread-local independence
- Guard cleanup on panic
- peek_lru/is_lru helpers
Diagnostic Codes Verified
| Code | Emitted When | Message Includes |
|---|---|---|
STRUCT_CIRCULAR_REF |
Cycle detected | ObjRef in msg |
STRUCT_DEPTH_EXCEEDED |
Depth > 256 | Limit value in msg |
Conclusion
The implementation is complete and all acceptance criteria PASS. No code changes were required for this bead—the feature was already implemented.