Jelajahi Sumber

Update delete pipelines

Daniel Supernault 2 tahun lalu
induk
melakukan
1cdc0fe8ed

+ 91 - 136
app/Jobs/DeletePipeline/DeleteAccountPipeline.php

@@ -50,6 +50,10 @@ use App\{
 	UserFilter,
 	UserSetting,
 };
+use App\Models\Conversation;
+use App\Models\Poll;
+use App\Models\PollVote;
+use App\Models\Portfolio;
 use App\Models\UserPronoun;
 
 class DeleteAccountPipeline implements ShouldQueue
@@ -59,6 +63,9 @@ class DeleteAccountPipeline implements ShouldQueue
 	protected $user;
 
 	public $timeout = 900;
+    public $tries = 3;
+    public $maxExceptions = 1;
+    public $deleteWhenMissingModels = true;
 
 	public function __construct(User $user)
 	{
@@ -68,160 +75,108 @@ class DeleteAccountPipeline implements ShouldQueue
 	public function handle()
 	{
 		$user = $this->user;
+        $profile = $user->profile;
+		$id = $user->profile_id;
 		$this->deleteUserColumns($user);
 		AccountService::del($user->profile_id);
 
-		DB::transaction(function() use ($user) {
-			AccountLog::whereItemType('App\User')->whereItemId($user->id)->forceDelete();
-		});
+		AccountLog::whereItemType('App\User')->whereItemId($user->id)->forceDelete();
 
-		DB::transaction(function() use ($user) {
-			AccountInterstitial::whereUserId($user->id)->delete();
-		});
+		AccountInterstitial::whereUserId($user->id)->delete();
 
-		DB::transaction(function() use ($user) {
-			if($user->profile) {
-				$avatar = $user->profile->avatar;
-				$path = $avatar->media_path;
-				if(!in_array($path, [
-					'public/avatars/default.jpg',
-					'public/avatars/default.png'
-				])) {
-					if(config('pixelfed.cloud_storage')) {
-						$disk = Storage::disk(config('filesystems.cloud'));
-						if($disk->exists($path)) {
-							$disk->delete($path);
-						}
-					}
-					$disk = Storage::disk(config('filesystems.local'));
-					if($disk->exists($path)) {
-						$disk->delete($path);
-					}
-				}
+		// Delete Avatar
+        $profile->avatar->forceDelete();
 
-				$avatar->forceDelete();
-			}
+        // Delete Poll Votes
+        PollVote::whereProfileId($id)->delete();
 
-			$id = $user->profile_id;
+        // Delete Polls
+        Poll::whereProfileId($id)->delete();
 
-			ImportData::whereProfileId($id)
-				->cursor()
-				->each(function($data) {
-					$path = storage_path('app/'.$data->path);
-					if(is_file($path)) {
-						unlink($path);
-					}
-					$data->delete();
-			});
-			ImportJob::whereProfileId($id)
-				->cursor()
-				->each(function($data) {
-					$path = storage_path('app/'.$data->media_json);
-					if(is_file($path)) {
-						unlink($path);
-					}
-					$data->delete();
-			});
-			MediaTag::whereProfileId($id)->delete();
-			Bookmark::whereProfileId($id)->forceDelete();
-			EmailVerification::whereUserId($user->id)->forceDelete();
-			StatusHashtag::whereProfileId($id)->delete();
-			DirectMessage::whereFromId($id)->orWhere('to_id', $id)->delete();
-			StatusArchived::whereProfileId($id)->delete();
-			UserPronoun::whereProfileId($id)->delete();
-			FollowRequest::whereFollowingId($id)
-				->orWhere('follower_id', $id)
-				->forceDelete();
-			Follower::whereProfileId($id)
-				->orWhere('following_id', $id)
-				->each(function($follow) {
-					FollowerService::remove($follow->profile_id, $follow->following_id);
-					$follow->delete();
-				});
-			FollowerService::delCache($id);
-			Like::whereProfileId($id)->forceDelete();
-		});
+        // Delete Portfolio
+        Portfolio::whereProfileId($id)->delete();
 
-		DB::transaction(function() use ($user) {
-			$pid = $this->user->profile_id;
-
-			StoryView::whereProfileId($pid)->delete();
-			$stories = Story::whereProfileId($pid)->get();
-			foreach($stories as $story) {
-				$path = storage_path('app/'.$story->path);
+		ImportData::whereProfileId($id)
+			->cursor()
+			->each(function($data) {
+				$path = storage_path('app/'.$data->path);
 				if(is_file($path)) {
 					unlink($path);
 				}
-				$story->forceDelete();
-			}
+				$data->delete();
 		});
 
-		DB::transaction(function() use ($user) {
-			$medias = Media::whereUserId($user->id)->get();
-			foreach($medias as $media) {
-				if(config('pixelfed.cloud_storage')) {
-					$disk = Storage::disk(config('filesystems.cloud'));
-					if($disk->exists($media->media_path)) {
-						$disk->delete($media->media_path);
-					}
-					if($disk->exists($media->thumbnail_path)) {
-						$disk->delete($media->thumbnail_path);
-					}
-				}
-				$disk = Storage::disk(config('filesystems.local'));
-				if($disk->exists($media->media_path)) {
-					$disk->delete($media->media_path);
-				}
-				if($disk->exists($media->thumbnail_path)) {
-					$disk->delete($media->thumbnail_path);
+		ImportJob::whereProfileId($id)
+			->cursor()
+			->each(function($data) {
+				$path = storage_path('app/'.$data->media_json);
+				if(is_file($path)) {
+					unlink($path);
 				}
-				$media->forceDelete();
-			}
+				$data->delete();
 		});
 
-		DB::transaction(function() use ($user) {
-			Mention::whereProfileId($user->profile_id)->forceDelete();
-			Notification::whereProfileId($user->profile_id)
-				->orWhere('actor_id', $user->profile_id)
-				->forceDelete();
-		});
-
-		DB::transaction(function() use ($user) {
-			$collections = Collection::whereProfileId($user->profile_id)->get();
-			foreach ($collections as $collection) {
-				$collection->items()->delete();
-				$collection->delete();
+		MediaTag::whereProfileId($id)->delete();
+		Bookmark::whereProfileId($id)->forceDelete();
+		EmailVerification::whereUserId($user->id)->forceDelete();
+		StatusHashtag::whereProfileId($id)->delete();
+		DirectMessage::whereFromId($id)->orWhere('to_id', $id)->delete();
+        Conversation::whereFromId($id)->orWhere('to_id', $id)->delete();
+		StatusArchived::whereProfileId($id)->delete();
+		UserPronoun::whereProfileId($id)->delete();
+		FollowRequest::whereFollowingId($id)
+			->orWhere('follower_id', $id)
+			->forceDelete();
+		Follower::whereProfileId($id)
+			->orWhere('following_id', $id)
+			->each(function($follow) {
+				FollowerService::remove($follow->profile_id, $follow->following_id);
+				$follow->delete();
+			});
+		FollowerService::delCache($id);
+		Like::whereProfileId($id)->forceDelete();
+        Mention::whereProfileId($id)->forceDelete();
+
+		StoryView::whereProfileId($id)->delete();
+		$stories = Story::whereProfileId($id)->get();
+		foreach($stories as $story) {
+			$path = storage_path('app/'.$story->path);
+			if(is_file($path)) {
+				unlink($path);
 			}
-			Contact::whereUserId($user->id)->delete();
-			HashtagFollow::whereUserId($user->id)->delete();
-			OauthClient::whereUserId($user->id)->delete();
-			DB::table('oauth_access_tokens')->whereUserId($user->id)->delete();
-			DB::table('oauth_auth_codes')->whereUserId($user->id)->delete();
-			ProfileSponsor::whereProfileId($user->profile_id)->delete();
-		});
-
-		DB::transaction(function() use ($user) {
-			Status::whereProfileId($user->profile_id)->forceDelete();
-			Report::whereUserId($user->id)->forceDelete();
-			PublicTimelineService::warmCache(true, 400);
-			$this->deleteProfile($user);
-		});
-	}
-
-	protected function deleteProfile($user) {
-		DB::transaction(function() use ($user) {
-			Profile::whereUserId($user->id)->delete();
-			$this->deleteUserSettings($user);
-		});
-	}
-
-	protected function deleteUserSettings($user) {
-
-		DB::transaction(function() use ($user) {
-			UserDevice::whereUserId($user->id)->forceDelete();
-			UserFilter::whereUserId($user->id)->forceDelete();
-			UserSetting::whereUserId($user->id)->forceDelete();
-		});
+			$story->forceDelete();
+		}
+
+        UserDevice::whereUserId($user->id)->forceDelete();
+        UserFilter::whereUserId($user->id)->forceDelete();
+        UserSetting::whereUserId($user->id)->forceDelete();
+
+		Mention::whereProfileId($id)->forceDelete();
+		Notification::whereProfileId($id)
+			->orWhere('actor_id', $id)
+			->forceDelete();
+
+		$collections = Collection::whereProfileId($id)->get();
+		foreach ($collections as $collection) {
+			$collection->items()->delete();
+			$collection->delete();
+		}
+		Contact::whereUserId($user->id)->delete();
+		HashtagFollow::whereUserId($user->id)->delete();
+		OauthClient::whereUserId($user->id)->delete();
+		DB::table('oauth_access_tokens')->whereUserId($user->id)->delete();
+		DB::table('oauth_auth_codes')->whereUserId($user->id)->delete();
+		ProfileSponsor::whereProfileId($id)->delete();
+
+		Status::whereProfileId($id)->chunk(50, function($statuses) {
+            foreach($statuses as $status) {
+                StatusDelete::dispatch($status)->onQueue('high');
+            }
+        });
+
+		Report::whereUserId($user->id)->forceDelete();
+		PublicTimelineService::warmCache(true, 400);
+		Profile::whereUserId($user->id)->delete();
 	}
 
 	protected function deleteUserColumns($user)

+ 77 - 62
app/Jobs/DeletePipeline/DeleteRemoteProfilePipeline.php

@@ -39,6 +39,7 @@ use App\{
 	ReportLog,
 	StatusHashtag,
 	Status,
+	StatusView,
 	Story,
 	StoryView,
 	User,
@@ -46,6 +47,10 @@ use App\{
 	UserFilter,
 	UserSetting,
 };
+use App\Models\Conversation;
+use App\Models\Poll;
+use App\Models\PollVote;
+use App\Services\AccountService;
 
 class DeleteRemoteProfilePipeline implements ShouldQueue
 {
@@ -53,6 +58,11 @@ class DeleteRemoteProfilePipeline implements ShouldQueue
 
 	protected $profile;
 
+	public $timeout = 900;
+	public $tries = 3;
+	public $maxExceptions = 1;
+	public $deleteWhenMissingModels = true;
+
 	public function __construct(Profile $profile)
 	{
 		$this->profile = $profile;
@@ -61,80 +71,85 @@ class DeleteRemoteProfilePipeline implements ShouldQueue
 	public function handle()
 	{
 		$profile = $this->profile;
+		$pid = $profile->id;
 
 		if($profile->domain == null || $profile->private_key) {
 			return;
 		}
 
-		DB::transaction(function() use ($profile) {
-			$profile->avatar->forceDelete();
-
-			$id = $profile->id;
-
-			MediaTag::whereProfileId($id)->delete();
-			StatusHashtag::whereProfileId($id)->delete();
-			DirectMessage::whereFromId($id)->delete();
-			FollowRequest::whereFollowingId($id)
-				->orWhere('follower_id', $id)
-				->forceDelete();
-			Follower::whereProfileId($id)
-				->orWhere('following_id', $id)
-				->forceDelete();
-			Like::whereProfileId($id)->forceDelete();
-		});
+		$profile->status = 'delete';
+		$profile->save();
+
+		AccountService::del($pid);
 
-		DB::transaction(function() use ($profile) {
-			$pid = $profile->id;
-			StoryView::whereProfileId($pid)->delete();
-			$stories = Story::whereProfileId($pid)->get();
-			foreach($stories as $story) {
-				$path = storage_path('app/'.$story->path);
-				if(is_file($path)) {
-					unlink($path);
+		// Delete statuses
+		Status::whereProfileId($pid)
+			->chunk(50, function($statuses) {
+				foreach($statuses as $status) {
+					DeleteRemoteStatusPipeline::dispatch($status)->onQueue('delete');
 				}
-				$story->forceDelete();
-			}
 		});
 
-		DB::transaction(function() use ($profile) {
-			$medias = Media::whereProfileId($profile->id)->get();
-			foreach($medias as $media) {
-				$path = storage_path('app/'.$media->media_path);
-				$thumb = storage_path('app/'.$media->thumbnail_path);
-				if(is_file($path)) {
-					unlink($path);
-				}
-				if(is_file($thumb)) {
-					unlink($thumb);
-				}
-				$media->forceDelete();
+		// Delete Poll Votes
+		PollVote::whereProfileId($pid)->delete();
+
+		// Delete Polls
+		Poll::whereProfileId($pid)->delete();
+
+		// Delete Avatar
+		$profile->avatar->forceDelete();
+
+		// Delete media tags
+		MediaTag::whereProfileId($pid)->delete();
+
+		// Delete DMs
+		DirectMessage::whereFromId($pid)->orWhere('to_id', $pid)->delete();
+		Conversation::whereFromId($pid)->orWhere('to_id', $pid)->delete();
+
+		// Delete FollowRequests
+		FollowRequest::whereFollowingId($pid)
+			->orWhere('follower_id', $pid)
+			->delete();
+
+		// Delete relationships
+		Follower::whereProfileId($pid)
+			->orWhere('following_id', $pid)
+			->delete();
+
+		// Delete likes
+		Like::whereProfileId($pid)->forceDelete();
+
+		// Delete Story Views + Stories
+		StoryView::whereProfileId($pid)->delete();
+		$stories = Story::whereProfileId($pid)->get();
+		foreach($stories as $story) {
+			$path = storage_path('app/'.$story->path);
+			if(is_file($path)) {
+				unlink($path);
 			}
-		});
+			$story->forceDelete();
+		}
 
-		DB::transaction(function() use ($profile) {
-			Mention::whereProfileId($profile->id)->forceDelete();
-			Notification::whereProfileId($profile->id)
-				->orWhere('actor_id', $profile->id)
-				->forceDelete();
-		});
+		// Delete mutes/blocks
+		UserFilter::whereFilterableType('App\Profile')->whereFilterableId($pid)->delete();
 
-		DB::transaction(function() use ($profile) {
-			Status::whereProfileId($profile->id)
-				->cursor()
-				->each(function($status) {
-					AccountInterstitial::where('item_type', 'App\Status')
-						->where('item_id', $status->id)
-						->delete();
-					$status->forceDelete();
-				});
-			Report::whereProfileId($profile->id)->forceDelete();
-			$this->deleteProfile($profile);
-		});
-	}
+		// Delete mentions
+		Mention::whereProfileId($pid)->forceDelete();
 
-	protected function deleteProfile($profile) {
-		DB::transaction(function() use ($profile) {
-			Profile::findOrFail($profile->id)->delete();
-		});
+		// Delete notifications
+		Notification::whereProfileId($pid)
+			->orWhere('actor_id', $pid)
+			->chunk(50, function($notifications) {
+				foreach($notifications as $n) {
+					$n->forceDelete();
+				}
+			});
+
+		// Delete reports
+		Report::whereProfileId($profile->id)->orWhere('reported_profile_id')->forceDelete();
+
+		// Delete profile
+		Profile::findOrFail($profile->id)->delete();
+		return;
 	}
 }

+ 13 - 6
app/Jobs/DeletePipeline/DeleteRemoteStatusPipeline.php

@@ -19,10 +19,12 @@ use App\Status;
 use App\StatusHashtag;
 use App\StatusView;
 use App\Notification;
+use App\Services\AccountService;
 use App\Services\NetworkTimelineService;
 use App\Services\StatusService;
 use App\Jobs\ProfilePipeline\DecrementPostCount;
 use App\Jobs\MediaPipeline\MediaDeletePipeline;
+use Cache;
 
 class DeleteRemoteStatusPipeline implements ShouldQueue
 {
@@ -30,9 +32,10 @@ class DeleteRemoteStatusPipeline implements ShouldQueue
 
     protected $status;
 
-    public $timeout = 300;
-    public $tries = 3;
+    public $timeout = 30;
+    public $tries = 2;
     public $maxExceptions = 1;
+    public $deleteWhenMissingModels = true;
 
     /**
      * Create a new job instance.
@@ -41,7 +44,7 @@ class DeleteRemoteStatusPipeline implements ShouldQueue
      */
     public function __construct(Status $status)
     {
-        $this->status = $status->withoutRelations();
+        $this->status = $status;
     }
 
     /**
@@ -53,9 +56,12 @@ class DeleteRemoteStatusPipeline implements ShouldQueue
     {
         $status = $this->status;
 
+        if(AccountService::get($status->profile_id, true)) {
+            DecrementPostCount::dispatch($status->profile_id)->onQueue('feed');
+        }
+
         NetworkTimelineService::del($status->id);
-        StatusService::del($status->id, true);
-        DecrementPostCount::dispatchNow($status->profile_id);
+        Cache::forget(StatusService::key($status->id));
         Bookmark::whereStatusId($status->id)->delete();
         Notification::whereItemType('App\Status')
             ->whereItemId($status->id)
@@ -73,6 +79,7 @@ class DeleteRemoteStatusPipeline implements ShouldQueue
         StatusHashtag::whereStatusId($status->id)->delete();
         StatusView::whereStatusId($status->id)->delete();
         Status::whereReblogOfId($status->id)->forceDelete();
-        $status->delete();
+        $status->forceDelete();
+        return 1;
     }
 }

+ 1 - 1
app/Jobs/StatusPipeline/StatusDelete.php

@@ -89,7 +89,7 @@ class StatusDelete implements ShouldQueue
         Media::whereStatusId($status->id)
         ->get()
         ->each(function($media) {
-            MediaDeletePipeline::dispatchNow($media);
+            MediaDeletePipeline::dispatch($media)->onQueue('mmo');
         });
 
 		if($status->in_reply_to_id) {

+ 1 - 1
app/Observers/AvatarObserver.php

@@ -65,7 +65,7 @@ class AvatarObserver
             @unlink($path);
         }
 
-        if($avatar->cdn_url && config_cache('pixelfed.cloud_storage')) {
+        if(config_cache('pixelfed.cloud_storage')) {
             $disk = Storage::disk(config('filesystems.cloud'));
             $base = Str::startsWith($avatar->media_path, 'cache/avatars/');
             if($base && $disk->exists($avatar->media_path)) {

+ 1 - 1
app/Services/MediaStorageService.php

@@ -274,6 +274,6 @@ class MediaStorageService {
 		if(!$confirm) {
 			return;
 		}
-		MediaDeletePipeline::dispatch($media);
+		MediaDeletePipeline::dispatch($media)->onQueue('mmo');
 	}
 }