mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2026-07-30 02:17:46 +08:00
60 lines
1.5 KiB
PHP
60 lines
1.5 KiB
PHP
<?php
|
|
declare( strict_types = 1 );
|
|
|
|
namespace WooCommerce\PayPalCommerce\Webhooks;
|
|
|
|
use Psr\Log\LoggerInterface;
|
|
|
|
/**
|
|
* Orchestrates webhook operations with lock protection to prevent race conditions.
|
|
*/
|
|
class WebhookOrchestrator {
|
|
|
|
private const LOCK_KEY = 'ppcp_webhook_operation_lock';
|
|
private const LOCK_DURATION = 60;
|
|
|
|
private LoggerInterface $logger;
|
|
|
|
public function __construct( LoggerInterface $logger ) {
|
|
$this->logger = $logger;
|
|
}
|
|
|
|
/**
|
|
* Execute a webhook operation with lock protection.
|
|
*
|
|
* @param string $action Which operation is started (for logging).
|
|
* @param callable $operation The operation to execute.
|
|
* @return mixed The result of the operation, or null if locked.
|
|
*/
|
|
public function with_lock( string $action, callable $operation ) {
|
|
if ( $this->is_locked() ) {
|
|
$this->logger->info( "Webhook operation '$action' skipped - lock held by another process." );
|
|
|
|
return null;
|
|
}
|
|
|
|
$this->acquire_lock( $action );
|
|
|
|
try {
|
|
$this->logger->debug( "Webhook operation '$action' started." );
|
|
|
|
return $operation();
|
|
} finally {
|
|
$this->release_lock( $action );
|
|
}
|
|
}
|
|
|
|
private function is_locked(): bool {
|
|
return false !== get_transient( self::LOCK_KEY );
|
|
}
|
|
|
|
private function acquire_lock( string $action ): void {
|
|
set_transient( self::LOCK_KEY, true, self::LOCK_DURATION );
|
|
$this->logger->debug( "Webhook lock acquired for '$action'." );
|
|
}
|
|
|
|
private function release_lock( string $action ): void {
|
|
delete_transient( self::LOCK_KEY );
|
|
$this->logger->debug( "Webhook lock released for '$action'." );
|
|
}
|
|
}
|