From 6bdf73de4d5a5d11004018621c4b7854ed5db7a7 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Sat, 6 Apr 2024 03:29:17 -0600 Subject: [PATCH 1/4] Update UnfollowPipeline, fix follower count cache bug --- app/Jobs/FollowPipeline/UnfollowPipeline.php | 175 ++++++++++--------- 1 file changed, 88 insertions(+), 87 deletions(-) diff --git a/app/Jobs/FollowPipeline/UnfollowPipeline.php b/app/Jobs/FollowPipeline/UnfollowPipeline.php index 99f763f5c..9417e535e 100644 --- a/app/Jobs/FollowPipeline/UnfollowPipeline.php +++ b/app/Jobs/FollowPipeline/UnfollowPipeline.php @@ -4,114 +4,115 @@ namespace App\Jobs\FollowPipeline; use App\Follower; use App\FollowRequest; +use App\Jobs\HomeFeedPipeline\FeedUnfollowPipeline; use App\Notification; use App\Profile; +use App\Services\AccountService; +use App\Services\FollowerService; +use App\Services\NotificationService; use Cache; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; -use Log; -use Illuminate\Support\Facades\Redis; -use App\Services\AccountService; -use App\Services\FollowerService; -use App\Services\NotificationService; -use App\Jobs\HomeFeedPipeline\FeedUnfollowPipeline; class UnfollowPipeline implements ShouldQueue { - use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; + use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; - protected $actor; - protected $target; + protected $actor; - /** - * Create a new job instance. - * - * @return void - */ - public function __construct($actor, $target) - { - $this->actor = $actor; - $this->target = $target; - } + protected $target; - /** - * Execute the job. - * - * @return void - */ - public function handle() - { - $actor = $this->actor; - $target = $this->target; + /** + * Create a new job instance. + * + * @return void + */ + public function __construct($actor, $target) + { + $this->actor = $actor; + $this->target = $target; + } - $actorProfile = Profile::find($actor); - if(!$actorProfile) { - return; - } - $targetProfile = Profile::find($target); - if(!$targetProfile) { - return; - } + /** + * Execute the job. + * + * @return void + */ + public function handle() + { + $actor = $this->actor; + $target = $this->target; - FeedUnfollowPipeline::dispatch($actor, $target)->onQueue('follow'); + $actorProfile = Profile::find($actor); + if (! $actorProfile) { + return; + } + $targetProfile = Profile::find($target); + if (! $targetProfile) { + return; + } - FollowerService::remove($actor, $target); + FeedUnfollowPipeline::dispatch($actor, $target)->onQueue('follow'); - $actorProfileSync = Cache::get(FollowerService::FOLLOWING_SYNC_KEY . $actor); - if(!$actorProfileSync) { - FollowServiceWarmCache::dispatch($actor)->onQueue('low'); - } else { - if($actorProfile->following_count) { - $actorProfile->decrement('following_count'); - } else { - $count = Follower::whereProfileId($actor)->count(); - $actorProfile->following_count = $count; - $actorProfile->save(); - } - Cache::put(FollowerService::FOLLOWING_SYNC_KEY . $actor, 1, 604800); - AccountService::del($actor); - } + FollowerService::remove($actor, $target); - $targetProfileSync = Cache::get(FollowerService::FOLLOWERS_SYNC_KEY . $target); - if(!$targetProfileSync) { - FollowServiceWarmCache::dispatch($target)->onQueue('low'); - } else { - if($targetProfile->followers_count) { - $targetProfile->decrement('followers_count'); - } else { - $count = Follower::whereFollowingId($target)->count(); - $targetProfile->followers_count = $count; - $targetProfile->save(); - } - Cache::put(FollowerService::FOLLOWERS_SYNC_KEY . $target, 1, 604800); - AccountService::del($target); - } + $actorProfileSync = Cache::get(FollowerService::FOLLOWING_SYNC_KEY.$actor); + if (! $actorProfileSync) { + FollowServiceWarmCache::dispatch($actor)->onQueue('low'); + } else { + if ($actorProfile->following_count) { + $actorProfile->decrement('following_count'); + } else { + $count = Follower::whereProfileId($actor)->count(); + $actorProfile->following_count = $count; + $actorProfile->save(); + } + Cache::put(FollowerService::FOLLOWING_SYNC_KEY.$actor, 1, 604800); + AccountService::del($actor); + } - if($targetProfile->domain == null) { - Notification::withTrashed() - ->whereProfileId($target) - ->whereAction('follow') - ->whereActorId($actor) - ->whereItemId($target) - ->whereItemType('App\Profile') - ->get() - ->each(function($n) { - NotificationService::del($n->profile_id, $n->id); - $n->forceDelete(); - }); - } + $targetProfileSync = Cache::get(FollowerService::FOLLOWERS_SYNC_KEY.$target); + if (! $targetProfileSync) { + FollowServiceWarmCache::dispatch($target)->onQueue('low'); + } else { + if ($targetProfile->followers_count) { + $targetProfile->decrement('followers_count'); + } else { + $count = Follower::whereFollowingId($target)->count(); + $targetProfile->followers_count = $count; + $targetProfile->save(); + } + Cache::put(FollowerService::FOLLOWERS_SYNC_KEY.$target, 1, 604800); + AccountService::del($target); + } - if($actorProfile->domain == null && config('instance.timeline.home.cached')) { - Cache::forget('pf:timelines:home:' . $actor); - } + if ($targetProfile->domain == null) { + Notification::withTrashed() + ->whereProfileId($target) + ->whereAction('follow') + ->whereActorId($actor) + ->whereItemId($target) + ->whereItemType('App\Profile') + ->get() + ->each(function ($n) { + NotificationService::del($n->profile_id, $n->id); + $n->forceDelete(); + }); + } - FollowRequest::whereFollowingId($target) - ->whereFollowerId($actor) - ->delete(); + if ($actorProfile->domain == null && config('instance.timeline.home.cached')) { + Cache::forget('pf:timelines:home:'.$actor); + } - return; - } + FollowRequest::whereFollowingId($target) + ->whereFollowerId($actor) + ->delete(); + + AccountService::del($target); + AccountService::del($actor); + + } } From dbc5df849f5a47dde952a5bea40a1467e4abfb59 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Sat, 6 Apr 2024 10:06:07 +0000 Subject: [PATCH 2/4] use ENABLE_CONFIG_CACHE when dumping composer autoload --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index a6ad884b8..a3317c11d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -237,7 +237,7 @@ USER ${RUNTIME_UID}:${RUNTIME_GID} # Generate optimized autoloader now that we have all files around RUN set -ex \ - && composer dump-autoload --optimize + && ENABLE_CONFIG_CACHE=false composer dump-autoload --optimize USER root From e227ee1bd5eca59363bf0e17ae2eb7917789a928 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Sat, 6 Apr 2024 10:53:48 +0000 Subject: [PATCH 3/4] use DOCKER_DB_HOST_PORT when checking if database is ready or not --- docker/shared/root/docker/helpers.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker/shared/root/docker/helpers.sh b/docker/shared/root/docker/helpers.sh index 3a21ee89e..8ca2880fd 100644 --- a/docker/shared/root/docker/helpers.sh +++ b/docker/shared/root/docker/helpers.sh @@ -467,14 +467,14 @@ function await-database-ready() case "${DB_CONNECTION:-}" in mysql) # shellcheck disable=SC2154 - while ! echo "SELECT 1" | mysql --user="${DB_USERNAME}" --password="${DB_PASSWORD}" --host="${DB_HOST}" "${DB_DATABASE}" --silent >/dev/null; do + while ! echo "SELECT 1" | mysql --user="${DB_USERNAME}" --password="${DB_PASSWORD}" --host="${DB_HOST}" --port="${DOCKER_DB_HOST_PORT}" "${DB_DATABASE}" --silent >/dev/null; do staggered-sleep done ;; pgsql) # shellcheck disable=SC2154 - while ! echo "SELECT 1" | PGPASSWORD="${DB_PASSWORD}" psql --user="${DB_USERNAME}" --host="${DB_HOST}" "${DB_DATABASE}" >/dev/null; do + while ! echo "SELECT 1" | PGPASSWORD="${DB_PASSWORD}" psql --user="${DB_USERNAME}" --host="${DB_HOST}" --port="${DOCKER_DB_HOST_PORT}" "${DB_DATABASE}" >/dev/null; do staggered-sleep done ;; From 4608c66c0bbd89809d50c290138279bcefb1a0db Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Thu, 11 Apr 2024 20:43:24 -0600 Subject: [PATCH 4/4] Re-add .env.example --- .env.example | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 .env.example diff --git a/.env.example b/.env.example new file mode 100644 index 000000000..d4d7228d1 --- /dev/null +++ b/.env.example @@ -0,0 +1,78 @@ +APP_NAME="Pixelfed" +APP_ENV="production" +APP_KEY= +APP_DEBUG="false" + +# Instance Configuration +OPEN_REGISTRATION="false" +ENFORCE_EMAIL_VERIFICATION="false" +PF_MAX_USERS="1000" +OAUTH_ENABLED="true" + +# Media Configuration +PF_OPTIMIZE_IMAGES="true" +IMAGE_QUALITY="80" +MAX_PHOTO_SIZE="15000" +MAX_CAPTION_LENGTH="500" +MAX_ALBUM_LENGTH="4" + +# Instance URL Configuration +APP_URL="http://localhost" +APP_DOMAIN="localhost" +ADMIN_DOMAIN="localhost" +SESSION_DOMAIN="localhost" +TRUST_PROXIES="*" + +# Database Configuration +DB_CONNECTION="mysql" +DB_HOST="127.0.0.1" +DB_PORT="3306" +DB_DATABASE="pixelfed" +DB_USERNAME="pixelfed" +DB_PASSWORD="pixelfed" + +# Redis Configuration +REDIS_CLIENT="predis" +REDIS_SCHEME="tcp" +REDIS_HOST="127.0.0.1" +REDIS_PASSWORD="null" +REDIS_PORT="6379" + +# Laravel Configuration +SESSION_DRIVER="database" +CACHE_DRIVER="redis" +QUEUE_DRIVER="redis" +BROADCAST_DRIVER="log" +LOG_CHANNEL="stack" +HORIZON_PREFIX="horizon-" + +# ActivityPub Configuration +ACTIVITY_PUB="false" +AP_REMOTE_FOLLOW="false" +AP_INBOX="false" +AP_OUTBOX="false" +AP_SHAREDINBOX="false" + +# Experimental Configuration +EXP_EMC="true" + +## Mail Configuration (Post-Installer) +MAIL_DRIVER=log +MAIL_HOST=smtp.mailtrap.io +MAIL_PORT=2525 +MAIL_USERNAME=null +MAIL_PASSWORD=null +MAIL_ENCRYPTION=null +MAIL_FROM_ADDRESS="pixelfed@example.com" +MAIL_FROM_NAME="Pixelfed" + +## S3 Configuration (Post-Installer) +PF_ENABLE_CLOUD=false +FILESYSTEM_CLOUD=s3 +#AWS_ACCESS_KEY_ID= +#AWS_SECRET_ACCESS_KEY= +#AWS_DEFAULT_REGION= +#AWS_BUCKET= +#AWS_URL= +#AWS_ENDPOINT= +#AWS_USE_PATH_STYLE_ENDPOINT=false