Make Gitlab::GrapeOpenapi::Generator a Singleton
Gitlab::GrapeOpenapi::Generator currently is intended to function as a Singleton in the gitlab-grape-openapi gem. However, there is nothing preventing people initializing multiple instances of the class in the future, thus breaking the assumption that the class functions as a Singleton.
Investigate whether it makes sense to enforce the Singleton pattern onto the class, e.g., by using Ruby's Singleton module, and if it does, implement the change.
Why This Matters
- Prevents accidental misuse of the class by enforcing the singleton pattern at the language level.
- Reduces maintenance burden by making the design intent explicit in code.
- Eliminates potential bugs from multiple instances being created.
Acceptance Criteria
-
The
Gitlab::GrapeOpenapi::Generatorclass uses Ruby'sSingletonmodule or a similar solution that achieves the same result of enforcing the Singleton pattern - Multiple instantiation attempts return the same instance
- Existing code that relies on the singleton behavior continues to work
- Tests verify singleton behavior is enforced
OR
- Justify in the comments the reason for NOT enforcing the Singleton pattern
Definition of Done
-
Code changes merged to
gitlab-grape-openapigem - All tests passing (new singleton tests + existing tests)
- Documentation/comments updated if needed
Potential Risks / Considerations
- Check if any code currently relies on creating multiple instances (unlikely but worth verifying)
- Ensure thread-safety if the singleton is used in multi-threaded contexts
Resources
Analysis by Duo:
Advantages of implementing Singleton:
1. Memory efficiency - Only one instance would exist, reducing memory overhead when generating OpenAPI specs multiple times across the application 2. Consistent state - The @schema_registry and @tag_registry would be shared across all usages, preventing duplicate schema registrations 3. Performance optimization - Entity and tag conversion could be cached and reused if the same API classes are processed multiple times 4. Simplified access - No need to pass the generator instance around; could access via Generator.instanceDisadvantages of implementing Singleton:
1. Testing complexity - Singleton state persists between tests, requiring explicit cleanup in test suites. The current spec creates fresh instances per test, which would break 2. Thread safety concerns - The registries (@schema_registry, @tag_registry) would need synchronization mechanisms for concurrent access 3. Configuration inflexibility - Currently accepts different api_classes and entity_classes per instantiation. Singleton would lock this to first initialization or require complex reset logic 4. State pollution - Registries accumulate schemas/tags across multiple generate calls, potentially mixing unrelated API specifications 5. Violates single responsibility - The class would manage both generation logic AND instance lifecycle 6. Harder to parallelize - Cannot generate multiple independent OpenAPI specs simultaneously (e.g., for different API versions)Current usage pattern benefits:
The current design where each generate call creates a fresh instance with clean registries is actually more appropriate for this use case because:
* Each OpenAPI spec generation is independent * No shared state needed between generations * Tests remain isolated and predictable * Supports generating specs for different API class combinations
Edited by 🤖 GitLab Bot 🤖