mirror of
https://github.com/discourse/discourse.git
synced 2024-12-30 16:43:44 +08:00
b704e338ef
So it can easily be overwritten in a plugin for example.
### Added more tests to provide better coverage
We previously only had `u.silenced_till IS NULL` but I made it consistent with pretty much every other places where we check for "active" users.
These two new lines do change the query a tiny bit though.
**Before**
- You could not get the badge if you were currently silenced (no matter what period is being checked)
- You could get the badge if you were suspended 😬
**After**
- You can't get the badge if you were silenced during the past year
- You can't get the badge if you were suspended during the past year
### Improved the performance of the query by using `NOT EXISTS` instead of `LEFT JOIN / COUNT() = 0`
There is no difference in behaviour between
```sql
LEFT JOIN user_badges AS ub ON ub.user_id = u.id AND ...
[...]
HAVING COUNT(ub.*) = 0
```
and
```sql
NOT EXISTS (SELECT 1 FROM user_badges AS ub WHERE ub.user_id = u.id AND ...)
```
The only difference is performance-wise. The `NOT EXISTS` is 10-30% faster on very large databases (aka. posts and users in X millions). I checked on 3 of the largest datasets I could find.
23 lines
593 B
Ruby
23 lines
593 B
Ruby
# frozen_string_literal: true
|
|
|
|
module Jobs
|
|
class GrantAnniversaryBadges < ::Jobs::Scheduled
|
|
every 1.day
|
|
|
|
def execute(args)
|
|
return unless SiteSetting.enable_badges?
|
|
return unless badge = Badge.find_by(id: Badge::Anniversary, enabled: true)
|
|
|
|
start_date = args[:start_date] || 1.year.ago
|
|
end_date = start_date + 1.year
|
|
|
|
sql = BadgeQueries.anniversaries(start_date, end_date)
|
|
user_ids = DB.query_single(sql)
|
|
|
|
User
|
|
.where(id: user_ids)
|
|
.find_each { |user| BadgeGranter.grant(badge, user, created_at: end_date) }
|
|
end
|
|
end
|
|
end
|