mirror of
https://github.com/pixelfed/pixelfed.git
synced 2025-01-18 02:20:46 +00:00
Fix notifications not being delivered by directly checking the state from the database
This commit is contained in:
parent
4ce6e610bd
commit
4d0cb32f79
3 changed files with 4 additions and 130 deletions
|
@ -51,8 +51,6 @@ class PushGatewayRefresh extends Command
|
||||||
$recheck = NotificationAppGatewayService::forceSupportRecheck();
|
$recheck = NotificationAppGatewayService::forceSupportRecheck();
|
||||||
if ($recheck) {
|
if ($recheck) {
|
||||||
$this->info('Success! Push Notifications are now active!');
|
$this->info('Success! Push Notifications are now active!');
|
||||||
PushNotificationService::warmList('like');
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
$this->error('Error, please ensure you have a valid API key.');
|
$this->error('Error, please ensure you have a valid API key.');
|
||||||
|
|
|
@ -1058,8 +1058,6 @@ class ApiV1Dot1Controller extends Controller
|
||||||
'notify_comment' => false,
|
'notify_comment' => false,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
PushNotificationService::removeMemberFromAll($request->user()->profile_id);
|
|
||||||
|
|
||||||
$user = $request->user();
|
$user = $request->user();
|
||||||
|
|
||||||
return $this->json([
|
return $this->json([
|
||||||
|
@ -1145,31 +1143,15 @@ class ApiV1Dot1Controller extends Controller
|
||||||
|
|
||||||
if ($request->filled('notify_like')) {
|
if ($request->filled('notify_like')) {
|
||||||
$request->user()->update(['notify_like' => (bool) $request->boolean('notify_like')]);
|
$request->user()->update(['notify_like' => (bool) $request->boolean('notify_like')]);
|
||||||
$request->boolean('notify_like') == true ?
|
|
||||||
PushNotificationService::set('like', $pid) :
|
|
||||||
PushNotificationService::removeMember('like', $pid);
|
|
||||||
}
|
}
|
||||||
if ($request->filled('notify_follow')) {
|
if ($request->filled('notify_follow')) {
|
||||||
$request->user()->update(['notify_follow' => (bool) $request->boolean('notify_follow')]);
|
$request->user()->update(['notify_follow' => (bool) $request->boolean('notify_follow')]);
|
||||||
$request->boolean('notify_follow') == true ?
|
|
||||||
PushNotificationService::set('follow', $pid) :
|
|
||||||
PushNotificationService::removeMember('follow', $pid);
|
|
||||||
}
|
}
|
||||||
if ($request->filled('notify_mention')) {
|
if ($request->filled('notify_mention')) {
|
||||||
$request->user()->update(['notify_mention' => (bool) $request->boolean('notify_mention')]);
|
$request->user()->update(['notify_mention' => (bool) $request->boolean('notify_mention')]);
|
||||||
$request->boolean('notify_mention') == true ?
|
|
||||||
PushNotificationService::set('mention', $pid) :
|
|
||||||
PushNotificationService::removeMember('mention', $pid);
|
|
||||||
}
|
}
|
||||||
if ($request->filled('notify_comment')) {
|
if ($request->filled('notify_comment')) {
|
||||||
$request->user()->update(['notify_comment' => (bool) $request->boolean('notify_comment')]);
|
$request->user()->update(['notify_comment' => (bool) $request->boolean('notify_comment')]);
|
||||||
$request->boolean('notify_comment') == true ?
|
|
||||||
PushNotificationService::set('comment', $pid) :
|
|
||||||
PushNotificationService::removeMember('comment', $pid);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($request->boolean('notify_enabled') == false) {
|
|
||||||
PushNotificationService::removeMemberFromAll($request->user()->profile_id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$user = $request->user();
|
$user = $request->user();
|
||||||
|
|
|
@ -3,121 +3,15 @@
|
||||||
namespace App\Services;
|
namespace App\Services;
|
||||||
|
|
||||||
use App\User;
|
use App\User;
|
||||||
use Exception;
|
|
||||||
use Illuminate\Support\Facades\Cache;
|
|
||||||
use Illuminate\Support\Facades\Redis;
|
|
||||||
use Log;
|
|
||||||
|
|
||||||
class PushNotificationService
|
class PushNotificationService {
|
||||||
{
|
|
||||||
public const ACTIVE_LIST_KEY = 'pf:services:push-notify:active_deliver:';
|
|
||||||
|
|
||||||
public const NOTIFY_TYPES = ['follow', 'like', 'mention', 'comment'];
|
public const NOTIFY_TYPES = ['follow', 'like', 'mention', 'comment'];
|
||||||
|
|
||||||
public const DEEP_CHECK_KEY = 'pf:services:push-notify:deep-check:';
|
|
||||||
|
|
||||||
public const PUSH_GATEWAY_VERSION = '1.0';
|
public const PUSH_GATEWAY_VERSION = '1.0';
|
||||||
|
|
||||||
public const LOTTERY_ODDS = 20;
|
public static function check($listId, $memberId) {
|
||||||
|
|
||||||
public const CACHE_LOCK_SECONDS = 10;
|
|
||||||
|
|
||||||
public static function get($list)
|
|
||||||
{
|
|
||||||
return Redis::smembers(self::ACTIVE_LIST_KEY.$list);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function set($listId, $memberId)
|
|
||||||
{
|
|
||||||
if (! in_array($listId, self::NOTIFY_TYPES)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$user = User::whereProfileId($memberId)->first();
|
|
||||||
if (! $user || $user->status || $user->deleted_at) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Redis::sadd(self::ACTIVE_LIST_KEY.$listId, $memberId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function check($listId, $memberId)
|
|
||||||
{
|
|
||||||
return random_int(1, self::LOTTERY_ODDS) === 1
|
|
||||||
? self::isMemberDeepCheck($listId, $memberId)
|
|
||||||
: self::isMember($listId, $memberId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function isMember($listId, $memberId)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
return Redis::sismember(self::ACTIVE_LIST_KEY.$listId, $memberId);
|
|
||||||
} catch (Exception $e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function isMemberDeepCheck($listId, $memberId)
|
|
||||||
{
|
|
||||||
$lock = Cache::lock(self::DEEP_CHECK_KEY.$listId, self::CACHE_LOCK_SECONDS);
|
|
||||||
|
|
||||||
try {
|
|
||||||
$lock->block(5);
|
|
||||||
$actualCount = User::whereNull('status')->where('notify_enabled', true)->where('notify_'.$listId, true)->count();
|
|
||||||
$cachedCount = self::count($listId);
|
|
||||||
if ($actualCount != $cachedCount) {
|
|
||||||
self::warmList($listId);
|
|
||||||
$user = User::where('notify_enabled', true)->where('profile_id', $memberId)->first();
|
$user = User::where('notify_enabled', true)->where('profile_id', $memberId)->first();
|
||||||
|
|
||||||
return $user ? (bool) $user->{"notify_{$listId}"} : false;
|
return $user ? (bool) $user->{"notify_{$listId}"} : false;
|
||||||
} else {
|
|
||||||
return self::isMember($listId, $memberId);
|
|
||||||
}
|
|
||||||
} catch (Exception $e) {
|
|
||||||
Log::error('Failed during deep membership check: '.$e->getMessage());
|
|
||||||
|
|
||||||
return false;
|
|
||||||
} finally {
|
|
||||||
optional($lock)->release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function removeMember($listId, $memberId)
|
|
||||||
{
|
|
||||||
return Redis::srem(self::ACTIVE_LIST_KEY.$listId, $memberId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function removeMemberFromAll($memberId)
|
|
||||||
{
|
|
||||||
foreach (self::NOTIFY_TYPES as $type) {
|
|
||||||
self::removeMember($type, $memberId);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function count($listId)
|
|
||||||
{
|
|
||||||
if (! in_array($listId, self::NOTIFY_TYPES)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Redis::scard(self::ACTIVE_LIST_KEY.$listId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function warmList($listId)
|
|
||||||
{
|
|
||||||
if (! in_array($listId, self::NOTIFY_TYPES)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$key = self::ACTIVE_LIST_KEY.$listId;
|
|
||||||
Redis::del($key);
|
|
||||||
foreach (User::where('notify_'.$listId, true)->cursor() as $acct) {
|
|
||||||
if ($acct->status || $acct->deleted_at || ! $acct->profile_id || ! $acct->notify_enabled) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Redis::sadd($key, $acct->profile_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
return self::count($listId);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue