Always generate the first page's continuation, and add fallback logic.

The fallback branch iterates from the last known continuation to get the 
continuation for the wanted page.
This commit is contained in:
0x24d 2021-11-20 11:57:45 +00:00
parent 55fc6e7bbe
commit dce70e2d93

View File

@ -58,33 +58,72 @@ def produce_channel_videos_continuation(ucid, page = 1, auto_generated = nil, so
end end
def get_channel_videos_response(ucid, page = 1, auto_generated = nil, sort_by = "newest") def get_channel_videos_response(ucid, page = 1, auto_generated = nil, sort_by = "newest")
if channel_continuation = PG_DB.query_one?("SELECT * FROM channel_continuations WHERE id = $1 AND page = $2 AND sort_by = $3", ucid, page, sort_by, as: ChannelContinuation) continuation = ""
initial_data = Hash(String, JSON::Any).new
if page == 1
# Always manually create the continuation for page 1 as this is likely faster than a db lookup.
continuation = produce_channel_videos_continuation(ucid, page, auto_generated: auto_generated, sort_by: sort_by, v2: true)
elsif channel_continuation = PG_DB.query_one?("SELECT * FROM channel_continuations WHERE id = $1 AND page = $2 AND sort_by = $3", ucid, page, sort_by, as: ChannelContinuation)
continuation = channel_continuation.continuation continuation = channel_continuation.continuation
else else
# Manually create the continuation, and insert it into the table, if one does not already exist. # This branch should not be needed in normal operation (navigating via the previous/next page buttons).
# This should only the case the first time the first page of each 'sort_by' mode is loaded for each channel, # This is just here as a fallback in case someone requests, for example, page 3 without previously requesting page 2.
# as all calls to this function with 'page = 1' will get the continuation for the next page (page 2) from the returned data below.
continuation = produce_channel_videos_continuation(ucid, page, auto_generated: auto_generated, sort_by: sort_by, v2: true) # Iterate backwards from the wanted page to page 2 to find a stored continuation.
channel_continuation = ChannelContinuation.new({ start = 1
id: ucid, ((page - 1)..2).each do |i|
page: page, if channel_continuation = PG_DB.query_one?("SELECT * FROM channel_continuations WHERE id = $1 AND page = $2 AND sort_by = $3", ucid, i, sort_by, as: ChannelContinuation)
sort_by: sort_by, start = i
continuation: continuation continuation = channel_continuation.continuation
}) break
PG_DB.exec("INSERT INTO channel_continuations VALUES ($1, $2, $3, $4) \ end
ON CONFLICT (id, page, sort_by) DO UPDATE SET continuation = $4", *channel_continuation.to_tuple) end
# If a continuation hasn't been found after getting to page 2, manually create the continuation for page 1.
if start == 1
continuation = produce_channel_videos_continuation(ucid, 1, auto_generated: auto_generated, sort_by: sort_by, v2: true)
end
# Iterate from the found/created continuation until we have the continuation for the wanted page or there are no more pages.
# Store the returned continuation each time so that it can be found in the db next time the current page is wanted.
(start..(page - 1)).each do |i|
initial_data = YoutubeAPI.browse(continuation)
continuation = fetch_continuation_token(initial_data)
break if continuation.nil? || continuation.empty?
channel_continuation = ChannelContinuation.new({
id: ucid,
page: i,
sort_by: sort_by,
continuation: continuation
})
PG_DB.exec("INSERT INTO channel_continuations VALUES ($1, $2, $3, $4) \
ON CONFLICT (id, page, sort_by) DO UPDATE SET continuation = $4", *channel_continuation.to_tuple)
end
end end
initial_data = YoutubeAPI.browse(continuation) # If we reached the channel's last page in the else loop above return an empty hash.
# Store the returned continuation in the table so that it can be used the next time this function is called requesting that page. if continuation.nil? || continuation.empty?
channel_continuation = ChannelContinuation.new({ initial_data.clear
id: ucid, else
page: page + 1, # Get the wanted page and store the returned continuation for the next page,
sort_by: sort_by, # if there is one, so that it can be used the next time this function is called requesting that page.
continuation: fetch_continuation_token(initial_data) || "" initial_data = YoutubeAPI.browse(continuation)
}) continuation = fetch_continuation_token(initial_data)
PG_DB.exec("INSERT INTO channel_continuations VALUES ($1, $2, $3, $4) \
ON CONFLICT (id, page, sort_by) DO UPDATE SET continuation = $4", *channel_continuation.to_tuple) if !continuation.nil? && !continuation.empty?
channel_continuation = ChannelContinuation.new({
id: ucid,
page: page + 1,
sort_by: sort_by,
continuation: continuation
})
PG_DB.exec("INSERT INTO channel_continuations VALUES ($1, $2, $3, $4) \
ON CONFLICT (id, page, sort_by) DO UPDATE SET continuation = $4", *channel_continuation.to_tuple)
end
end
return initial_data return initial_data
end end