diff --git a/src/invidious.cr b/src/invidious.cr index 6a9d4970..ecdd1476 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -163,39 +163,8 @@ Invidious::Jobs.register Invidious::Jobs::RefreshChannelsJob.new(PG_DB, logger, Invidious::Jobs.register Invidious::Jobs::RefreshFeedsJob.new(PG_DB, logger, config) Invidious::Jobs.register Invidious::Jobs::SubscribeToFeedsJob.new(PG_DB, logger, config, HMAC_KEY) -statistics = { - "error" => "Statistics are not availabile.", -} if config.statistics_enabled - spawn do - statistics = { - "version" => "2.0", - "software" => SOFTWARE, - "openRegistrations" => config.registration_enabled, - "usage" => { - "users" => { - "total" => PG_DB.query_one("SELECT count(*) FROM users", as: Int64), - "activeHalfyear" => PG_DB.query_one("SELECT count(*) FROM users WHERE CURRENT_TIMESTAMP - updated < '6 months'", as: Int64), - "activeMonth" => PG_DB.query_one("SELECT count(*) FROM users WHERE CURRENT_TIMESTAMP - updated < '1 month'", as: Int64), - }, - }, - "metadata" => { - "updatedAt" => Time.utc.to_unix, - "lastChannelRefreshedAt" => PG_DB.query_one?("SELECT updated FROM channels ORDER BY updated DESC LIMIT 1", as: Time).try &.to_unix || 0_i64, - }, - } - - loop do - sleep 1.minute - Fiber.yield - - statistics["usage"].as(Hash)["users"].as(Hash)["total"] = PG_DB.query_one("SELECT count(*) FROM users", as: Int64) - statistics["usage"].as(Hash)["users"].as(Hash)["activeHalfyear"] = PG_DB.query_one("SELECT count(*) FROM users WHERE CURRENT_TIMESTAMP - updated < '6 months'", as: Int64) - statistics["usage"].as(Hash)["users"].as(Hash)["activeMonth"] = PG_DB.query_one("SELECT count(*) FROM users WHERE CURRENT_TIMESTAMP - updated < '1 month'", as: Int64) - statistics["metadata"].as(Hash(String, Int64))["updatedAt"] = Time.utc.to_unix - statistics["metadata"].as(Hash(String, Int64))["lastChannelRefreshedAt"] = PG_DB.query_one?("SELECT updated FROM channels ORDER BY updated DESC LIMIT 1", as: Time).try &.to_unix || 0_i64 - end - end + Invidious::Jobs.register Invidious::Jobs::StatisticsRefreshJob.new(PG_DB, config, SOFTWARE) end Invidious::Jobs.register Invidious::Jobs::PullPopularVideosJob.new(PG_DB) @@ -3658,12 +3627,7 @@ get "/api/v1/stats" do |env| next error_message end - if statistics["error"]? - env.response.status_code = 500 - next statistics.to_json - end - - statistics.to_json + Invidious::Jobs::StatisticsRefreshJob::STATISTICS.to_json end # YouTube provides "storyboards", which are sprites containing x * y diff --git a/src/invidious/jobs/statistics_refresh_job.cr b/src/invidious/jobs/statistics_refresh_job.cr new file mode 100644 index 00000000..021671be --- /dev/null +++ b/src/invidious/jobs/statistics_refresh_job.cr @@ -0,0 +1,59 @@ +class Invidious::Jobs::StatisticsRefreshJob < Invidious::Jobs::BaseJob + STATISTICS = { + "version" => "2.0", + "software" => { + "name" => "invidious", + "version" => "", + "branch" => "", + }, + "openRegistrations" => true, + "usage" => { + "users" => { + "total" => 0_i64, + "activeHalfyear" => 0_i64, + "activeMonth" => 0_i64, + }, + }, + "metadata" => { + "updatedAt" => Time.utc.to_unix, + "lastChannelRefreshedAt" => 0_i64, + }, + } + + private getter db : DB::Database + private getter config : Config + + def initialize(@db, @config, @software_config : Hash(String, String)) + end + + def begin + load_initial_stats + + loop do + refresh_stats + sleep 1.minute + Fiber.yield + end + end + + # should only be called once at the very beginning + private def load_initial_stats + STATISTICS["software"] = { + "name" => @software_config["name"], + "version" => @software_config["version"], + "branch" => @software_config["branch"], + } + STATISTICS["openRegistration"] = config.registration_enabled + end + + private def refresh_stats + users = STATISTICS.dig("usage", "users").as(Hash(String, Int64)) + users["total"] = db.query_one("SELECT count(*) FROM users", as: Int64) + users["activeHalfyear"] = db.query_one("SELECT count(*) FROM users WHERE CURRENT_TIMESTAMP - updated < '6 months'", as: Int64) + users["activeMonth"] = db.query_one("SELECT count(*) FROM users WHERE CURRENT_TIMESTAMP - updated < '1 month'", as: Int64) + STATISTICS["metadata"] = { + "updatedAt" => Time.utc.to_unix, + "lastChannelRefreshedAt" => db.query_one?("SELECT updated FROM channels ORDER BY updated DESC LIMIT 1", as: Time).try &.to_unix || 0_i64, + } + end +end