java-sdk-contrib icon indicating copy to clipboard operation
java-sdk-contrib copied to clipboard

[flagd] Use a scheduler instead of Thread.sleep for retry/backoff in SyncStreamQueueSource

Open aepfli opened this issue 5 months ago • 3 comments

Problem

The current implementation of SyncStreamQueueSource in the flagd provider core connection logic uses Thread.sleep() for retry backoff when re-establishing the stream connection after an error. This usage is found in the observeSyncStream() method (line 126) and can be undesirable because Thread.sleep blocks the thread, limiting scalability and responsiveness, especially in environments that favor non-blocking or asynchronous IO.

Suggested Improvement

It would be better to refactor this retry/backoff mechanism to utilize a scheduled executor (such as ScheduledExecutorService) or similar scheduling abstraction. This would allow the retry logic to be non-blocking and would enable easier integration with asynchronous patterns. Additionally, this could simplify future improvements to connection logic, such as jitter, exponential backoff, or cancellation support.

References

Example code location:

Proposal

  • Replace usages of Thread.sleep(this.maxBackoffMs); in observeSyncStream() and any related retry logic with non-blocking scheduling logic (e.g., via ScheduledExecutorService).
  • Consider further enhancements such as custom retry policies or graceful cancellation.

Example: Using ScheduledExecutorService for Non-blocking Retry

// Define the scheduler (typically a field in your class)
private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();

// Instead of blocking with Thread.sleep:
if (shouldThrottle.getAndSet(false)) {
    scheduler.schedule(
        this::retrySyncStream,
        this.maxBackoffMs,
        TimeUnit.MILLISECONDS
    );
    return;
}

// Add a method to handle the retry logic:
private void retrySyncStream() {
    if (shutdown.get()) return;
    observeSyncStream(); // or the desired reconnection logic
}

Key Points:

  • Using a scheduler avoids blocking the thread.
  • You can extend this pattern for exponential backoff, jitter, or cancellation.
  • Ensure proper shutdown of ScheduledExecutorService in your cleanup logic.

Benefits

  • Improves scalability and responsiveness.
  • Aligns with modern Java practices for IO and connection management.
  • Simplifies enhancement of retry logic in future.

aepfli avatar Nov 26 '25 13:11 aepfli

@chrfwow do you think this is feasible - I really hate our thread.sleeps

aepfli avatar Nov 26 '25 13:11 aepfli

I do think it is feasible. But I am not sure if it is worth it if it's not easily and cleanly doable

chrfwow avatar Nov 27 '25 07:11 chrfwow

lets see what copilot creates

aepfli avatar Nov 27 '25 08:11 aepfli