[FSSDK-11776] fixing memory leak with project
Summary
This pull request introduces a robust caching mechanism to the Optimizely::Project class to prevent memory leaks caused by repeated SDK initialization, especially in high-throughput environments (like Rails apps). It adds a static instance cache, ensures proper cleanup of background threads, and provides new APIs for cache management. Extensive tests and documentation are included to guarantee safe usage and clarify best practices.
Key changes include:
Memory Leak Prevention & Caching Logic
- Introduced a class-level instance cache in
Optimizely::Project, with thread-safe access, to ensure that repeated initialization with the same static datafile returns the same instance, preventing unbounded thread growth and memory leaks. Instances are only cached for static datafile configurations and not for dynamic options (e.g.,sdk_key, custom managers, etc.). - Added
.get_or_create_instance,.clear_instance_cache!, and.cached_instance_countAPIs to manage cached instances, and ensured that closing an instance removes it from the cache [1] [2].
Resource Cleanup & Thread Management
- Implemented a finalizer using
ObjectSpace.define_finalizerto ensure background threads (config_manager,event_processor,odp_manager) are cleaned up even ifcloseis not called explicitly, further reducing risk of leaks. - Updated the
closemethod to remove the instance from the cache and stop all background resources safely.
Testing & Safety Guarantees
- Added comprehensive specs in
spec/project_caching_spec.rbandspec/memory_leak_prevention_spec.rbto verify caching logic, proper resource cleanup, thread stability, and to ensure that only safe configurations are cached [1] [2].
Documentation
- Added a new
.github/copilot-instructions.mdfile detailing the SDK architecture, memory safety best practices, and correct usage patterns to prevent memory leaks in production environments.
These improvements make the SDK safer for production use, especially in multi-threaded and long-running server environments.
Memory leak prevention and caching:
- Added class-level instance cache and
.get_or_create_instanceAPI toOptimizely::Projectfor safe reuse of static datafile configurations, preventing memory leaks from repeated initialization. - Ensured only safe configurations are cached (static datafile, no dynamic options), and provided APIs for clearing and monitoring the cache.
Resource cleanup and thread management:
- Added a finalizer to clean up background threads if
closeis not called, and updatedcloseto remove the instance from the cache [1] [2].
Testing and safety guarantees:
- Introduced new specs to verify caching, thread stability, correct cleanup, and memory safety in various usage patterns (
spec/project_caching_spec.rb,spec/memory_leak_prevention_spec.rb) [1] [2].
Documentation and usage guidance:
- Added
.github/copilot-instructions.mdwith architecture overview, memory leak prevention advice, and best practices for safe SDK usage.
Test plan
Pass automated tests