Module: DiscourseUpdates

Defined in:
lib/discourse_updates.rb

Class Method Summary collapse

Class Method Details

.bump_last_viewed_feature_date(user_id, feature_date) ⇒ Object



202
203
204
# File 'lib/discourse_updates.rb', line 202

def bump_last_viewed_feature_date(user_id, feature_date)
  Discourse.redis.hset(last_viewed_feature_dates_for_users_key, user_id.to_s, feature_date)
end

.check_versionObject



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
# File 'lib/discourse_updates.rb', line 5

def check_version
  attrs = {
    installed_version: Discourse::VERSION::STRING,
    installed_sha: (Discourse.git_version == "unknown" ? nil : Discourse.git_version),
    installed_describe: Discourse.full_version,
    git_branch: Discourse.git_branch,
    updated_at: updated_at,
  }

  unless updated_at.nil?
    attrs.merge!(
      latest_version: latest_version,
      critical_updates: critical_updates_available?,
      missing_versions_count: missing_versions_count,
    )
  end

  version_info = DiscourseVersionCheck.new(attrs)

  # replace -commit_count with +commit_count
  if version_info.installed_describe =~ /-(\d+)-/
    version_info.installed_describe =
      version_info.installed_describe.gsub(/-(\d+)-.*/, " +#{$1}")
  end

  if SiteSetting.version_checks?
    is_stale_data =
      (
        version_info.missing_versions_count == 0 &&
          version_info.latest_version != version_info.installed_version
      ) ||
        (
          version_info.missing_versions_count != 0 &&
            version_info.latest_version == version_info.installed_version
        )

    # Handle cases when version check data is old so we report something that makes sense
    if version_info.updated_at.nil? || last_installed_version != Discourse::VERSION::STRING || # never performed a version check # upgraded since the last version check
         is_stale_data
      Jobs.enqueue(:version_check, all_sites: true)
      version_info.version_check_pending = true

      unless version_info.updated_at.nil?
        version_info.missing_versions_count = 0
        version_info.critical_updates = false
      end
    end

    version_info.stale_data =
      version_info.version_check_pending || (updated_at && updated_at < 48.hours.ago) ||
        is_stale_data
  end

  version_info
end

.clean_stateObject



206
207
208
209
210
211
212
213
214
215
216
217
218
219
# File 'lib/discourse_updates.rb', line 206

def clean_state
  Discourse.redis.del(
    last_installed_version_key,
    latest_version_key,
    critical_updates_available_key,
    missing_versions_count_key,
    updated_at_key,
    missing_versions_list_key,
    new_features_key,
    last_viewed_feature_dates_for_users_key,
    *Discourse.redis.keys("#{missing_versions_key_prefix}*"),
    *Discourse.redis.keys(new_features_last_seen_key("*")),
  )
end

.critical_updates_available=(arg) ⇒ Object



90
91
92
# File 'lib/discourse_updates.rb', line 90

def critical_updates_available=(arg)
  Discourse.redis.set(critical_updates_available_key, arg)
end

.critical_updates_available?Boolean

Returns:

  • (Boolean)


86
87
88
# File 'lib/discourse_updates.rb', line 86

def critical_updates_available?
  (Discourse.redis.get(critical_updates_available_key) || false) == "true"
end

.current_versionObject



130
131
132
# File 'lib/discourse_updates.rb', line 130

def current_version
  last_installed_version || Discourse::VERSION::STRING
end

.get_last_viewed_feature_date(user_id) ⇒ Object



196
197
198
199
200
# File 'lib/discourse_updates.rb', line 196

def get_last_viewed_feature_date(user_id)
  date = Discourse.redis.hget(last_viewed_feature_dates_for_users_key, user_id.to_s)
  return if date.blank?
  Time.zone.parse(date)
end

.has_unseen_features?(user_id) ⇒ Boolean

Returns:

  • (Boolean)


165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/discourse_updates.rb', line 165

def has_unseen_features?(user_id)
  entries = new_features
  return false if entries.nil?

  last_seen = new_features_last_seen(user_id)

  if last_seen.present?
    entries.select! { |item| Time.zone.parse(item["created_at"]) > last_seen }
  end

  entries.size > 0
end

.last_installed_versionObject

last_installed_version is the installed version at the time of the last version check



62
63
64
# File 'lib/discourse_updates.rb', line 62

