Merge "Push: Submit requests to configured service endpoint"

This commit is contained in:
jenkins-bot 2020-06-09 17:08:31 +00:00 committed by Gerrit Code Review
commit 2a38f60ab8
5 changed files with 71 additions and 14 deletions

View file

@ -12,7 +12,7 @@ return [
NotificationServiceClient {
$echoConfig = $services->getConfigFactory()->makeConfig( 'Echo' );
$httpRequestFactory = $services->getHttpRequestFactory();
$url = $echoConfig->get( 'EchoPushServiceUrl' );
$url = $echoConfig->get( 'EchoPushServiceBaseUrl' );
$client = new NotificationServiceClient( $httpRequestFactory, $url );
$client->setLogger( LoggerFactory::getInstance( 'Echo' ) );
return $client;

View file

@ -990,7 +990,7 @@
"value": false,
"description": "Whether to enable push notifications"
},
"EchoPushServiceUrl": {
"EchoPushServiceBaseUrl": {
"value": false,
"description": "Request endpoint URL for the push notification service"
}

View file

@ -16,7 +16,7 @@ class NotificationRequestJob extends Job {
$subscriptionManager = $echoServices->getPushSubscriptionManager();
$subscriptions = $subscriptionManager->getSubscriptionsForUser( $centralId );
$serviceClient = $echoServices->getPushNotificationServiceClient();
$serviceClient->sendCheckEchoRequest( $subscriptions );
$serviceClient->sendCheckEchoRequests( $subscriptions );
return true;
}

View file

@ -3,8 +3,10 @@
namespace EchoPush;
use MediaWiki\Http\HttpRequestFactory;
use MWHttpRequest;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerAwareTrait;
use Status;
class NotificationServiceClient implements LoggerAwareInterface {
@ -14,32 +16,71 @@ class NotificationServiceClient implements LoggerAwareInterface {
private $httpRequestFactory;
/** @var string */
private $url;
private $endpointBase;
/**
* @param HttpRequestFactory $httpRequestFactory
* @param string $url push service notification request endpoint URL
* @param string $endpointBase push service notification request endpoint base URL
*/
public function __construct( HttpRequestFactory $httpRequestFactory, string $url ) {
public function __construct( HttpRequestFactory $httpRequestFactory, string $endpointBase ) {
$this->httpRequestFactory = $httpRequestFactory;
$this->url = $url;
$this->endpointBase = $endpointBase;
}
/**
* Send a CHECK_ECHO notification request to the push service.
* Send a CHECK_ECHO notification request to the push service for each subscription found.
* TODO: Update the service to handle multiple providers in a single request (T254379)
* @param array $subscriptions Subscriptions for which to send the message
*/
public function sendCheckEchoRequest( array $subscriptions ): void {
$this->sendRequest( $subscriptions, [ 'message' => 'CHECK_ECHO' ] );
public function sendCheckEchoRequests( array $subscriptions ): void {
$tokensByProvider = [];
foreach ( $subscriptions as $subscription ) {
$provider = $subscription->getProvider();
if ( !isset( $tokensByProvider[$provider] ) ) {
$tokensByProvider[$provider] = [];
}
$tokensByProvider[$provider][] = $subscription->getToken();
}
foreach ( array_keys( $tokensByProvider ) as $provider ) {
$tokens = $tokensByProvider[$provider];
$payload = [ 'deviceTokens' => $tokens, 'messageType' => 'checkEchoV1' ];
$this->sendRequest( $provider, $payload );
}
}
/**
* @param array $subscriptions Subscriptions for which to send the message
* Send a notification request for a single push provider
* @param string $provider Provider endpoint to which to send the message
* @param array $payload message payload
*/
private function sendRequest( array $subscriptions, array $payload ): void {
// TODO: Implement this when the push notification service's request API exists
$this->logger->debug( 'Sending push notification request' );
private function sendRequest( string $provider, array $payload ): void {
$request = $this->constructRequest( $provider, $payload );
$status = $request->execute();
if ( !$status->isOK() ) {
$errors = $status->getErrorsByType( 'error' );
$this->logger->warning(
Status::wrap( $status )->getMessage( false, false, 'en' )->serialize(),
[
'error' => $errors,
'caller' => __METHOD__,
'content' => $request->getContent()
]
);
}
}
/**
* Construct a MWHttpRequest object based on the subscription and payload.
* @param string $provider
* @param array $payload
* @return MWHttpRequest
*/
private function constructRequest( string $provider, array $payload ): MWHttpRequest {
$url = "$this->endpointBase/$provider";
$opts = [ 'method' => 'POST', 'postData' => json_encode( $payload ) ];
$req = $this->httpRequestFactory->create( $url, $opts );
$req->setHeader( 'Content-Type', 'application/json; charset=utf-8' );
return $req;
}
}

View file

@ -0,0 +1,16 @@
<?php
use Wikimedia\TestingAccessWrapper;
/** @covers \EchoPush\NotificationServiceClient */
class NotificationServiceClientTest extends MediaWikiIntegrationTestCase {
public function testConstructRequest(): void {
$client = EchoServices::getInstance()->getPushNotificationServiceClient();
$client = TestingAccessWrapper::newFromObject( $client );
$payload = [ 'deviceTokens' => [ 'foo' ], 'messageType' => 'checkEchoV1' ];
$request = $client->constructRequest( 'fcm', $payload );
$this->assertInstanceOf( MWHttpRequest::class, $request );
}
}