Class: Jekyll::WebmentionIO::WebmentionPolicy

Inherits:
Object
  • Object
show all
Defined in:
lib/jekyll/webmention_policy.rb

Overview

The WebmentionPolicy class encapsulates all the configuration and state management logic for dealing with request failures.

Instance Method Summary collapse

Constructor Details

#initialize(config, caches) ⇒ WebmentionPolicy

Returns a new instance of WebmentionPolicy.



15
16
17
18
# File 'lib/jekyll/webmention_policy.rb', line 15

def initialize(config, caches)
  @config = config
  @caches = caches
end

Instance Method Details

#error(uri) ⇒ Object

Update our URI cache to indicate that the last request for the given URI resulted in an error being returned from the target.



89
90
91
# File 'lib/jekyll/webmention_policy.rb', line 89

def error(uri)
  update_uri_cache(uri, State::ERROR)
end

#failure(uri) ⇒ Object

Update our URI cache to indicate that the last request for the given URI resulted in an failure in accessing the given resource.



95
96
97
# File 'lib/jekyll/webmention_policy.rb', line 95

def failure(uri)
  update_uri_cache(uri, State::FAILURE)
end

#post_should_be_throttled?(post, item_date, last_lookup) ⇒ Boolean

Determines webmention gathering for the given post should or should not be delayed/throttled in order to minimize load on webmention.io based on the configured throttling policy.

allowed throttles: last_week, last_month, last_year, older allowed values: daily, weekly, monthly, yearly, every X days|weeks|months|years

Returns:

  • (Boolean)


112
113
114
115
116
117
118
119
120
121
122
# File 'lib/jekyll/webmention_policy.rb', line 112

def post_should_be_throttled?(post, item_date, last_lookup)
  return false unless item_date && last_lookup

  lookup_threshold = @config.last_lookup_threshold(item_date)

  return false if lookup_threshold.nil? || (last_lookup <= lookup_threshold)

  Jekyll::WebmentionIO.log 'info', "Throttling #{post.data['title']} due to policy (last was #{last_lookup}, threshold is #{lookup_threshold})"

  true
end

#success(uri) ⇒ Object

Update our URI cache to indicate that the last request for the given URI was a success.



83
84
85
# File 'lib/jekyll/webmention_policy.rb', line 83

def success(uri)
  update_uri_cache(uri, State::SUCCESS)
end

#unsupported(uri) ⇒ Object

Update our URI cache to indicate that endpoint indicated by the given URI is not available/supported (for example, if an attempt was made to send a webmention to a site that doesn’t support them).



102
103
104
# File 'lib/jekyll/webmention_policy.rb', line 102

def unsupported(uri)
  update_uri_cache(uri, State::UNSUPPORTED)
end

#uri_ok?(uri) ⇒ Boolean

Check if we should attempt to send a webmention to the given URI based on the error handling policy and the last attempt.

Returns:

  • (Boolean)


22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/jekyll/webmention_policy.rb', line 22

def uri_ok?(uri)
  uri = URI::Parser.new.parse(uri.to_s)
  uri_str = uri.to_s

  # If the URI is whitelisted, it's always ok!
  return true if @config.bad_uri_policy.whitelist.any? { |expr| expr.match uri_str }

  # If the URI is blacklisted, it's never ok!
  return false if @config.bad_uri_policy.blacklist.any? { |expr| expr.match uri_str }

  entry = get_bad_uri_cache_entry(uri)

  # If the entry isn't in our cache yet, then it's ok.
  return true if entry.nil?

  # Okay, the last time we tried to send a webmention to this URI it
  # failed, so depending on what happened and the policy, we need to
  # decide what to do.
  #
  # First pull the retry policy given the type of the last error for the URI
  policy_entry = @config.bad_uri_policy.for_state(entry['state'])

  return false if policy_entry.policy == Config::UriPolicy::BAN

  return true if policy_entry.policy == Config::UriPolicy::IGNORE

  if policy_entry.policy == Config::UriPolicy::RETRY
    now = Time.now

    attempts = entry['attempts']
    max_attempts = policy_entry.max_attempts

    if !max_attempts.nil? && (attempts >= max_attempts)
      # If there's a retry limit and we've hit it, URI is not ok.
      Jekyll::WebmentionIO.log 'msg', "Skipping #{uri}, attempted #{attempts} times and max is #{max_attempts}"

      return false
    end

    retry_delay = policy_entry.retry_delay

    # Sneaky trick.  By clamping to the array length, the last entry in
    # the retry_delay list is used for all remaining retries.
    delay = retry_delay[(attempts - 1).clamp(0, retry_delay.length - 1)]

    recheck_at = (entry['last_checked'] + (delay * 3600))

    if recheck_at.to_r > now.to_r
      Jekyll::WebmentionIO.log 'msg', "Skipping #{uri}, next attempt will happen after #{recheck_at}"

      return false
    end
  else
    Jekyll::WebmentionIO.log 'error', "Invalid bad URI policy type: #{policy}"
  end

  true
end