diff --git a/src/invidious/videos.cr b/src/invidious/videos.cr index bec26de9..c055f2a7 100644 --- a/src/invidious/videos.cr +++ b/src/invidious/videos.cr @@ -7,6 +7,16 @@ end struct Video include DB::Serializable + # Version of the JSON structure + # It prevents us from loading an incompatible version from cache + # (either newer or older, if instances with different versions run + # concurrently, e.g during a version upgrade rollout). + # + # NOTE: don't forget to bump this number if any change is made to + # the `params` structure in videos/parser.cr!!! + # + SCHEMA_VERSION = 2 + property id : String @[DB::Field(converter: Video::JSONConverter)] @@ -55,6 +65,10 @@ struct Video return VideoType.parse?(video_type) || VideoType::Video end + def schema_version : Int + return info["version"]?.try &.as_i || 1 + end + def published : Time return info["published"]? .try { |t| Time.parse(t.as_s, "%Y-%m-%d", Time::Location::UTC) } || Time.utc @@ -326,7 +340,8 @@ def get_video(id, refresh = true, region = nil, force_refresh = false) if (refresh && (Time.utc - video.updated > 10.minutes) || (video.premiere_timestamp.try &.< Time.utc)) || - force_refresh + force_refresh || + video.schema_version != Video::SCHEMA_VERSION # cache control begin video = fetch_video(id, region) Invidious::Database::Videos.update(video) diff --git a/src/invidious/videos/parser.cr b/src/invidious/videos/parser.cr index 53372942..64c8d21a 100644 --- a/src/invidious/videos/parser.cr +++ b/src/invidious/videos/parser.cr @@ -71,7 +71,8 @@ def extract_video_info(video_id : String, proxy_region : String? = nil, context_ # Stop here if video is not a scheduled livestream if playability_status != "LIVE_STREAM_OFFLINE" return { - "reason" => JSON::Any.new(reason), + "version" => JSON::Any.new(Video::SCHEMA_VERSION.to_i64), + "reason" => JSON::Any.new(reason), } end elsif video_id != player_response.dig("videoDetails", "videoId") @@ -121,6 +122,9 @@ def extract_video_info(video_id : String, proxy_region : String? = nil, context_ params[f] = player_response[f] if player_response[f]? end + # Data structure version, for cache control + params["version"] = JSON::Any.new(Video::SCHEMA_VERSION.to_i64) + return params end