merge: ST11 Webhooks worker switch to Notification

This commit is contained in:
Jake Barnby
2026-05-06 14:48:29 +12:00
+60 -20
View File
@@ -2,8 +2,8 @@
namespace Appwrite\Platform\Workers;
use Appwrite\Event\Mail;
use Appwrite\Event\Message\Usage as UsageMessage;
use Appwrite\Event\Notification;
use Appwrite\Event\Publisher\Usage as UsagePublisher;
use Appwrite\Template\Template;
use Appwrite\Usage\Context as UsageContext;
@@ -36,7 +36,7 @@ class Webhooks extends Action
->inject('message')
->inject('project')
->inject('dbForPlatform')
->inject('queueForMails')
->inject('queueForNotifications')
->inject('publisherForUsage')
->inject('log')
->inject('plan')
@@ -47,14 +47,14 @@ class Webhooks extends Action
* @param Message $message
* @param Document $project
* @param Database $dbForPlatform
* @param Mail $queueForMails
* @param Notification $queueForNotifications
* @param UsagePublisher $publisherForUsage
* @param Log $log
* @param array $plan
* @return void
* @throws Exception
*/
public function action(Message $message, Document $project, Database $dbForPlatform, Mail $queueForMails, UsagePublisher $publisherForUsage, Log $log, array $plan): void
public function action(Message $message, Document $project, Database $dbForPlatform, Notification $queueForNotifications, UsagePublisher $publisherForUsage, Log $log, array $plan): void
{
$this->errors = [];
$payload = $message->getPayload();
@@ -73,7 +73,7 @@ class Webhooks extends Action
foreach ($project->getAttribute('webhooks', []) as $webhook) {
if (array_intersect($webhook->getAttribute('events', []), $events)) {
$this->execute($events, $webhookPayload, $webhook, $user, $project, $dbForPlatform, $queueForMails, $publisherForUsage, $plan);
$this->execute($events, $webhookPayload, $webhook, $user, $project, $dbForPlatform, $queueForNotifications, $publisherForUsage, $plan);
}
}
@@ -89,11 +89,11 @@ class Webhooks extends Action
* @param Document $user
* @param Document $project
* @param Database $dbForPlatform
* @param Mail $queueForMails
* @param Notification $queueForNotifications
* @param array $plan
* @return void
*/
private function execute(array $events, string $payload, Document $webhook, Document $user, Document $project, Database $dbForPlatform, Mail $queueForMails, UsagePublisher $publisherForUsage, array $plan): void
private function execute(array $events, string $payload, Document $webhook, Document $user, Document $project, Database $dbForPlatform, Notification $queueForNotifications, UsagePublisher $publisherForUsage, array $plan): void
{
if ($webhook->getAttribute('enabled') !== true) {
return;
@@ -171,7 +171,7 @@ class Webhooks extends Action
if ($attempts >= \intval(System::getEnv('_APP_WEBHOOK_MAX_FAILED_ATTEMPTS', '10'))) {
$webhook->setAttribute('enabled', false);
$updatePayload['enabled'] = false;
$this->sendEmailAlert($attempts, $statusCode, $webhook, $project, $dbForPlatform, $queueForMails, $plan);
$this->sendAlert($attempts, $statusCode, $webhook, $project, $dbForPlatform, $queueForNotifications, $plan);
}
$dbForPlatform->updateDocument('webhooks', $webhook->getId(), new Document($updatePayload));
@@ -203,26 +203,49 @@ class Webhooks extends Action
* @param Document $webhook
* @param Document $project
* @param Database $dbForPlatform
* @param Mail $queueForMails
* @param Notification $queueForNotifications
* @param array $plan
* @return void
*/
public function sendEmailAlert(int $attempts, mixed $statusCode, Document $webhook, Document $project, Database $dbForPlatform, Mail $queueForMails, array $plan): void
public function sendAlert(int $attempts, mixed $statusCode, Document $webhook, Document $project, Database $dbForPlatform, Notification $queueForNotifications, array $plan): void
{
$memberships = $dbForPlatform->find('memberships', [
Query::equal('teamInternalId', [$project->getAttribute('teamInternalId')]),
Query::limit(APP_LIMIT_SUBQUERY)
]);
$userIds = array_column(\array_map(fn ($membership) => $membership->getArrayCopy(), $memberships), 'userId');
// Webhook-paused alerts go only to project owners — non-owner team members do not receive them.
$ownerMemberships = \array_filter(
$memberships,
fn (Document $membership) => \in_array('owner', $membership->getAttribute('roles', []), true)
);
if (empty($ownerMemberships)) {
return;
}
$userIds = \array_values(\array_unique(\array_filter(\array_map(
fn (Document $membership) => $membership->getAttribute('userId'),
$ownerMemberships
))));
if (empty($userIds)) {
return;
}
$users = $dbForPlatform->find('users', [
Query::equal('$id', $userIds),
Query::limit(APP_LIMIT_SUBQUERY),
]);
if (empty($users)) {
return;
}
$projectId = $project->getId();
$region = $project->getAttribute('region', 'default');
$webhookId = $webhook->getId();
$teamId = $project->getAttribute('teamId');
$template = Template::fromFile(__DIR__ . '/../../../../app/config/locale/templates/email-webhook-failed.tpl');
@@ -241,7 +264,6 @@ class Webhooks extends Action
$template->setParam('{{termsUrl}}', $plan['termsUrl'] ?? APP_EMAIL_TERMS_URL);
$template->setParam('{{privacyUrl}}', $plan['privacyUrl'] ?? APP_EMAIL_PRIVACY_URL);
// TODO: Use setbodyTemplate once #7307 is merged
$subject = 'Webhook deliveries have been paused';
$preview = 'Webhook deliveries to your endpoint have been paused.';
$body = Template::fromFile(__DIR__ . '/../../../../app/config/locale/templates/email-base-styled.tpl');
@@ -249,20 +271,38 @@ class Webhooks extends Action
$body
->setParam('{{subject}}', $subject)
->setParam('{{message}}', $template->render())
->setParam('{{year}}', date("Y"));
->setParam('{{year}}', date('Y'));
$queueForMails
$queueForNotifications
->setProject($project)
->setSubject($subject)
->setPreview($preview)
->setBody($body->render());
->setBody($body->render())
->setDeduplicationKey('webhook:' . $webhook->getId() . ':paused:' . $attempts);
foreach ($users as $user) {
$queueForMails
->setVariables(['user' => $user->getAttribute('name', '')])
->setName($user->getAttribute('name', ''))
->setRecipient($user->getAttribute('email'))
->trigger();
$email = $user->getAttribute('email');
$userId = $user->getId();
if (!empty($email)) {
$queueForNotifications->addRecipient(
$email,
NOTIFICATION_TYPE_EMAIL,
null,
$userId,
$teamId,
);
}
$queueForNotifications->addRecipient(
$userId,
NOTIFICATION_TYPE_CONSOLE,
null,
$userId,
$teamId,
);
}
$queueForNotifications->trigger();
}
}