Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TT-13139] Request times out in some cases when sending input via http inputs #6601

Open
wants to merge 9 commits into
base: master
Choose a base branch
from

Conversation

buraksezer
Copy link
Contributor

@buraksezer buraksezer commented Oct 3, 2024

User description

TT-13139
Summary Request times out in some cases when sending input via http inputs
Type Bug Bug
Status In Dev
Points N/A
Labels -

Cherry-picked stream caching feature from this branch: #6538

Two new integration tests have been added to test input http -> output http scenario. See this issue for the details: https://tyktech.atlassian.net/browse/TT-13139

Closing the previous one: #6592


PR Type

Enhancement, Tests


Description

  • Implemented stream caching and garbage collection in the StreamingMiddleware to manage inactive streams and improve performance.
  • Added new fields and methods to handle stream activity and caching efficiently.
  • Introduced a garbage collection routine to periodically clean up inactive stream managers.
  • Added integration tests for single and multiple client scenarios, focusing on HTTP server input and WebSocket output.
  • Verified message distribution and handling in the new tests to ensure correct functionality.

Changes walkthrough 📝

Relevant files
Enhancement
mw_streaming.go
Implement stream caching and garbage collection in StreamingMiddleware

gateway/mw_streaming.go

  • Introduced stream caching and garbage collection for inactive streams.
  • Added new fields to manage stream activity and cache.
  • Implemented a garbage collection routine for stream managers.
  • Updated stream manager creation to utilize caching.
  • +98/-20 
    Tests
    mw_streaming_test.go
    Add integration tests for HTTP server streaming scenarios

    gateway/mw_streaming_test.go

  • Added tests for single and multiple client streaming scenarios.
  • Implemented test for HTTP server input and WebSocket output.
  • Verified message distribution and handling in tests.
  • +137/-0 

    💡 PR-Agent usage: Comment /help "your question" on any pull request to receive relevant information

    @buger
    Copy link
    Member

    buger commented Oct 3, 2024

    I'm a bot and I 👍 this PR title. 🤖

    Copy link
    Contributor

    github-actions bot commented Oct 3, 2024

    PR Reviewer Guide 🔍

    Here are some key observations to aid the review process:

    ⏱️ Estimated effort to review: 4 🔵🔵🔵🔵⚪
    🧪 PR contains tests
    🔒 No security concerns identified
    ⚡ Recommended focus areas for review

    Concurrency Concerns
    The use of sync.Map and atomic operations suggests that concurrency is a concern. However, it's essential to ensure that all operations on shared resources are safe and that there are no race conditions or deadlocks.

    Error Handling
    The error handling in the stream removal and garbage collection processes should be reviewed to ensure that errors are handled appropriately and do not lead to inconsistent states or resource leaks.

    Resource Management
    The implementation of garbage collection for stream managers should be carefully reviewed to ensure that it effectively frees up resources without prematurely removing active streams or causing interruptions.

    Copy link
    Contributor

    github-actions bot commented Oct 3, 2024

    API Changes

    --- prev.txt	2024-10-03 12:25:14.192088526 +0000
    +++ current.txt	2024-10-03 12:25:08.273121874 +0000
    @@ -7563,6 +7563,12 @@
     	ErrOAuthClientDeleted               = "oauth.client_deleted"
     )
     const (
    +	// ExtensionTykStreaming is the oas extension for tyk streaming
    +	ExtensionTykStreaming = "x-tyk-streaming"
    +	StreamGCInterval      = 1 * time.Minute
    +	StreamInactiveLimit   = 10 * time.Minute
    +)
    +const (
     	ResetQuota              string = "resetQuota"
     	CertificateRemoved      string = "CertificateRemoved"
     	CertificateAdded        string = "CertificateAdded"
    @@ -7614,10 +7620,6 @@
         The name for event handlers as defined in the API Definition JSON/BSON
         format
     
    -const (
    -	// ExtensionTykStreaming is the oas extension for tyk streaming
    -	ExtensionTykStreaming = "x-tyk-streaming"
    -)
     const ListDetailed = "detailed"
     const LoopScheme = "tyk"
     const OIDPREFIX = "openid"

    Copy link
    Contributor

    github-actions bot commented Oct 3, 2024

    PR Code Suggestions ✨

    Explore these optional code suggestions:

    CategorySuggestion                                                                                                                                    Score
    Security
    Improve security by using a more secure hash function for generating cache keys

    Replace the MD5 hash function with a more secure hash function like SHA-256 for
    generating cache keys, as MD5 is vulnerable to collision attacks.

    gateway/mw_streaming.go [231]

    -cacheKey := fmt.Sprintf("%x", md5.Sum(configJSON))
    +cacheKey := fmt.Sprintf("%x", sha256.Sum256(configJSON))
    Suggestion importance[1-10]: 9

    Why: The suggestion to replace MD5 with SHA-256 for generating cache keys enhances security by mitigating collision vulnerabilities associated with MD5. This is a significant improvement in terms of security best practices.

    9
    Resource management
    Ensure proper resource cleanup by calling the cancel function for each stream

    Ensure that the cancel function from the context is called for each stream in
    removeStreamManager to properly release resources and avoid potential memory leaks.

    gateway/mw_streaming.go [143]

    +sm.cancel()
     s.streamManagerCache.Delete(cacheKey)
    Suggestion importance[1-10]: 8

    Why: Adding a call to the cancel function ensures proper resource cleanup and prevents potential memory leaks, which is crucial for maintaining application stability and performance.

    8
    Error handling
    Add error handling for JSON marshaling to enhance robustness

    Add error handling for the json.Marshal operation when creating the cache key to
    handle potential serialization issues gracefully.

    gateway/mw_streaming.go [230]

    -configJSON, _ := json.Marshal(streamsConfig)
    +configJSON, err := json.Marshal(streamsConfig)
    +if err != nil {
    +    s.Logger().Errorf("Failed to marshal streams config: %v", err)
    +    return nil
    +}
    Suggestion importance[1-10]: 7

    Why: Introducing error handling for the JSON marshaling process improves the robustness of the code by ensuring that serialization issues are caught and logged, preventing potential runtime errors.

    7
    Concurrency management
    Improve thread safety and performance by reviewing locking mechanisms around shared resources

    Consider using a more precise locking mechanism or review the necessity of locking
    around lastActivity.Store(time.Now()) to avoid potential race conditions or
    performance bottlenecks.

    gateway/mw_streaming.go [497-499]

    +h.sm.routeLock.Lock()
     h.sm.lastActivity.Store(time.Now())
    +h.sm.routeLock.Unlock()
    Suggestion importance[1-10]: 6

    Why: The suggestion to add locking around the lastActivity.Store operation addresses potential race conditions, enhancing thread safety. However, it may introduce performance bottlenecks, so the impact is moderate.

    6

    Copy link

    sonarcloud bot commented Oct 3, 2024

    Quality Gate Failed Quality Gate failed

    Failed conditions
    64.7% Coverage on New Code (required ≥ 80%)
    C Reliability Rating on New Code (required ≥ A)

    See analysis details on SonarCloud

    Catch issues before they fail your Quality Gate with our IDE extension SonarLint

    dryRun: r == nil,
    streamsConfig := s.getStreamsConfig(r)
    configJSON, _ := json.Marshal(streamsConfig)
    cacheKey := fmt.Sprintf("%x", md5.Sum(configJSON))
    Copy link
    Member

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    100% should be replaced by smth like sha256 or similar. md5 is too weak (I know it was part of orig implementation, but still..)

    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Projects
    None yet
    Development

    Successfully merging this pull request may close these issues.

    2 participants