Merge branch 'master' into glitch-soc/master
Conflicts: config/routes.rb Added the “endorsements” route from upstream.
This commit is contained in:
@ -43,7 +43,7 @@ class AccountsController < ApplicationController
|
||||
format.json do
|
||||
skip_session!
|
||||
|
||||
render_cached_json(['activitypub', 'actor', @account.cache_key], content_type: 'application/activity+json') do
|
||||
render_cached_json(['activitypub', 'actor', @account], content_type: 'application/activity+json') do
|
||||
ActiveModelSerializers::SerializableResource.new(@account, serializer: ActivityPub::ActorSerializer, adapter: ActivityPub::Adapter)
|
||||
end
|
||||
end
|
||||
|
72
app/controllers/api/v1/endorsements_controller.rb
Normal file
72
app/controllers/api/v1/endorsements_controller.rb
Normal file
@ -0,0 +1,72 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1::EndorsementsController < Api::BaseController
|
||||
before_action -> { doorkeeper_authorize! :read, :'read:accounts' }
|
||||
before_action :require_user!
|
||||
after_action :insert_pagination_headers
|
||||
|
||||
respond_to :json
|
||||
|
||||
def index
|
||||
@accounts = load_accounts
|
||||
render json: @accounts, each_serializer: REST::AccountSerializer
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def load_accounts
|
||||
if unlimited?
|
||||
endorsed_accounts.all
|
||||
else
|
||||
endorsed_accounts.paginate_by_max_id(
|
||||
limit_param(DEFAULT_ACCOUNTS_LIMIT),
|
||||
params[:max_id],
|
||||
params[:since_id]
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def endorsed_accounts
|
||||
current_account.endorsed_accounts
|
||||
end
|
||||
|
||||
def insert_pagination_headers
|
||||
set_pagination_headers(next_path, prev_path)
|
||||
end
|
||||
|
||||
def next_path
|
||||
return if unlimited?
|
||||
|
||||
if records_continue?
|
||||
api_v1_endorsements_url pagination_params(max_id: pagination_max_id)
|
||||
end
|
||||
end
|
||||
|
||||
def prev_path
|
||||
return if unlimited?
|
||||
|
||||
unless @accounts.empty?
|
||||
api_v1_endorsements_url pagination_params(since_id: pagination_since_id)
|
||||
end
|
||||
end
|
||||
|
||||
def pagination_max_id
|
||||
@accounts.last.id
|
||||
end
|
||||
|
||||
def pagination_since_id
|
||||
@accounts.first.id
|
||||
end
|
||||
|
||||
def records_continue?
|
||||
@accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
|
||||
end
|
||||
|
||||
def pagination_params(core_params)
|
||||
params.slice(:limit).permit(:limit).merge(core_params)
|
||||
end
|
||||
|
||||
def unlimited?
|
||||
params[:limit] == '0'
|
||||
end
|
||||
end
|
@ -17,8 +17,7 @@ class Api::V1::StatusesController < Api::BaseController
|
||||
CONTEXT_LIMIT = 4_096
|
||||
|
||||
def show
|
||||
cached = Rails.cache.read(@status.cache_key)
|
||||
@status = cached unless cached.nil?
|
||||
@status = cache_collection([@status], Status).first
|
||||
render json: @status, serializer: REST::StatusSerializer
|
||||
end
|
||||
|
||||
|
@ -178,12 +178,8 @@ class ApplicationController < ActionController::Base
|
||||
return raw unless klass.respond_to?(:with_includes)
|
||||
|
||||
raw = raw.cache_ids.to_a if raw.is_a?(ActiveRecord::Relation)
|
||||
uncached_ids = []
|
||||
cached_keys_with_value = Rails.cache.read_multi(*raw.map(&:cache_key))
|
||||
|
||||
raw.each do |item|
|
||||
uncached_ids << item.id unless cached_keys_with_value.key?(item.cache_key)
|
||||
end
|
||||
cached_keys_with_value = Rails.cache.read_multi(*raw).transform_keys(&:id)
|
||||
uncached_ids = raw.map(&:id) - cached_keys_with_value.keys
|
||||
|
||||
klass.reload_stale_associations!(cached_keys_with_value.values) if klass.respond_to?(:reload_stale_associations!)
|
||||
|
||||
@ -191,11 +187,11 @@ class ApplicationController < ActionController::Base
|
||||
uncached = klass.where(id: uncached_ids).with_includes.map { |item| [item.id, item] }.to_h
|
||||
|
||||
uncached.each_value do |item|
|
||||
Rails.cache.write(item.cache_key, item)
|
||||
Rails.cache.write(item, item)
|
||||
end
|
||||
end
|
||||
|
||||
raw.map { |item| cached_keys_with_value[item.cache_key] || uncached[item.id] }.compact
|
||||
raw.map { |item| cached_keys_with_value[item.id] || uncached[item.id] }.compact
|
||||
end
|
||||
|
||||
def respond_with_error(code)
|
||||
@ -211,7 +207,6 @@ class ApplicationController < ActionController::Base
|
||||
|
||||
def render_cached_json(cache_key, **options)
|
||||
options[:expires_in] ||= 3.minutes
|
||||
cache_key = cache_key.join(':') if cache_key.is_a?(Enumerable)
|
||||
cache_public = options.key?(:public) ? options.delete(:public) : true
|
||||
content_type = options.delete(:content_type) || 'application/json'
|
||||
|
||||
|
@ -9,7 +9,7 @@ class EmojisController < ApplicationController
|
||||
format.json do
|
||||
skip_session!
|
||||
|
||||
render_cached_json(['activitypub', 'emoji', @emoji.cache_key], content_type: 'application/activity+json') do
|
||||
render_cached_json(['activitypub', 'emoji', @emoji], content_type: 'application/activity+json') do
|
||||
ActiveModelSerializers::SerializableResource.new(@emoji, serializer: ActivityPub::EmojiSerializer, adapter: ActivityPub::Adapter)
|
||||
end
|
||||
end
|
||||
|
@ -34,7 +34,7 @@ class StatusesController < ApplicationController
|
||||
format.json do
|
||||
skip_session! unless @stream_entry.hidden?
|
||||
|
||||
render_cached_json(['activitypub', 'note', @status.cache_key], content_type: 'application/activity+json', public: !@stream_entry.hidden?) do
|
||||
render_cached_json(['activitypub', 'note', @status], content_type: 'application/activity+json', public: !@stream_entry.hidden?) do
|
||||
ActiveModelSerializers::SerializableResource.new(@status, serializer: ActivityPub::NoteSerializer, adapter: ActivityPub::Adapter)
|
||||
end
|
||||
end
|
||||
@ -44,7 +44,7 @@ class StatusesController < ApplicationController
|
||||
def activity
|
||||
skip_session!
|
||||
|
||||
render_cached_json(['activitypub', 'activity', @status.cache_key], content_type: 'application/activity+json', public: !@stream_entry.hidden?) do
|
||||
render_cached_json(['activitypub', 'activity', @status], content_type: 'application/activity+json', public: !@stream_entry.hidden?) do
|
||||
ActiveModelSerializers::SerializableResource.new(@status, serializer: ActivityPub::ActivitySerializer, adapter: ActivityPub::Adapter)
|
||||
end
|
||||
end
|
||||
|
@ -55,7 +55,7 @@ export function expandTimeline(timelineId, path, params = {}, done = noOp) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!params.max_id && timeline.get('items', ImmutableList()).size > 0) {
|
||||
if (!params.max_id && !params.pinned && timeline.get('items', ImmutableList()).size > 0) {
|
||||
params.since_id = timeline.getIn(['items', 0]);
|
||||
}
|
||||
|
||||
|
@ -137,7 +137,7 @@ class DropdownMenu extends React.PureComponent {
|
||||
// It should not be transformed when mounting because the resulting
|
||||
// size will be used to determine the coordinate of the menu by
|
||||
// react-overlays
|
||||
<div className='dropdown-menu' style={{ ...style, opacity: opacity, transform: mounted ? `scale(${scaleX}, ${scaleY})` : null }} ref={this.setRef}>
|
||||
<div className={`dropdown-menu ${placement}`} style={{ ...style, opacity: opacity, transform: mounted ? `scale(${scaleX}, ${scaleY})` : null }} ref={this.setRef}>
|
||||
<div className={`dropdown-menu__arrow ${placement}`} style={{ left: arrowOffsetLeft, top: arrowOffsetTop }} />
|
||||
|
||||
<ul>
|
||||
|
@ -28,6 +28,7 @@ class PrivacyDropdownMenu extends React.PureComponent {
|
||||
style: PropTypes.object,
|
||||
items: PropTypes.array.isRequired,
|
||||
value: PropTypes.string.isRequired,
|
||||
placement: PropTypes.string.isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
};
|
||||
@ -119,7 +120,7 @@ class PrivacyDropdownMenu extends React.PureComponent {
|
||||
|
||||
render () {
|
||||
const { mounted } = this.state;
|
||||
const { style, items, value } = this.props;
|
||||
const { style, items, placement, value } = this.props;
|
||||
|
||||
return (
|
||||
<Motion defaultStyle={{ opacity: 0, scaleX: 0.85, scaleY: 0.75 }} style={{ opacity: spring(1, { damping: 35, stiffness: 400 }), scaleX: spring(1, { damping: 35, stiffness: 400 }), scaleY: spring(1, { damping: 35, stiffness: 400 }) }}>
|
||||
@ -127,7 +128,7 @@ class PrivacyDropdownMenu extends React.PureComponent {
|
||||
// It should not be transformed when mounting because the resulting
|
||||
// size will be used to determine the coordinate of the menu by
|
||||
// react-overlays
|
||||
<div className='privacy-dropdown__dropdown' style={{ ...style, opacity: opacity, transform: mounted ? `scale(${scaleX}, ${scaleY})` : null }} role='listbox' ref={this.setRef}>
|
||||
<div className={`privacy-dropdown__dropdown ${placement}`} style={{ ...style, opacity: opacity, transform: mounted ? `scale(${scaleX}, ${scaleY})` : null }} role='listbox' ref={this.setRef}>
|
||||
{items.map(item => (
|
||||
<div role='option' tabIndex='0' key={item.value} data-index={item.value} onKeyDown={this.handleKeyDown} onClick={this.handleClick} className={classNames('privacy-dropdown__option', { active: item.value === value })} aria-selected={item.value === value} ref={item.value === value ? this.setFocusRef : null}>
|
||||
<div className='privacy-dropdown__option__icon'>
|
||||
@ -226,7 +227,7 @@ export default class PrivacyDropdown extends React.PureComponent {
|
||||
const valueOption = this.options.find(item => item.value === value);
|
||||
|
||||
return (
|
||||
<div className={classNames('privacy-dropdown', { active: open })} onKeyDown={this.handleKeyDown}>
|
||||
<div className={classNames('privacy-dropdown', placement, { active: open })} onKeyDown={this.handleKeyDown}>
|
||||
<div className={classNames('privacy-dropdown__value', { active: this.options.indexOf(valueOption) === 0 })}>
|
||||
<IconButton
|
||||
className='privacy-dropdown__value-icon'
|
||||
@ -247,6 +248,7 @@ export default class PrivacyDropdown extends React.PureComponent {
|
||||
value={value}
|
||||
onClose={this.handleClose}
|
||||
onChange={this.handleChange}
|
||||
placement={placement}
|
||||
/>
|
||||
</Overlay>
|
||||
</div>
|
||||
|
@ -89,6 +89,7 @@ const keyMap = {
|
||||
goToProfile: 'g u',
|
||||
goToBlocked: 'g b',
|
||||
goToMuted: 'g m',
|
||||
goToRequests: 'g r',
|
||||
toggleHidden: 'x',
|
||||
};
|
||||
|
||||
@ -427,6 +428,10 @@ export default class UI extends React.PureComponent {
|
||||
this.context.router.history.push('/mutes');
|
||||
}
|
||||
|
||||
handleHotkeyGoToRequests = () => {
|
||||
this.context.router.history.push('/follow_requests');
|
||||
}
|
||||
|
||||
render () {
|
||||
const { draggingOver } = this.state;
|
||||
const { children, isComposing, location, dropdownMenuIsOpen } = this.props;
|
||||
@ -449,6 +454,7 @@ export default class UI extends React.PureComponent {
|
||||
goToProfile: this.handleHotkeyGoToProfile,
|
||||
goToBlocked: this.handleHotkeyGoToBlocked,
|
||||
goToMuted: this.handleHotkeyGoToMuted,
|
||||
goToRequests: this.handleHotkeyGoToRequests,
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { createSelector } from 'reselect';
|
||||
import { List as ImmutableList } from 'immutable';
|
||||
import { me } from '../initial_state';
|
||||
|
||||
const getAccountBase = (state, id) => state.getIn(['accounts', id], null);
|
||||
const getAccountCounters = (state, id) => state.getIn(['accounts_counters', id], null);
|
||||
@ -83,7 +84,7 @@ export const makeGetStatus = () => {
|
||||
statusReblog = null;
|
||||
}
|
||||
|
||||
const regex = regexFromFilters(filters);
|
||||
const regex = (accountReblog || accountBase).get('id') !== me && regexFromFilters(filters);
|
||||
const filtered = regex && regex.test(statusBase.get('reblog') ? statusReblog.get('search_index') : statusBase.get('search_index'));
|
||||
|
||||
return statusBase.withMutations(map => {
|
||||
|
@ -230,7 +230,6 @@
|
||||
|
||||
.dropdown-menu {
|
||||
position: absolute;
|
||||
transform-origin: 50% 0;
|
||||
}
|
||||
|
||||
.invisible {
|
||||
@ -1634,6 +1633,22 @@ a.account__display-name {
|
||||
ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
&.left {
|
||||
transform-origin: 100% 50%;
|
||||
}
|
||||
|
||||
&.top {
|
||||
transform-origin: 50% 100%;
|
||||
}
|
||||
|
||||
&.bottom {
|
||||
transform-origin: 50% 0;
|
||||
}
|
||||
|
||||
&.right {
|
||||
transform-origin: 0 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-menu__arrow {
|
||||
@ -3300,7 +3315,14 @@ a.status-card {
|
||||
border-radius: 4px;
|
||||
margin-left: 40px;
|
||||
overflow: hidden;
|
||||
transform-origin: 50% 0;
|
||||
|
||||
&.top {
|
||||
transform-origin: 50% 100%;
|
||||
}
|
||||
|
||||
&.bottom {
|
||||
transform-origin: 50% 0;
|
||||
}
|
||||
}
|
||||
|
||||
.privacy-dropdown__option {
|
||||
@ -3372,6 +3394,10 @@ a.status-card {
|
||||
}
|
||||
}
|
||||
|
||||
&.top .privacy-dropdown__value {
|
||||
border-radius: 0 0 4px 4px;
|
||||
}
|
||||
|
||||
.privacy-dropdown__dropdown {
|
||||
display: block;
|
||||
box-shadow: 2px 4px 6px rgba($base-shadow-color, 0.1);
|
||||
@ -4176,6 +4202,10 @@ a.status-card {
|
||||
color: $highlight-text-color;
|
||||
}
|
||||
|
||||
.status__content p {
|
||||
color: $inverted-text-color;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 480px) {
|
||||
max-height: 10vh;
|
||||
}
|
||||
|
@ -154,9 +154,8 @@ code {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
li {
|
||||
float: left;
|
||||
width: 50%;
|
||||
ul {
|
||||
columns: 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
#
|
||||
|
||||
class AccountPin < ApplicationRecord
|
||||
include Paginable
|
||||
include RelationshipCacheable
|
||||
|
||||
belongs_to :account
|
||||
|
@ -23,7 +23,7 @@ class Form::StatusBatch
|
||||
media_attached_status_ids = MediaAttachment.where(status_id: status_ids).pluck(:status_id)
|
||||
|
||||
ApplicationRecord.transaction do
|
||||
Status.where(id: media_attached_status_ids).find_each do |status|
|
||||
Status.where(id: media_attached_status_ids).reorder(nil).find_each do |status|
|
||||
status.update!(sensitive: sensitive)
|
||||
log_action :update, status
|
||||
end
|
||||
@ -35,7 +35,7 @@ class Form::StatusBatch
|
||||
end
|
||||
|
||||
def delete_statuses
|
||||
Status.where(id: status_ids).find_each do |status|
|
||||
Status.where(id: status_ids).reorder(nil).find_each do |status|
|
||||
RemovalWorker.perform_async(status.id)
|
||||
log_action :destroy, status
|
||||
end
|
||||
|
@ -39,8 +39,6 @@ class Notification < ApplicationRecord
|
||||
validates :account_id, uniqueness: { scope: [:activity_type, :activity_id] }
|
||||
validates :activity_type, inclusion: { in: TYPE_CLASS_MAP.values }
|
||||
|
||||
scope :cache_ids, -> { select(:id, :updated_at, :activity_type, :activity_id) }
|
||||
|
||||
scope :browserable, ->(exclude_types = []) {
|
||||
types = TYPE_CLASS_MAP.values - activity_types_from_types(exclude_types + [:follow_request])
|
||||
where(activity_type: types)
|
||||
@ -68,6 +66,10 @@ class Notification < ApplicationRecord
|
||||
end
|
||||
|
||||
class << self
|
||||
def cache_ids
|
||||
select(:id, :updated_at, :activity_type, :activity_id)
|
||||
end
|
||||
|
||||
def reload_stale_associations!(cached_items)
|
||||
account_ids = (cached_items.map(&:from_account_id) + cached_items.map { |item| item.target_status&.account_id }.compact).uniq
|
||||
|
||||
|
@ -26,8 +26,6 @@
|
||||
#
|
||||
|
||||
class Status < ApplicationRecord
|
||||
self.cache_versioning = false
|
||||
|
||||
include Paginable
|
||||
include Streamable
|
||||
include Cacheable
|
||||
|
@ -15,13 +15,13 @@ class AfterBlockDomainFromAccountService < BaseService
|
||||
private
|
||||
|
||||
def reject_existing_followers!
|
||||
@account.passive_relationships.where(account: Account.where(domain: @domain)).includes(:account).find_each do |follow|
|
||||
@account.passive_relationships.where(account: Account.where(domain: @domain)).includes(:account).reorder(nil).find_each do |follow|
|
||||
reject_follow!(follow)
|
||||
end
|
||||
end
|
||||
|
||||
def reject_pending_follow_requests!
|
||||
FollowRequest.where(target_account: @account).where(account: Account.where(domain: @domain)).includes(:account).find_each do |follow_request|
|
||||
FollowRequest.where(target_account: @account).where(account: Account.where(domain: @domain)).includes(:account).reorder(nil).find_each do |follow_request|
|
||||
reject_follow!(follow_request)
|
||||
end
|
||||
end
|
||||
|
@ -18,7 +18,7 @@ class BackupService < BaseService
|
||||
def build_json!
|
||||
@collection = serialize(collection_presenter, ActivityPub::CollectionSerializer)
|
||||
|
||||
account.statuses.with_includes.find_in_batches do |statuses|
|
||||
account.statuses.with_includes.reorder(nil).find_in_batches do |statuses|
|
||||
statuses.each do |status|
|
||||
item = serialize(status, ActivityPub::ActivitySerializer)
|
||||
item.delete(:'@context')
|
||||
@ -60,7 +60,7 @@ class BackupService < BaseService
|
||||
end
|
||||
|
||||
def dump_media_attachments!(tar)
|
||||
MediaAttachment.attached.where(account: account).find_in_batches do |media_attachments|
|
||||
MediaAttachment.attached.where(account: account).reorder(nil).find_in_batches do |media_attachments|
|
||||
media_attachments.each do |m|
|
||||
download_to_tar(tar, m.file, m.file.path)
|
||||
end
|
||||
|
@ -43,14 +43,14 @@ class BlockDomainService < BaseService
|
||||
end
|
||||
|
||||
def suspend_accounts!
|
||||
blocked_domain_accounts.where(suspended: false).find_each do |account|
|
||||
blocked_domain_accounts.where(suspended: false).reorder(nil).find_each do |account|
|
||||
UnsubscribeService.new.call(account) if account.subscribed?
|
||||
SuspendAccountService.new.call(account)
|
||||
end
|
||||
end
|
||||
|
||||
def clear_account_images!
|
||||
blocked_domain_accounts.find_each do |account|
|
||||
blocked_domain_accounts.reorder(nil).find_each do |account|
|
||||
account.avatar.destroy if account.avatar.exists?
|
||||
account.header.destroy if account.header.exists?
|
||||
account.save
|
||||
@ -58,7 +58,7 @@ class BlockDomainService < BaseService
|
||||
end
|
||||
|
||||
def clear_account_attachments!
|
||||
media_from_blocked_domain.find_each do |attachment|
|
||||
media_from_blocked_domain.reorder(nil).find_each do |attachment|
|
||||
@affected_status_ids << attachment.status_id if attachment.status_id.present?
|
||||
|
||||
attachment.file.destroy if attachment.file.exists?
|
||||
|
@ -43,13 +43,13 @@ class RemoveStatusService < BaseService
|
||||
end
|
||||
|
||||
def remove_from_followers
|
||||
@account.followers_for_local_distribution.find_each do |follower|
|
||||
@account.followers_for_local_distribution.reorder(nil).find_each do |follower|
|
||||
FeedManager.instance.unpush_from_home(follower, @status)
|
||||
end
|
||||
end
|
||||
|
||||
def remove_from_lists
|
||||
@account.lists_for_local_distribution.select(:id, :account_id).find_each do |list|
|
||||
@account.lists_for_local_distribution.select(:id, :account_id).reorder(nil).find_each do |list|
|
||||
FeedManager.instance.unpush_from_list(list, @status)
|
||||
end
|
||||
end
|
||||
|
@ -23,9 +23,7 @@ class SuspendAccountService < BaseService
|
||||
|
||||
def purge_content!
|
||||
if @account.local?
|
||||
ActivityPub::RawDistributionWorker.perform_async(delete_actor_json, @account.id)
|
||||
|
||||
ActivityPub::DeliveryWorker.push_bulk(Relay.enabled.pluck(:inbox_url)) do |inbox_url|
|
||||
ActivityPub::DeliveryWorker.push_bulk(delivery_inboxes) do |inbox_url|
|
||||
[delete_actor_json, @account.id, inbox_url]
|
||||
end
|
||||
end
|
||||
@ -75,4 +73,8 @@ class SuspendAccountService < BaseService
|
||||
|
||||
@delete_actor_json = Oj.dump(ActivityPub::LinkedDataSignature.new(payload).sign!(@account))
|
||||
end
|
||||
|
||||
def delivery_inboxes
|
||||
Account.inboxes + Relay.enabled.pluck(:inbox_url)
|
||||
end
|
||||
end
|
||||
|
@ -8,7 +8,7 @@ class Maintenance::UncacheMediaWorker
|
||||
def perform(media_attachment_id)
|
||||
media = MediaAttachment.find(media_attachment_id)
|
||||
|
||||
return unless media.file.exists?
|
||||
return if media.file.blank?
|
||||
|
||||
media.file.destroy
|
||||
media.save
|
||||
|
@ -9,7 +9,7 @@ class RefollowWorker
|
||||
target_account = Account.find(target_account_id)
|
||||
return unless target_account.protocol == :activitypub
|
||||
|
||||
target_account.followers.where(domain: nil).find_each do |follower|
|
||||
target_account.followers.where(domain: nil).reorder(nil).find_each do |follower|
|
||||
# Locally unfollow remote account
|
||||
follower.unfollow!(target_account)
|
||||
|
||||
|
@ -3,8 +3,10 @@
|
||||
class Scheduler::BackupCleanupScheduler
|
||||
include Sidekiq::Worker
|
||||
|
||||
sidekiq_options unique: :until_executed
|
||||
|
||||
def perform
|
||||
old_backups.find_each(&:destroy!)
|
||||
old_backups.reorder(nil).find_each(&:destroy!)
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -3,6 +3,8 @@
|
||||
class Scheduler::DoorkeeperCleanupScheduler
|
||||
include Sidekiq::Worker
|
||||
|
||||
sidekiq_options unique: :until_executed
|
||||
|
||||
def perform
|
||||
Doorkeeper::AccessToken.where('revoked_at IS NOT NULL').where('revoked_at < NOW()').delete_all
|
||||
Doorkeeper::AccessGrant.where('revoked_at IS NOT NULL').where('revoked_at < NOW()').delete_all
|
||||
|
@ -3,8 +3,10 @@
|
||||
class Scheduler::EmailScheduler
|
||||
include Sidekiq::Worker
|
||||
|
||||
sidekiq_options unique: :until_executed
|
||||
|
||||
def perform
|
||||
eligible_users.find_each do |user|
|
||||
eligible_users.reorder(nil).find_each do |user|
|
||||
next unless user.allows_digest_emails?
|
||||
DigestMailerWorker.perform_async(user.id)
|
||||
end
|
||||
|
@ -3,6 +3,8 @@
|
||||
class Scheduler::FeedCleanupScheduler
|
||||
include Sidekiq::Worker
|
||||
|
||||
sidekiq_options unique: :until_executed
|
||||
|
||||
def perform
|
||||
clean_home_feeds!
|
||||
clean_list_feeds!
|
||||
|
@ -5,6 +5,8 @@ class Scheduler::IpCleanupScheduler
|
||||
|
||||
RETENTION_PERIOD = 1.year
|
||||
|
||||
sidekiq_options unique: :until_executed
|
||||
|
||||
def perform
|
||||
time_ago = RETENTION_PERIOD.ago
|
||||
SessionActivation.where('updated_at < ?', time_ago).destroy_all
|
||||
|
@ -3,6 +3,8 @@
|
||||
class Scheduler::MediaCleanupScheduler
|
||||
include Sidekiq::Worker
|
||||
|
||||
sidekiq_options unique: :until_executed
|
||||
|
||||
def perform
|
||||
unattached_media.find_each(&:destroy)
|
||||
end
|
||||
|
@ -3,6 +3,8 @@
|
||||
class Scheduler::SubscriptionsCleanupScheduler
|
||||
include Sidekiq::Worker
|
||||
|
||||
sidekiq_options unique: :until_executed
|
||||
|
||||
def perform
|
||||
Subscription.expired.in_batches.delete_all
|
||||
end
|
||||
|
@ -3,6 +3,8 @@
|
||||
class Scheduler::SubscriptionsScheduler
|
||||
include Sidekiq::Worker
|
||||
|
||||
sidekiq_options unique: :until_executed
|
||||
|
||||
def perform
|
||||
Pubsubhubbub::SubscribeWorker.push_bulk(expiring_accounts.pluck(:id))
|
||||
end
|
||||
|
@ -3,8 +3,10 @@
|
||||
class Scheduler::UserCleanupScheduler
|
||||
include Sidekiq::Worker
|
||||
|
||||
sidekiq_options unique: :until_executed
|
||||
|
||||
def perform
|
||||
User.where('confirmed_at is NULL AND confirmation_sent_at <= ?', 2.days.ago).find_in_batches do |batch|
|
||||
User.where('confirmed_at is NULL AND confirmation_sent_at <= ?', 2.days.ago).reorder(nil).find_in_batches do |batch|
|
||||
Account.where(id: batch.map(&:account_id)).delete_all
|
||||
User.where(id: batch.map(&:id)).delete_all
|
||||
end
|
||||
|
Reference in New Issue
Block a user