Class: SourceMonitor::Fetching::FeedFetcher::AdaptiveInterval
- Inherits:
-
Object
- Object
- SourceMonitor::Fetching::FeedFetcher::AdaptiveInterval
- Defined in:
- lib/source_monitor/fetching/feed_fetcher/adaptive_interval.rb
Constant Summary collapse
- MIN_FETCH_INTERVAL =
5.minutes.to_f
- MAX_FETCH_INTERVAL =
24.hours.to_f
- INCREASE_FACTOR =
1.25- DECREASE_FACTOR =
0.75- FAILURE_INCREASE_FACTOR =
1.5- JITTER_PERCENT =
0.1
Instance Attribute Summary collapse
-
#jitter_proc ⇒ Object
readonly
Returns the value of attribute jitter_proc.
-
#source ⇒ Object
readonly
Returns the value of attribute source.
Instance Method Summary collapse
- #adjusted_interval_with_jitter(interval_seconds) ⇒ Object
- #apply_adaptive_interval!(attributes, content_changed:, failure: false) ⇒ Object
- #compute_next_interval_seconds(content_changed:, failure:) ⇒ Object
- #configured_non_negative(value, default) ⇒ Object
- #configured_positive(value, default) ⇒ Object
- #configured_seconds(minutes_value, default) ⇒ Object
- #extract_numeric(value) ⇒ Object
-
#initialize(source:, jitter_proc: nil) ⇒ AdaptiveInterval
constructor
A new instance of AdaptiveInterval.
- #interval_minutes_for(interval_seconds) ⇒ Object
- #jitter_offset(interval_seconds) ⇒ Object
Constructor Details
#initialize(source:, jitter_proc: nil) ⇒ AdaptiveInterval
Returns a new instance of AdaptiveInterval.
16 17 18 19 |
# File 'lib/source_monitor/fetching/feed_fetcher/adaptive_interval.rb', line 16 def initialize(source:, jitter_proc: nil) @source = source @jitter_proc = jitter_proc end |
Instance Attribute Details
#jitter_proc ⇒ Object (readonly)
Returns the value of attribute jitter_proc.
14 15 16 |
# File 'lib/source_monitor/fetching/feed_fetcher/adaptive_interval.rb', line 14 def jitter_proc @jitter_proc end |
#source ⇒ Object (readonly)
Returns the value of attribute source.
14 15 16 |
# File 'lib/source_monitor/fetching/feed_fetcher/adaptive_interval.rb', line 14 def source @source end |
Instance Method Details
#adjusted_interval_with_jitter(interval_seconds) ⇒ Object
54 55 56 57 58 59 |
# File 'lib/source_monitor/fetching/feed_fetcher/adaptive_interval.rb', line 54 def adjusted_interval_with_jitter(interval_seconds) jitter = jitter_offset(interval_seconds) adjusted = interval_seconds + jitter adjusted = min_fetch_interval_seconds if adjusted < min_fetch_interval_seconds adjusted end |
#apply_adaptive_interval!(attributes, content_changed:, failure: false) ⇒ Object
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/source_monitor/fetching/feed_fetcher/adaptive_interval.rb', line 21 def apply_adaptive_interval!(attributes, content_changed:, failure: false) if source.adaptive_fetching_enabled? interval_seconds = compute_next_interval_seconds(content_changed:, failure:) scheduled_time = Time.current + adjusted_interval_with_jitter(interval_seconds) scheduled_time = [ scheduled_time, source.backoff_until ].compact.max if source.backoff_until.present? attributes[:fetch_interval_minutes] = interval_minutes_for(interval_seconds) attributes[:next_fetch_at] = scheduled_time attributes[:backoff_until] = failure ? scheduled_time : nil else fixed_minutes = [ source.fetch_interval_minutes.to_i, 1 ].max fixed_seconds = fixed_minutes * 60.0 attributes[:next_fetch_at] = Time.current + adjusted_interval_with_jitter(fixed_seconds) attributes[:backoff_until] = nil end end |
#compute_next_interval_seconds(content_changed:, failure:) ⇒ Object
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/source_monitor/fetching/feed_fetcher/adaptive_interval.rb', line 38 def compute_next_interval_seconds(content_changed:, failure:) current = [ current_interval_seconds, min_fetch_interval_seconds ].max next_interval = if failure current * failure_increase_factor_value elsif content_changed current * decrease_factor_value else current * increase_factor_value end next_interval = min_fetch_interval_seconds if next_interval < min_fetch_interval_seconds next_interval = max_fetch_interval_seconds if next_interval > max_fetch_interval_seconds next_interval.to_f end |
#configured_non_negative(value, default) ⇒ Object
90 91 92 93 94 95 |
# File 'lib/source_monitor/fetching/feed_fetcher/adaptive_interval.rb', line 90 def configured_non_negative(value, default) number = extract_numeric(value) return default if number.nil? number.negative? ? 0.0 : number end |
#configured_positive(value, default) ⇒ Object
83 84 85 86 87 88 |
# File 'lib/source_monitor/fetching/feed_fetcher/adaptive_interval.rb', line 83 def configured_positive(value, default) number = extract_numeric(value) return default unless number && number.positive? number end |
#configured_seconds(minutes_value, default) ⇒ Object
76 77 78 79 80 81 |
# File 'lib/source_monitor/fetching/feed_fetcher/adaptive_interval.rb', line 76 def configured_seconds(minutes_value, default) minutes = extract_numeric(minutes_value) return default unless minutes && minutes.positive? minutes * 60.0 end |
#extract_numeric(value) ⇒ Object
97 98 99 100 101 102 103 104 |
# File 'lib/source_monitor/fetching/feed_fetcher/adaptive_interval.rb', line 97 def extract_numeric(value) return value if value.is_a?(Numeric) return value.to_f if value.respond_to?(:to_f) nil rescue StandardError nil end |
#interval_minutes_for(interval_seconds) ⇒ Object
71 72 73 74 |
# File 'lib/source_monitor/fetching/feed_fetcher/adaptive_interval.rb', line 71 def interval_minutes_for(interval_seconds) minutes = (interval_seconds / 60.0).round [ minutes, 1 ].max end |
#jitter_offset(interval_seconds) ⇒ Object
61 62 63 64 65 66 67 68 69 |
# File 'lib/source_monitor/fetching/feed_fetcher/adaptive_interval.rb', line 61 def jitter_offset(interval_seconds) return 0 if interval_seconds <= 0 return jitter_proc.call(interval_seconds) if jitter_proc.respond_to?(:call) jitter_range = interval_seconds * jitter_percent_value return 0 if jitter_range <= 0 ((rand * 2) - 1) * jitter_range end |