2019-05-02 17:17:27 -05:00
# frozen_string_literal: true
2013-02-19 14:16:50 -06:00
module DiscourseUpdates
class << self
def check_version
2017-11-21 03:01:27 -06:00
attrs = {
installed_version : Discourse :: VERSION :: STRING ,
2023-01-09 06:10:19 -06:00
installed_sha : ( Discourse . git_version == " unknown " ? nil : Discourse . git_version ) ,
2017-11-21 03:01:27 -06:00
installed_describe : Discourse . full_version ,
git_branch : Discourse . git_branch ,
updated_at : updated_at ,
}
unless updated_at . nil?
attrs . merge! (
2013-07-03 10:06:07 -05:00
latest_version : latest_version ,
critical_updates : critical_updates_available? ,
2023-01-09 06:10:19 -06:00
missing_versions_count : missing_versions_count ,
2013-07-03 10:06:07 -05:00
)
end
2017-11-21 03:01:27 -06:00
version_info = DiscourseVersionCheck . new ( attrs )
2015-02-23 17:57:54 -06:00
# replace -commit_count with +commit_count
if version_info . installed_describe =~ / -( \ d+)- /
2023-01-09 06:10:19 -06:00
version_info . installed_describe =
version_info . installed_describe . gsub ( / -( \ d+)-.* / , " + #{ $1 } " )
2015-02-23 17:57:54 -06:00
end
2013-07-30 11:11:51 -05:00
if SiteSetting . version_checks?
2017-11-21 03:01:27 -06:00
is_stale_data =
2023-01-09 06:10:19 -06:00
(
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
)
2013-07-30 11:11:51 -05:00
# Handle cases when version check data is old so we report something that makes sense
2023-01-09 06:10:19 -06:00
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
2013-07-30 11:11:51 -05:00
Jobs . enqueue ( :version_check , all_sites : true )
2013-11-04 11:51:01 -06:00
version_info . version_check_pending = true
2017-11-21 03:01:27 -06:00
2013-11-04 11:51:01 -06:00
unless version_info . updated_at . nil?
version_info . missing_versions_count = 0
version_info . critical_updates = false
end
2013-07-30 11:11:51 -05:00
end
2017-11-21 03:01:27 -06:00
version_info . stale_data =
2023-01-09 06:10:19 -06:00
version_info . version_check_pending || ( updated_at && updated_at < 48 . hours . ago ) ||
is_stale_data
2013-07-03 10:06:07 -05:00
end
version_info
2013-02-19 14:16:50 -06:00
end
2013-11-04 11:51:01 -06:00
# last_installed_version is the installed version at the time of the last version check
def last_installed_version
2019-12-03 03:05:53 -06:00
Discourse . redis . get last_installed_version_key
2013-11-04 11:51:01 -06:00
end
2021-10-27 03:39:28 -05:00
def last_installed_version = ( arg )
2021-11-09 00:20:09 -06:00
Discourse . redis . set ( last_installed_version_key , arg )
2021-10-27 03:39:28 -05:00
end
2013-02-19 14:16:50 -06:00
def latest_version
2019-12-03 03:05:53 -06:00
Discourse . redis . get latest_version_key
2013-02-19 14:16:50 -06:00
end
2021-10-27 03:39:28 -05:00
def latest_version = ( arg )
2021-11-09 00:20:09 -06:00
Discourse . redis . set ( latest_version_key , arg )
2021-10-27 03:39:28 -05:00
end
2013-03-05 17:14:51 -06:00
def missing_versions_count
2019-12-03 03:05:53 -06:00
Discourse . redis . get ( missing_versions_count_key ) . try ( :to_i )
2013-02-19 14:16:50 -06:00
end
2021-10-27 03:39:28 -05:00
def missing_versions_count = ( arg )
2021-10-28 20:03:11 -05:00
Discourse . redis . set ( missing_versions_count_key , arg )
2021-10-27 03:39:28 -05:00
end
2013-03-06 09:34:15 -06:00
def critical_updates_available?
2023-01-09 06:10:19 -06:00
( Discourse . redis . get ( critical_updates_available_key ) || false ) == " true "
2013-02-19 14:16:50 -06:00
end
2021-10-27 03:39:28 -05:00
def critical_updates_available = ( arg )
2021-10-28 20:03:11 -05:00
Discourse . redis . set ( critical_updates_available_key , arg )
2021-10-27 03:39:28 -05:00
end
2013-07-03 10:06:07 -05:00
def updated_at
2019-12-03 03:05:53 -06:00
t = Discourse . redis . get ( updated_at_key )
2013-07-03 10:06:07 -05:00
t ? Time . zone . parse ( t ) : nil
end
def updated_at = ( time_with_zone )
2019-12-03 03:05:53 -06:00
Discourse . redis . set updated_at_key , time_with_zone . as_json
2013-07-03 10:06:07 -05:00
end
2013-12-31 14:52:16 -06:00
def missing_versions = ( versions )
# delete previous list from redis
2019-12-03 03:05:53 -06:00
prev_keys = Discourse . redis . lrange ( missing_versions_list_key , 0 , 4 )
2013-12-31 14:52:16 -06:00
if prev_keys
2019-12-03 03:05:53 -06:00
Discourse . redis . del prev_keys
Discourse . redis . del ( missing_versions_list_key )
2013-12-31 14:52:16 -06:00
end
2014-01-07 13:31:54 -06:00
if versions . present?
# store the list in redis
version_keys = [ ]
2017-07-27 20:20:09 -05:00
versions [ 0 , 5 ] . each do | v |
2023-01-09 06:10:19 -06:00
key = " #{ missing_versions_key_prefix } : #{ v [ " version " ] } "
2019-12-03 03:05:53 -06:00
Discourse . redis . mapped_hmset key , v
2014-01-07 13:31:54 -06:00
version_keys << key
end
2019-12-03 03:05:53 -06:00
Discourse . redis . rpush missing_versions_list_key , version_keys
2013-12-31 14:52:16 -06:00
end
2014-01-07 13:31:54 -06:00
versions || [ ]
2013-12-31 14:52:16 -06:00
end
def missing_versions
2019-12-03 03:05:53 -06:00
keys = Discourse . redis . lrange ( missing_versions_list_key , 0 , 4 ) # max of 5 versions
keys . present? ? keys . map { | k | Discourse . redis . hgetall ( k ) } : [ ]
2013-12-31 14:52:16 -06:00
end
2021-04-21 11:40:27 -05:00
def current_version
last_installed_version || Discourse :: VERSION :: STRING
end
2021-02-12 07:52:59 -06:00
def new_features_payload
2021-01-22 09:09:02 -06:00
response = Excon . new ( new_features_endpoint ) . request ( expects : [ 200 ] , method : :Get )
2021-02-12 09:49:10 -06:00
response . body
2021-02-12 07:52:59 -06:00
end
2021-02-12 09:49:10 -06:00
def update_new_features ( payload = nil )
payload || = new_features_payload
Discourse . redis . set ( new_features_key , payload )
2021-01-22 09:09:02 -06:00
end
2021-02-10 12:12:04 -06:00
def new_features
2023-01-09 06:10:19 -06:00
entries =
begin
JSON . parse ( Discourse . redis . get ( new_features_key ) )
rescue StandardError
nil
end
2021-01-22 09:09:02 -06:00
return nil if entries . nil?
2021-02-10 12:12:04 -06:00
entries . select! do | item |
2023-01-09 06:10:19 -06:00
begin
item [ " discourse_version " ] . nil? ||
Discourse . has_needed_version? ( current_version , item [ " discourse_version " ] )
rescue StandardError
nil
end
2021-02-10 12:12:04 -06:00
end
2021-02-19 10:03:36 -06:00
entries . sort_by { | item | Time . zone . parse ( item [ " created_at " ] ) . to_i } . reverse
2021-02-10 12:12:04 -06:00
end
def has_unseen_features? ( user_id )
entries = new_features
return false if entries . nil?
2021-01-22 09:09:02 -06:00
last_seen = new_features_last_seen ( user_id )
if last_seen . present?
entries . select! { | item | Time . zone . parse ( item [ " created_at " ] ) > last_seen }
end
2021-02-10 12:12:04 -06:00
entries . size > 0
2021-01-22 09:09:02 -06:00
end
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
def mark_new_features_as_seen ( user_id )
2023-01-09 06:10:19 -06:00
entries =
begin
JSON . parse ( Discourse . redis . get ( new_features_key ) )
rescue StandardError
nil
end
2021-01-22 09:09:02 -06:00
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
2022-12-15 11:12:53 -06:00
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
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
2022-12-23 06:41:30 -06:00
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
2013-02-19 14:16:50 -06:00
private
2019-01-01 15:47:29 -06:00
def last_installed_version_key
2023-01-09 06:10:19 -06:00
" last_installed_version "
2019-01-01 15:47:29 -06:00
end
2013-11-04 11:51:01 -06:00
2019-01-01 15:47:29 -06:00
def latest_version_key
2023-01-09 06:10:19 -06:00
" discourse_latest_version "
2019-01-01 15:47:29 -06:00
end
2013-02-19 14:16:50 -06:00
2019-01-01 15:47:29 -06:00
def critical_updates_available_key
2023-01-09 06:10:19 -06:00
" critical_updates_available "
2019-01-01 15:47:29 -06:00
end
2013-03-05 17:14:51 -06:00
2019-01-01 15:47:29 -06:00
def missing_versions_count_key
2023-01-09 06:10:19 -06:00
" missing_versions_count "
2019-01-01 15:47:29 -06:00
end
2013-07-03 10:06:07 -05:00
2019-01-01 15:47:29 -06:00
def updated_at_key
2023-01-09 06:10:19 -06:00
" last_version_check_at "
2019-01-01 15:47:29 -06:00
end
2013-12-31 14:52:16 -06:00
2019-01-01 15:47:29 -06:00
def missing_versions_list_key
2023-01-09 06:10:19 -06:00
" missing_versions "
2019-01-01 15:47:29 -06:00
end
2013-12-31 14:52:16 -06:00
2019-01-01 15:47:29 -06:00
def missing_versions_key_prefix
2023-01-09 06:10:19 -06:00
" missing_version "
2019-01-01 15:47:29 -06:00
end
2021-01-22 09:09:02 -06:00
def new_features_endpoint
2023-01-09 06:10:19 -06:00
" https://meta.discourse.org/new-features.json "
2021-01-22 09:09:02 -06:00
end
def new_features_key
2023-01-09 06:10:19 -06:00
" new_features "
2021-01-22 09:09:02 -06:00
end
def new_features_last_seen_key ( user_id )
" new_features_last_seen_user_ #{ user_id } "
end
2022-12-15 11:12:53 -06:00
def last_viewed_feature_dates_for_users_key
" last_viewed_feature_dates_for_users_hash "
end
2013-02-19 14:16:50 -06:00
end
2015-02-23 17:57:54 -06:00
end