Skip to content

Add nested graph tracking support#94

Merged
muukii merged 1 commit intomainfrom
feature/nested-graph-tracking
Feb 3, 2026
Merged

Add nested graph tracking support#94
muukii merged 1 commit intomainfrom
feature/nested-graph-tracking

Conversation

@muukii
Copy link
Copy Markdown
Contributor

@muukii muukii commented Feb 3, 2026

Summary

  • Enable nesting withGraphTrackingGroup and withGraphTrackingMap within each other
  • When a parent group/map re-executes, all nested children are automatically cancelled and recreated
  • Prevents subscription accumulation and ensures correct re-execution behavior

Changes

New Files

  • GraphTrackingCancellable.swift: Tree-structured Cancellable class for managing parent-child relationships
  • NestedGraphTrackingTests.swift: 13 comprehensive test cases

Modified Files

  • ThreadLocal.swift: Added currentCancellable to track parent scope
  • withGraphTrackingGroup.swift: Updated for nested tracking support
  • withGraphTrackingMap.swift: Updated for nested tracking support

Usage Example

let items = Stored(wrappedValue: [1, 2, 3])

withGraphTracking {
  withGraphTrackingGroup {  // parent
    for item in items.wrappedValue {
      withGraphTrackingGroup {  // child - cancelled when parent re-executes
        // ...
      }
    }
  }
}

Conditional Nesting

let showDetails = Stored(wrappedValue: false)

withGraphTracking {
  withGraphTrackingGroup {
    if showDetails.wrappedValue {
      withGraphTrackingMap { ... } onChange: { ... }  // created/destroyed based on condition
    }
  }
}

Test plan

  • All 99 existing tests pass
  • 13 new nested tracking tests covering:
    • Basic nested groups/maps
    • 3+ level deep nesting
    • Sibling group independence
    • Mixed group/map nesting
    • Conditional nested tracking (if/switch)
    • Dynamic item lists
    • Memory/cancellation behavior

🤖 Generated with Claude Code

@claude
Copy link
Copy Markdown
Contributor

claude bot commented Feb 3, 2026

Claude finished @muukii's task —— View job


PR Review: Add nested graph tracking support

Todo List:

  • Read and analyze all changed files
  • Review GraphTrackingCancellable architecture
  • Analyze modifications to tracking functions
  • Examine test coverage and quality
  • Check for potential issues (bugs, performance, security)
  • Provide comprehensive feedback

🎯 Overall Assessment

This is a well-designed and thoroughly implemented feature that adds robust nested graph tracking capabilities. The implementation follows good Swift practices and integrates cleanly with the existing architecture.

Strengths

Architecture & Design

  • Clean separation of concerns: GraphTrackingCancellable handles the tree hierarchy, while tracking functions focus on their core responsibilities
  • Excellent integration: Minimal changes to existing APIs while adding powerful new functionality
  • Thread safety: Proper use of OSAllocatedUnfairLock throughout
  • Memory management: Smart use of weak references and automatic cleanup prevents retain cycles

Implementation Quality

  • Consistent patterns: Both withGraphTrackingGroup and withGraphTrackingMap follow identical nesting implementation
  • Robust error handling: Proper guard clauses and assertion failures for misuse
  • Clear lifecycle management: cancelChildren() before re-execution prevents subscription accumulation

Documentation & Testing

  • Exceptional documentation: Comprehensive examples showing real-world usage patterns
  • Thorough test coverage: 13 tests covering all edge cases including conditional nesting, deep nesting, and memory management
  • Clear examples: The conditional tracking examples are particularly valuable

🔍 Code Review Findings

GraphTrackingCancellable.swift ⭐⭐⭐⭐⭐

Excellent implementation of tree-structured cancellation:

final class GraphTrackingCancellable: Cancellable, @unchecked Sendable {
  private struct State {
    var onCancel: (() -> Void)?
    var children: [GraphTrackingCancellable] = []
  }
  private let state: OSAllocatedUnfairLock<State>
  private weak var parent: GraphTrackingCancellable?

Strengths:

  • Thread-safe design: OSAllocatedUnfairLock protects mutable state
  • Memory safe: Weak parent references prevent retain cycles
  • Clean API: addChild() and cancelChildren() methods are intuitive
  • Proper cleanup: removeFromParent() ensures no dangling references

Minor observation (not an issue):

  • The @unchecked Sendable is justified since thread-safety is properly implemented with locks

withGraphTrackingGroup.swift ⭐⭐⭐⭐⭐

Excellent integration of nested tracking:

withContinuousStateGraphTracking(
  apply: {
    scopeCancellable.cancelChildren()
    ThreadLocal.currentCancellable.withValue(scopeCancellable) {
      _handlerBox.withLock { $0?.handler() }
    }
  }
)

Strengths:

