Skip to content

Commit 1684bf8

Browse files
authored
Merge pull request #1758 from codetriage/schneems/poke-inactive-update
Update poke-inactive mailer
2 parents aa03ffc + e88cf47 commit 1684bf8

File tree

14 files changed

+109
-79
lines changed

14 files changed

+109
-79
lines changed

app/mailers/user_mailer.rb

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,14 +75,22 @@ def send_triage(user:, assignment:, repo:, create: false)
7575
mail(to: @user.email, reply_to: "[email protected]", subject: "[CodeTriage] Help triage #{@repo.full_name}")
7676
end
7777

78-
def poke_inactive(user:, repos_by_need_ids:)
78+
def poke_inactive(user:, min_issue_count:, min_subscriber_count:)
7979
return unless set_and_check_user(user)
80-
@most_repo = Repo.order_by_issue_count.first
80+
languages = @user.favorite_languages&.sort || []
8181

82-
repo_need_id = repos_by_need_ids.detect { |id| id != @most_repo.id }
83-
@need_repo = Repo.where(id: repo_need_id).first
82+
query = Repo
83+
query = repo.where(language: languages) if !languages.empty?
84+
query = query
85+
.where("issues_count >= ?", min_issue_count)
86+
.where("subscribers_count >= ?", min_subscriber_count)
87+
88+
@repos = Random::CachedIdQuery.new(
89+
query: query,
90+
limit: 3,
91+
expires_in: 24.hours
92+
).call
8493

85-
@random_repo = Repo.rand.not_in(@most_repo.id, @need_repo.id).first || @most_repo || @need_repo
8694
mail(to: @user.email, reply_to: "[email protected]", subject: "CodeTriage misses you")
8795
end
8896

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Provides an actual random result exactly as expected
2+
# but it's cached for a period of time.
3+
#
4+
# Cache keys expire after the set time but
5+
# are unbounded. Take care to not pass in arbitrary data
6+
# from users into the query.
7+
#
8+
# The raw SQL is used for a cache key so take care
9+
# to pass in values in sorted order etc.
10+
#
11+
# The first run of this is VERY expensive on a large
12+
# model and can still cause significant database load
13+
class Random::CachedIdQuery
14+
private attr_reader :limit, :query, :key, :expires_in
15+
16+
def initialize(query:, limit:, expires_in:)
17+
@query = query.order("RANDOM()")
18+
@key = "random_cached_query:#{@query.to_sql.hash}"
19+
@expires_in = expires_in
20+
@limit = limit
21+
end
22+
23+
def call
24+
ids = Rails.cache.fetch(key, expires_in: expires_in) do
25+
query.select(:id).first(limit).map(&:id)
26+
end
27+
28+
query.klass.where(id: ids)
29+
end
30+
end

app/models/repo.rb

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -115,10 +115,6 @@ def weight
115115
end
116116
end
117117

118-
def subscriber_count
119-
users.count
120-
end
121-
122118
# pulls out number of issues divided by number of subscribers
123119
def self.order_by_need
124120
joins(:repo_subscriptions)
@@ -135,13 +131,6 @@ def self.not_in(*ids)
135131
where("repos.id not in (?)", ids)
136132
end
137133

138-
@@max_id = nil
139-
def self.rand
140-
@@max_id = self.maximum(:id) if @@max_id.nil?
141-
142-
where("id >= ?", Random.new.rand(1..@@max_id))
143-
end
144-
145134
def self.all_languages
146135
self.select("language").group("language").order("language ASC").map(&:language).reject(&:blank?)
147136
end

app/models/user.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,10 @@ def auth_is_valid?
103103
end
104104

105105
@@max_id = nil
106-
def self.random
106+
107+
# Much faster than order("RANDOM()") but it's
108+
# not guaranteed to return results
109+
def self.fast_rand
107110
@@max_id = self.maximum(:id) if @@max_id.nil?
108111

109112
where("id >= ?", Random.new.rand(1..@@max_id))

app/views/user_mailer/poke_inactive.html.erb

Lines changed: 0 additions & 26 deletions
This file was deleted.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
Hello <%= @user.github %>,
2+
3+
You're getting this email because you've signed up for [CodeTriage](<%= root_url %>), but haven't subscribed to any repos yet. Here are some tips for getting started.
4+
5+
### Tips and tricks
6+
7+
- Open source tip: Not sure how to get started? Read [picking the right repo](https://www.codetriage.com/university/picking_a_repo) from the [CodeTriage University](<%= university_index_url %>).
8+
- Open source tip: More of a visual learner? [Watch Richard triage issues in real time](https://www.schneems.com/2020/09/22/triage-with-me-11-issues-2-prs-in-15-hours/) (about 7 minutes per issue) from the [CodeTriage University](<%= university_index_url %>).
9+
- Want more? The ["How to Open Source" is a comprehensive contribution manual](https://howtoopensource.dev/). Click through for a free sample chapter.
10+
11+
### Suggested repos
12+
13+
<% @repos.each do |repo| %>
14+
- **<%= repo.language %>: <%= repo.full_name %>** ([Subscribe](<%= repo_url(repo) %>))
15+
<% end %>
16+
17+
If you don't like any of those [add your own repo](<%= new_repo_url %>) or [browse all repos](<%= root_url %>).
18+
19+
<% if @user.favorite_languages.blank? %>
20+
21+
### Tell us your favorite progrmaming languages
22+
23+
CodeTriage can help you pick a repo. All you have to do is tell us the programming language(s) you most commonly use:
24+
25+
[Select your favorite languages(s)](user_url(@user))
26+
27+
<% end %>
28+
29+
### See you next week
30+
31+
Subscribe to a repo, or you will get this same email next week, maybe with different suggestions. To unsubscribe entirely, [delete your account](<%= user_url(@user) %>), but don't do that, subscribe to a repo and start your open source journey. We believe in you!
32+
33+
--
34+
For open source tips, follow [@HowToOpenSource](https://twitter.com/HowToOpenSource) on Twitter.

app/views/user_mailer/poke_inactive.text.erb

Lines changed: 0 additions & 27 deletions
This file was deleted.

config/initializers/git_hub_bub.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ def call
3333
@mutex.synchronize do
3434
return if @keys.any?
3535

36-
@keys = User.random.where.not(token: nil).limit(5000).pluck(:token)
36+
@keys = User.fast_rand.where.not(token: nil).limit(5000).pluck(:token)
3737

3838
if @keys.empty? && User.where.not(token: nil).empty?
3939
raise "No users with tokens in the database"
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class AddIndexSubscriberCount < ActiveRecord::Migration[7.0]
2+
def change
3+
add_index :repos, :subscribers_count
4+
end
5+
end

db/schema.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#
1111
# It's strongly recommended that you check this file into your version control system.
1212

13-
ActiveRecord::Schema[7.0].define(version: 2022_10_13_212959) do
13+
ActiveRecord::Schema[7.0].define(version: 2022_12_28_065556) do
1414
# These are extensions that must be enabled in order to support this database
1515
enable_extension "pg_stat_statements"
1616
enable_extension "plpgsql"
@@ -161,6 +161,7 @@
161161
t.index ["issues_count"], name: "index_repos_on_issues_count"
162162
t.index ["language"], name: "index_repos_on_language"
163163
t.index ["name", "user_name"], name: "index_repos_on_name_and_user_name", unique: true
164+
t.index ["subscribers_count"], name: "index_repos_on_subscribers_count"
164165
t.index ["user_name"], name: "index_repos_on_user_name"
165166
end
166167

0 commit comments

Comments
 (0)