def last_installed_version
  Discourse.redis.get last_installed_version_key
end

.last_installed_version=(arg) ⇒ Object



66
67
68
# File 'lib/discourse_updates.rb', line 66

def last_installed_version=(arg)
  Discourse.redis.set(last_installed_version_key, arg)
end

.latest_versionObject



70
71
72
# File 'lib/discourse_updates.rb', line 70

def latest_version
  Discourse.redis.get latest_version_key
end

.latest_version=(arg) ⇒ Object



74
75
76
# File 'lib/discourse_updates.rb', line 74

def latest_version=(arg)
  Discourse.redis.set(latest_version_key, arg)
end

.mark_new_features_as_seen(user_id) ⇒ Object



184
185
186
187
188
189
190
191
192
193
194
# File 'lib/discourse_updates.rb', line 184

def mark_new_features_as_seen(user_id)
  entries =
    begin
      JSON.parse(Discourse.redis.get(new_features_key))
    rescue StandardError
      nil
    end
  return nil if entries.nil?
  last_seen = entries.max_by { |x| x["created_at"] }
  Discourse.redis.set(new_features_last_seen_key(user_id), last_seen["created_at"])
end

.missing_versionsObject



125
126
127
128
# File 'lib/discourse_updates.rb', line 125

def missing_versions
  keys = Discourse.redis.lrange(missing_versions_list_key, 0, 4) # max of 5 versions
  keys.present? ? keys.map { |k| Discourse.redis.hgetall(k) } : []
end

.missing_versions=(versions) ⇒ Object



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/discourse_updates.rb', line 103

def missing_versions=(versions)
  # delete previous list from redis
  prev_keys = Discourse.redis.lrange(missing_versions_list_key, 0, 4)
  if prev_keys
    Discourse.redis.del prev_keys
    Discourse.redis.del(missing_versions_list_key)
  end

  if versions.present?
    # store the list in redis
    version_keys = []
    versions[0, 5].each do |v|
      key = "#{missing_versions_key_prefix}:#{v["version"]}"
      Discourse.redis.mapped_hmset key, v
      version_keys << key
    end
    Discourse.redis.rpush missing_versions_list_key, version_keys
  end

  versions || []
end

.missing_versions_countObject



78
79
80
# File 'lib/discourse_updates.rb', line 78

def missing_versions_count
  Discourse.redis.get(missing_versions_count_key).try(:to_i)
end

.missing_versions_count=(arg) ⇒ Object



82
83
84
# File 'lib/discourse_updates.rb', line 82

def missing_versions_count=(arg)
  Discourse.redis.set(missing_versions_count_key, arg)
end

.new_featuresObject



144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/discourse_updates.rb', line 144

def new_features
  entries =
    begin
      JSON.parse(Discourse.redis.get(new_features_key))
    rescue StandardError
      nil
    end
  return nil if entries.nil?

  entries.select! do |item|
    begin
      item["discourse_version"].nil? ||
        Discourse.has_needed_version?(current_version, item["discourse_version"])
    rescue StandardError
      nil
    end
  end

  entries.sort_by { |item| Time.zone.parse(item["created_at"]).to_i }.reverse
end

.new_features_last_seen(user_id) ⇒ Object



178
179
180
181
182
# File 'lib/discourse_updates.rb', line 178

def new_features_last_seen(user_id)
  last_seen = Discourse.redis.get new_features_last_seen_key(user_id)
  return nil if last_seen.blank?
  Time.zone.parse(last_seen)
end

.new_features_payloadObject



134
135
136
137
# File 'lib/discourse_updates.rb', line 134

def new_features_payload
  response = Excon.new(new_features_endpoint).request(expects: [200], method: :Get)
  response.body
end

.update_new_features(payload = nil) ⇒ Object



139
140
141
142
# File 'lib/discourse_updates.rb', line 139

def update_new_features(payload = nil)
  payload ||= new_features_payload
  Discourse.redis.set(new_features_key, payload)
end

.updated_atObject



94
95
96
97
# File 'lib/discourse_updates.rb', line 94

def updated_at
  t = Discourse.redis.get(updated_at_key)
  t ? Time.zone.parse(t) : nil
end

.updated_at=(time_with_zone) ⇒ Object



99
100
101
# File 'lib/discourse_updates.rb', line 99

def updated_at=(time_with_zone)
  Discourse.redis.set updated_at_key, time_with_zone.as_json
end