. */ /** * Background job to delete prolific users without disrupting front-end too much. * * Up to 50 messages are deleted on each run through; when all messages are gone, * the actual account is deleted. * * @package QueueHandler * @maintainer Brion Vibber */ class DelUserQueueHandler extends QueueHandler { const DELETION_WINDOW = 50; public function transport() { return 'deluser'; } public function handle($user) { if (!($user instanceof User)) { common_log(LOG_ERR, "Got a bogus user, not deleting"); return true; } $user = User::getKV('id', $user->id); if (!$user) { common_log(LOG_INFO, "User {$user->nickname} was deleted before we got here."); return true; } try { if (!$user->hasRole(Profile_role::DELETED)) { common_log(LOG_INFO, "User {$user->nickname} is not pending deletion; aborting."); return true; } } catch (UserNoProfileException $unp) { common_log(LOG_INFO, "Deleting user {$user->nickname} with no profile... probably a good idea!"); } $notice = $this->getNextBatch($user); if ($notice->N) { common_log(LOG_INFO, "Deleting next {$notice->N} notices by {$user->nickname}"); while ($notice->fetch()) { $del = clone($notice); $del->delete(); } // @todo improve reliability in case we died during the above deletions // with a fatal error. If the job is lost, we should perform some kind // of garbage collection later. // Queue up the next batch. $qm = QueueManager::get(); $qm->enqueue($user, 'deluser'); } else { // Out of notices? Let's finish deleting this guy! $user->delete(); common_log(LOG_INFO, "User $user->id $user->nickname deleted."); return true; } return true; } /** * Fetch the next self::DELETION_WINDOW messages for this user. * @return Notice */ protected function getNextBatch(User $user) { $notice = new Notice(); $notice->profile_id = $user->id; $notice->limit(self::DELETION_WINDOW); $notice->find(); return $notice; } }