From 21fa609e05cfa2e3d7ada3b3cf8e7c58b09ccf44 Mon Sep 17 00:00:00 2001 From: yystopf Date: Tue, 26 Oct 2021 18:42:35 +0800 Subject: [PATCH] add: project rank and user rank api --- app/controllers/project_rank_controller.rb | 24 +++++++++++++++++++ app/controllers/user_rank_controller.rb | 24 +++++++++++++++++++ app/models/project.rb | 7 +++--- app/services/cache/v2/owner_common_service.rb | 14 +++++++++++ .../cache/v2/project_common_service.rb | 7 ++++-- app/services/cache/v2/project_rank_service.rb | 10 ++++++-- .../cache/v2/user_date_rank_service.rb | 7 +++--- app/views/project_rank/_detail.json.jbuilder | 19 +++++++++++++++ app/views/project_rank/index.json.jbuilder | 8 +++++++ app/views/user_rank/_detail.json.jbuilder | 15 ++++++++++++ app/views/user_rank/index.json.jbuilder | 8 +++++++ config/routes.rb | 3 +++ 12 files changed, 136 insertions(+), 10 deletions(-) create mode 100644 app/controllers/project_rank_controller.rb create mode 100644 app/controllers/user_rank_controller.rb create mode 100644 app/views/project_rank/_detail.json.jbuilder create mode 100644 app/views/project_rank/index.json.jbuilder create mode 100644 app/views/user_rank/_detail.json.jbuilder create mode 100644 app/views/user_rank/index.json.jbuilder diff --git a/app/controllers/project_rank_controller.rb b/app/controllers/project_rank_controller.rb new file mode 100644 index 000000000..07bc2fb0f --- /dev/null +++ b/app/controllers/project_rank_controller.rb @@ -0,0 +1,24 @@ +class ProjectRankController < ApplicationController + # 根据时间获取热门项目 + def index + $redis_cache.zunionstore("recent-days-project-rank", get_timeable_key_names) + @project_rank = $redis_cache.zrevrange("recent-days-project-rank", 0, 5, withscores: true) + rescue Exception => e + @project_rack = [] + end + + private + # 默认显示7天的 + def time + params.fetch(:time, 7).to_i + end + + def get_timeable_key_names + names_array = [] + (0...time).to_a.each do |i| + date_time_string = (Date.today - i.days).to_s + names_array << "v2-project-rank-#{date_time_string}" + end + names_array + end +end \ No newline at end of file diff --git a/app/controllers/user_rank_controller.rb b/app/controllers/user_rank_controller.rb new file mode 100644 index 000000000..734b94c84 --- /dev/null +++ b/app/controllers/user_rank_controller.rb @@ -0,0 +1,24 @@ +class UserRankController < ApplicationController + # 根据时间获取热门开发者 + def index + $redis_cache.zunionstore("recent-days-user-rank", get_timeable_key_names) + @user_rank = $redis_cache.zrevrange("recent-days-user-rank", 0, 5, withscores: true) + rescue Exception => e + @user_rank = [] + end + + private + # 默认显示7天的 + def time + params.fetch(:time, 7).to_i + end + + def get_timeable_key_names + names_array = [] + (0...time).to_a.each do |i| + date_time_string = (Date.today - i.days).to_s + names_array << "v2-user-rank-#{date_time_string}" + end + names_array + end +end \ No newline at end of file diff --git a/app/models/project.rb b/app/models/project.rb index 78c049ab2..c4c085096 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -127,9 +127,10 @@ class Project < ApplicationRecord has_many :has_pinned_users, through: :pinned_projects, source: :user has_many :webhooks, class_name: "Gitea::Webhook", primary_key: :gpid, foreign_key: :repo_id after_create :init_project_common, :incre_user_statistic, :incre_platform_statistic - after_save :check_project_members - before_save :set_invite_code, :reset_cache_data, :reset_unmember_followed - after_destroy :decre_project_common, :decre_user_statistic, :decre_platform_statistic + after_save :check_project_members, :reset_cache_data + before_save :set_invite_code, :reset_unmember_followed + before_destroy :decre_project_common + after_destroy :decre_user_statistic, :decre_platform_statistic scope :project_statics_select, -> {select(:id,:name, :is_public, :identifier, :status, :project_type, :user_id, :forked_count, :visits, :project_category_id, :project_language_id, :license_id, :ignore_id, :watchers_count, :created_on)} scope :no_anomory_projects, -> {where("projects.user_id is not null and projects.user_id != ?", 2)} scope :recommend, -> { visible.project_statics_select.where(recommend: true) } diff --git a/app/services/cache/v2/owner_common_service.rb b/app/services/cache/v2/owner_common_service.rb index 07183f811..62322b49c 100644 --- a/app/services/cache/v2/owner_common_service.rb +++ b/app/services/cache/v2/owner_common_service.rb @@ -31,6 +31,10 @@ class Cache::V2::OwnerCommonService < ApplicationService "v2-owner-common:#{@login}-#{@email.to_s}" end + def owner_common_key_by_id + "v2-owner-common:#{@owner.id}" + end + def owner_common $redis_cache.hgetall(owner_common_key).blank? ? reset_owner_common : $redis_cache.hgetall(owner_common_key) end @@ -46,6 +50,9 @@ class Cache::V2::OwnerCommonService < ApplicationService else $redis_cache.hset(owner_common_key, "name", @name) $redis_cache.hset(owner_common_key, "avatar_url", url_to_avatar(owner)) + + $redis_cache.hset(owner_common_key_by_id, "name", @name) + $redis_cache.hset(owner_common_key_by_id, "avatar_url", url_to_avatar(owner)) end end if @email.present? @@ -53,6 +60,7 @@ class Cache::V2::OwnerCommonService < ApplicationService reset_owner_email else $redis_cache.hset(owner_common_key, "email", @email) + $redis_cache.hset(owner_common_key_by_id, "email", @email) end end @@ -60,23 +68,29 @@ class Cache::V2::OwnerCommonService < ApplicationService end def reset_owner_id $redis_cache.hset(owner_common_key, "id", owner&.id) + $redis_cache.hset(owner_common_key_by_id, "id", owner&.id) end def reset_owner_type $redis_cache.hset(owner_common_key, "type", owner&.type) + $redis_cache.hset(owner_common_key_by_id, "type", owner&.type) end def reset_owner_login $redis_cache.hset(owner_common_key, "login", owner&.login) + $redis_cache.hset(owner_common_key_by_id, "login", owner&.login) end def reset_owner_email $redis_cache.hset(owner_common_key, "email", owner&.mail) + $redis_cache.hset(owner_common_key_by_id, "email", owner&.mail) end def reset_owner_name $redis_cache.hset(owner_common_key, "name", owner&.real_name) $redis_cache.hset(owner_common_key, "avatar_url", url_to_avatar(owner)) + $redis_cache.hset(owner_common_key_by_id, "name", owner&.real_name) + $redis_cache.hset(owner_common_key_by_id, "avatar_url", url_to_avatar(owner)) end def reset_owner_common diff --git a/app/services/cache/v2/project_common_service.rb b/app/services/cache/v2/project_common_service.rb index 6ea4bb3a9..841a0bb55 100644 --- a/app/services/cache/v2/project_common_service.rb +++ b/app/services/cache/v2/project_common_service.rb @@ -120,7 +120,10 @@ class Cache::V2::ProjectCommonService < ApplicationService Cache::V2::ProjectRankService.call(@project_id, {visits: @visits}) Cache::V2::ProjectDateRankService.call(@project_id, Date.today, {visits: @visits}) else - $redis_cache.hincrby(project_common_key, visits_key, @visits) + puts project_common_key + puts visits_key + puts @visits + $redis_cache.hincrby(project_common_key, visits_key, @visits.to_s) Cache::V2::ProjectRankService.call(@project_id, {visits: @visits}) Cache::V2::ProjectDateRankService.call(@project_id, Date.today, {visits: @visits}) end @@ -196,7 +199,7 @@ class Cache::V2::ProjectCommonService < ApplicationService end def reset_project_visits - $redis_cache.hset(project_common_key, visits_key, @project&.visits) + $redis_cache.hset(project_common_key, visits_key, @project&.visits || 0) end def reset_project_watchers diff --git a/app/services/cache/v2/project_rank_service.rb b/app/services/cache/v2/project_rank_service.rb index 089258d96..45484dc08 100644 --- a/app/services/cache/v2/project_rank_service.rb +++ b/app/services/cache/v2/project_rank_service.rb @@ -37,6 +37,7 @@ class Cache::V2::ProjectRankService < ApplicationService end def set_project_rank + load_project_common if $redis_cache.zscore(project_rank_key, @project_id).blank? reset_project_rank return @@ -56,16 +57,21 @@ class Cache::V2::ProjectRankService < ApplicationService if @pullrequests.present? $redis_cache.zincrby(project_rank_key, @pullrequests.to_i * 10, @project_id) end + reset_user_project_rank $redis_cache.zscore(project_rank_key, @project_id) end def reset_project_rank load_project_common - $redis_cache.zrem(project_rank_key, @project_id) score = @project_common["visits"].to_i * 1 + @project_common["praises"].to_i * 5 + @project_common["forks"].to_i * 5 + @project_common["issues"].to_i * 10 + @project_common["pullrequests"].to_i * 10 - $redis_cache.zincrby(project_rank_key, score, @project_id) + $redis_cache.zadd(project_rank_key, score, @project_id) + reset_user_project_rank $redis_cache.zscore(project_rank_key, @project_id) end + + def reset_user_project_rank + $redis_cache.zadd("v2-user-project-rank:#{@project_common["owner_id"]}", $redis_cache.zscore(project_rank_key, @project_id), @project_id) + end end \ No newline at end of file diff --git a/app/services/cache/v2/user_date_rank_service.rb b/app/services/cache/v2/user_date_rank_service.rb index 583f03a22..00073a8e8 100644 --- a/app/services/cache/v2/user_date_rank_service.rb +++ b/app/services/cache/v2/user_date_rank_service.rb @@ -93,7 +93,8 @@ class Cache::V2::UserDateRankService < ApplicationService fork_count = $redis_cache.hget(user_date_statistic_key, "fork-count") || 0 project_watchers_count = $redis_cache.hget(user_date_statistic_key, "project-watcher-count") || 0 project_praises_count = $redis_cache.hget(user_date_statistic_key, "project-praise-count") || 0 - project_languages_count = $redis_cache.hget(user_date_statistic_key, "project-language").nil? ? 0 : $redis_cache.hget(user_date_statistic_key, "project-language").length + project_language = $redis_cache.hget(user_date_statistic_key, "project-language") + project_languages_count = project_language.nil? || project_language == "{}" ? 0 : JSON.parse(project_language).length # 影响力 influence = (60.0 + follow_count.to_i / (follow_count.to_i + 20.0) * 40.0).to_i @@ -110,8 +111,8 @@ class Cache::V2::UserDateRankService < ApplicationService language = (60.0 + project_languages_count.to_i / (project_languages_count.to_i + 5.0) * 40.0).to_i score = influence+ contribution + activity + experience + language - - $redis_cache.zadd(user_rank_key, score, @user_id) if score.to_i > 300 + $redis_cache.zrem(user_rank_key, @user_id) + $redis_cache.zadd(user_rank_key, score-300, @user_id) if score > 300 $redis_cache.zscore(user_rank_key, @user_id) end diff --git a/app/views/project_rank/_detail.json.jbuilder b/app/views/project_rank/_detail.json.jbuilder new file mode 100644 index 000000000..454aee2cb --- /dev/null +++ b/app/views/project_rank/_detail.json.jbuilder @@ -0,0 +1,19 @@ +project_common = $redis_cache.hgetall("v2-project-common:#{item[0]}") +owner_common = $redis_cache.hgetall("v2-owner-common:#{project_common["owner_id"]}") +json.id item[0] +json.score item[1] +json.name project_common["name"] +json.identifier project_common["identifier"] +json.description project_common["description"] +json.owner do + json.id project_common["owner_id"] + json.name owner_common["name"] + json.login owner_common["login"] + json.avatar_url owner_common["avatar_url"] +end +json.visits project_common["visits"] +json.forks project_common["forks"] +json.watchers project_common["watchers"] +json.praises project_common["praises"] +json.issues project_common["issues"] +json.pulls project_common["pullrequests"] \ No newline at end of file diff --git a/app/views/project_rank/index.json.jbuilder b/app/views/project_rank/index.json.jbuilder new file mode 100644 index 000000000..84792ca7d --- /dev/null +++ b/app/views/project_rank/index.json.jbuilder @@ -0,0 +1,8 @@ +json.partial! "commons/success" +json.projects do + + json.array! @project_rank.each do |item| + json.partial! "detail", locals: {item: item} + end + +end \ No newline at end of file diff --git a/app/views/user_rank/_detail.json.jbuilder b/app/views/user_rank/_detail.json.jbuilder new file mode 100644 index 000000000..54afea5c4 --- /dev/null +++ b/app/views/user_rank/_detail.json.jbuilder @@ -0,0 +1,15 @@ +owner_common = $redis_cache.hgetall("v2-owner-common:#{item[0]}") +popular_project = $redis_cache.zrevrange("v2-user-project-rank:#{item[0]}", 0, 1, withscores: true)[0] +popular_project_common = $redis_cache.hgetall("v2-project-common:#{popular_project[0]}") +json.id item[0] +json.score item[1] +json.name owner_common["name"] +json.type owner_common["type"] +json.login owner_common["login"] +json.avatar_url owner_common["avatar_url"] +json.project do + json.id popular_project[0] + json.name popular_project_common["name"] + json.identifier popular_project_common["identifier"] + json.description popular_project_common["description"] +end \ No newline at end of file diff --git a/app/views/user_rank/index.json.jbuilder b/app/views/user_rank/index.json.jbuilder new file mode 100644 index 000000000..51ad153c4 --- /dev/null +++ b/app/views/user_rank/index.json.jbuilder @@ -0,0 +1,8 @@ +json.partial! "commons/success" +json.users do + + json.array! @user_rank.each do |item| + json.partial! "detail", locals: {item: item} + end + +end \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 35fea39c7..7f78cc8dd 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -73,6 +73,9 @@ Rails.application.routes.draw do resources :public_keys, only: [:index, :create, :destroy] + resources :project_rank, only: [:index] + resources :user_rank, only: [:index] + resources :statistic, only: [:index] do collection do get :platform_profile