  • Perfect timing: cancelChildren() called before re-execution prevents accumulation
  • Clean nesting: ThreadLocal context properly propagates down the hierarchy
  • Consistent registration: Handles both root and nested cases elegantly

withGraphTrackingMap.swift ⭐⭐⭐⭐⭐

Identical pattern to group tracking - excellent consistency.

ThreadLocal.swift ⭐⭐⭐⭐⭐

Minimal, focused change:

static let currentCancellable: ThreadLocalValue<GraphTrackingCancellable> = .init(key: "org.vergegroup.state-graph.currentCancellable")

Perfect addition that follows existing patterns.

Test Coverage ⭐⭐⭐⭐⭐

Exceptional test suite covering:

  • ✅ Basic nested groups and maps
  • ✅ Deep nesting (3+ levels)
  • ✅ Sibling independence
  • ✅ Mixed group/map combinations
  • ✅ Conditional tracking scenarios
  • ✅ Dynamic item lists
  • ✅ Memory/cancellation behavior

Particularly impressed by:

  • conditionalNestedTracking() - Tests creation/destruction based on feature flags
  • switchBetweenNestedTrackings() - Complex state machine scenarios
  • childrenNotLeakedOnReexecution() - Memory leak verification

🚀 Performance Considerations

Positive:

  • Lazy creation: Nested groups only created when conditions are met
  • Efficient cleanup: cancelChildren() prevents subscription accumulation
  • Lock granularity: Fine-grained locking in GraphTrackingCancellable

No performance concerns identified.

🔒 Security Assessment

No security concerns. This is purely a reactive programming enhancement with:

  • No external dependencies
  • No network operations
  • No file system access
  • Proper memory management

🐛 Potential Issues Found

None - Clean Implementation

I carefully reviewed for common issues but found:

  • ✅ No retain cycles (proper weak references)
  • ✅ No race conditions (proper locking)
  • ✅ No memory leaks (automatic cleanup)
  • ✅ No deadlocks (non-recursive locks used correctly)

📊 Test Coverage Assessment

Coverage: Excellent (5/5)

  • Edge cases: Covered comprehensively
  • Real-world scenarios: Conditional tracking tests mirror actual usage
  • Memory testing: Explicit leak verification
  • Async behavior: Proper use of Task.sleep for timing

💡 Suggestions for Consideration

Documentation Enhancement (Optional)

Consider adding a migration guide section showing how to refactor existing tracking code to take advantage of nesting:

// Before: Manual subscription management
// After: Automatic with nested tracking

Performance Monitoring (Future)

For future iterations, consider adding metrics for:

  • Maximum nesting depth
  • Number of children per parent
  • Re-execution frequency

🏆 Final Verdict

Recommendation: ✅ APPROVE

This PR represents exemplary software engineering:

  • Clean, well-tested implementation
  • Excellent documentation
  • Backward compatible
  • Follows established patterns
  • Comprehensive test coverage
  • No security or performance concerns

The nested graph tracking feature will significantly enhance the library's usability for complex reactive scenarios while maintaining the library's high standards for code quality.

Enable nesting withGraphTrackingGroup and withGraphTrackingMap within each other.
When a parent group/map re-executes, all nested children are automatically
cancelled and recreated.

Key changes:
- Add GraphTrackingCancellable: tree-structured Cancellable for managing
  parent-child relationships between tracking scopes
- Add ThreadLocal.currentCancellable to track the current parent scope
- Update withGraphTrackingGroup/Map to:
  - Create scopeCancellable for each scope
  - Cancel children before re-execution via cancelChildren()
  - Register with parent (nested) or root subscriptions (top-level)
- Add comprehensive tests for nested tracking scenarios including:
  - Basic nested groups/maps
  - 3+ level deep nesting
  - Sibling independence
  - Conditional nested tracking (if/switch)
  - Dynamic item lists

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@muukii muukii force-pushed the feature/nested-graph-tracking branch from fa52285 to 364425e Compare February 3, 2026 06:19
@muukii muukii merged commit 5cb4c93 into main Feb 3, 2026
3 checks passed
@muukii muukii deleted the feature/nested-graph-tracking branch February 3, 2026 06:36
muukii added a commit that referenced this pull request Feb 3, 2026
Document the nested tracking feature added in #94, including:
- How nested groups/maps are automatically cancelled and recreated
- Conditional tracking example with feature flags
- Key features and use cases

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant