Class: Falcon::Limiter::LongTask
- Inherits:
-
Object
- Object
- Falcon::Limiter::LongTask
- Defined in:
- lib/falcon/limiter/long_task.rb
Overview
Manages long-running tasks by releasing connection tokens during I/O operations to prevent contention and maintain server responsiveness.
A long task is any long (1+ sec) operation that isn’t CPU-bound (usually long I/O). Starting a long task lets the server accept one more (potentially CPU-bound) request. This allows us to handle many concurrent I/O bound requests, without adding contention (which impacts latency).
Constant Summary collapse
- STOP_PRIORITY =
The priority to use when stopping a long task to re-acquire the connection token.
1000
Class Method Summary collapse
- .current ⇒ Object
-
.current=(long_task) ⇒ Object
Assign the current long task.
-
.for(request, limiter, **options) ⇒ Object
Create a long task for the given request.
Instance Method Summary collapse
-
#acquired? ⇒ Boolean
Check if the long task has been acquired.
-
#initialize(request, limiter, connection_token = nil, start_delay: 0.1) ⇒ LongTask
constructor
Initialize a new long task with the specified configuration.
-
#start(delay: @start_delay) ⇒ Object
Start the long task, optionally with a delay to avoid overhead for short operations.
-
#started? ⇒ Boolean
Check if the long task has been started, but not necessarily acquired (e.g. if there was a delay).
-
#stop(force: false, **options) ⇒ Object
Stop the long task and restore connection token.
-
#with ⇒ Object
Execute the block with the current long task.
Constructor Details
#initialize(request, limiter, connection_token = nil, start_delay: 0.1) ⇒ LongTask
Initialize a new long task with the specified configuration.
58 59 60 61 62 63 64 65 66 |
# File 'lib/falcon/limiter/long_task.rb', line 58 def initialize(request, limiter, connection_token = nil, start_delay: 0.1) @request = request @limiter = limiter @connection_token = connection_token @start_delay = start_delay @token = Async::Limiter::Token.new(@limiter) @delayed_start_task = nil end |
Class Method Details
.current ⇒ Object
23 24 25 |
# File 'lib/falcon/limiter/long_task.rb', line 23 def self.current Fiber.current.falcon_limiter_long_task end |
.current=(long_task) ⇒ Object
Assign the current long task.
28 29 30 |
# File 'lib/falcon/limiter/long_task.rb', line 28 def self.current=(long_task) Fiber.current.falcon_limiter_long_task = long_task end |
.for(request, limiter, **options) ⇒ Object
Create a long task for the given request. Extracts connection token from the request if available for proper token management.
47 48 49 50 51 52 |
# File 'lib/falcon/limiter/long_task.rb', line 47 def self.for(request, limiter, **) # Get connection token from request if possible: connection_token = request&.connection&.stream&.io&.token rescue nil return new(request, limiter, connection_token, **) end |
Instance Method Details
#acquired? ⇒ Boolean
Check if the long task has been acquired.
76 77 78 |
# File 'lib/falcon/limiter/long_task.rb', line 76 def acquired? @token.acquired? end |
#start(delay: @start_delay) ⇒ Object
Start the long task, optionally with a delay to avoid overhead for short operations
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/falcon/limiter/long_task.rb', line 81 def start(delay: @start_delay) # If already started, nothing to do: if started? if block_given? return yield self else return self end end if delay == true delay = @start_delay elsif delay == false delay = nil end # Otherwise, start the long task: if delay&.positive? # Wait specified delay before starting the long task: @delayed_start_task = Async do sleep(delay) self.acquire rescue Async::Stop # Gracefully exit on stop. ensure @delayed_start_task = nil end else # Start the long task immediately: self.acquire end return self unless block_given? begin yield self ensure self.stop end end |
#started? ⇒ Boolean
Check if the long task has been started, but not necessarily acquired (e.g. if there was a delay).
70 71 72 |
# File 'lib/falcon/limiter/long_task.rb', line 70 def started? @token.acquired? || @delayed_start_task end |
#stop(force: false, **options) ⇒ Object
Stop the long task and restore connection token
123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/falcon/limiter/long_task.rb', line 123 def stop(force: false, **) if delayed_start_task = @delayed_start_task @delayed_start_task = nil delayed_start_task.stop end # Re-acquire the connection token with high priority than inbound requests: [:priority] ||= STOP_PRIORITY # Release the long task token: release(force, **) end |
#with ⇒ Object
Execute the block with the current long task.
33 34 35 36 37 38 39 |
# File 'lib/falcon/limiter/long_task.rb', line 33 def with previous = self.class.current self.class.current = self yield ensure self.class.current = previous end |