summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOmar Roth <omarroth@protonmail.com>2019-05-26 11:28:54 -0500
committerOmar Roth <omarroth@protonmail.com>2019-05-26 11:28:54 -0500
commitb016a60a7521fe28c14af1ea1af6e2e182e81464 (patch)
tree7170fb063e63c56af94ea35340889b6dd0a21637
parent890d485bb5ffce3d56fc890d837bd4d881f6b2be (diff)
downloadinvidious-b016a60a7521fe28c14af1ea1af6e2e182e81464.tar.gz
invidious-b016a60a7521fe28c14af1ea1af6e2e182e81464.tar.bz2
invidious-b016a60a7521fe28c14af1ea1af6e2e182e81464.zip
Add triggers for updating feeds
-rw-r--r--src/invidious.cr19
-rw-r--r--src/invidious/channels.cr36
-rw-r--r--src/invidious/helpers/jobs.cr23
3 files changed, 65 insertions, 13 deletions
diff --git a/src/invidious.cr b/src/invidious.cr
index c69a4198..3758713c 100644
--- a/src/invidious.cr
+++ b/src/invidious.cr
@@ -2845,16 +2845,25 @@ post "/feed/webhook/:token" do |env|
premiere_timestamp: video.premiere_timestamp,
)
- PG_DB.exec("UPDATE users SET notifications = notifications || $1 \
- WHERE updated < $2 AND $3 = ANY(subscriptions) AND $1 <> ALL(notifications)", video.id, video.published, video.ucid)
+ users = PG_DB.query_all("UPDATE users SET notifications = notifications || $1 \
+ WHERE updated < $2 AND $3 = ANY(subscriptions) AND $1 <> ALL(notifications) RETURNING email",
+ video.id, video.published, video.ucid, as: String)
video_array = video.to_a
args = arg_array(video_array)
PG_DB.exec("INSERT INTO channel_videos VALUES (#{args}) \
- ON CONFLICT (id) DO UPDATE SET title = $2, published = $3, \
- updated = $4, ucid = $5, author = $6, length_seconds = $7, \
- live_now = $8, premiere_timestamp = $9", video_array)
+ ON CONFLICT (id) DO UPDATE SET title = $2, published = $3, \
+ updated = $4, ucid = $5, author = $6, length_seconds = $7, \
+ live_now = $8, premiere_timestamp = $9", video_array)
+
+ users.each do |user|
+ payload = {
+ "email" => user,
+ "action" => "refresh",
+ }.to_json
+ PG_DB.exec("NOTIFY feeds, E'#{payload}'")
+ end
end
end
diff --git a/src/invidious/channels.cr b/src/invidious/channels.cr
index 8e4aa0ec..c8de9543 100644
--- a/src/invidious/channels.cr
+++ b/src/invidious/channels.cr
@@ -178,18 +178,27 @@ def fetch_channel(ucid, db, pull_all_videos = true, locale = nil)
premiere_timestamp: premiere_timestamp
)
- db.exec("UPDATE users SET notifications = notifications || $1 \
- WHERE updated < $2 AND $3 = ANY(subscriptions) AND $1 <> ALL(notifications)", video.id, video.published, ucid)
+ users = db.query_all("UPDATE users SET notifications = notifications || $1 \
+ WHERE updated < $2 AND $3 = ANY(subscriptions) AND $1 <> ALL(notifications) RETURNING email",
+ video.id, video.published, ucid, as: String)
video_array = video.to_a
args = arg_array(video_array)
- # We don't include the 'premire_timestamp' here because channel pages don't include them,
+ # We don't include the 'premiere_timestamp' here because channel pages don't include them,
# meaning the above timestamp is always null
db.exec("INSERT INTO channel_videos VALUES (#{args}) \
ON CONFLICT (id) DO UPDATE SET title = $2, published = $3, \
updated = $4, ucid = $5, author = $6, length_seconds = $7, \
live_now = $8", video_array)
+
+ users.each do |user|
+ payload = {
+ "email" => user,
+ "action" => "refresh",
+ }.to_json
+ PG_DB.exec("NOTIFY feeds, E'#{payload}'")
+ end
end
if pull_all_videos
@@ -233,18 +242,29 @@ def fetch_channel(ucid, db, pull_all_videos = true, locale = nil)
videos.each do |video|
ids << video.id
- # FIXME: Red videos don't provide published date, so the best we can do is ignore them
+ # We are notified of Red videos elsewhere (PubSub), which includes a correct published date,
+ # so since they don't provide a published date here we can safely ignore them.
if Time.now - video.published > 1.minute
- db.exec("UPDATE users SET notifications = notifications || $1 \
- WHERE updated < $2 AND $3 = ANY(subscriptions) AND $1 <> ALL(notifications)", video.id, video.published, video.ucid)
+ users = db.query_all("UPDATE users SET notifications = notifications || $1 \
+ WHERE updated < $2 AND $3 = ANY(subscriptions) AND $1 <> ALL(notifications) RETURNING email",
+ video.id, video.published, video.ucid, as: String)
video_array = video.to_a
args = arg_array(video_array)
# We don't update the 'premire_timestamp' here because channel pages don't include them
db.exec("INSERT INTO channel_videos VALUES (#{args}) \
- ON CONFLICT (id) DO UPDATE SET title = $2, updated = $4, \
- ucid = $5, author = $6, length_seconds = $7, live_now = $8", video_array)
+ ON CONFLICT (id) DO UPDATE SET title = $2, updated = $4, \
+ ucid = $5, author = $6, length_seconds = $7, live_now = $8", video_array)
+
+ # Update all users affected by insert
+ users.each do |user|
+ payload = {
+ "email" => user,
+ "action" => "refresh",
+ }.to_json
+ PG_DB.exec("NOTIFY feeds, E'#{payload}'")
+ end
end
end
diff --git a/src/invidious/helpers/jobs.cr b/src/invidious/helpers/jobs.cr
index 9afd859f..05a0a5a4 100644
--- a/src/invidious/helpers/jobs.cr
+++ b/src/invidious/helpers/jobs.cr
@@ -45,6 +45,29 @@ end
def refresh_feeds(db, logger, max_threads = 1)
max_channel = Channel(Int32).new
+ # TODO: Make this config option, similar to use_pubsub
+ # Spawn thread to handle feed events
+ if max_threads > 0
+ spawn do
+ PG.connect_listen(PG_URL, "feeds") do |event|
+ spawn do
+ feed = JSON.parse(event.payload)
+ email = feed["email"].as_s
+ action = feed["action"].as_s
+
+ view_name = "subscriptions_#{sha256(email)}"
+
+ case action
+ when "refresh"
+ db.exec("REFRESH MATERIALIZED VIEW #{view_name}")
+ end
+ end
+
+ Fiber.yield
+ end
+ end
+ end
+
spawn do
max_threads = max_channel.receive
active_threads = 0