Legoktm has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/92248


Change subject: [WIP] Add Redis backend
......................................................................

[WIP] Add Redis backend

Still at proof of concept stage

TODO:
* Don't use $wgMemc, use our own BagOfStuff class
* Implement bundling because I don't know how that works
* Make suck less

Change-Id: I3ee409be59cf31fe2e3e88221394cc05999eb8d3
---
M Echo.php
A includes/RedisEchoBackend.php
2 files changed, 267 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Echo 
refs/changes/48/92248/1

diff --git a/Echo.php b/Echo.php
index f5f3e61..4d317bc 100644
--- a/Echo.php
+++ b/Echo.php
@@ -101,6 +101,7 @@
 // Backend support
 $wgAutoloadClasses['MWEchoBackend'] = $dir . 'includes/EchoBackend.php';
 $wgAutoloadClasses['MWDbEchoBackend'] = $dir . 'includes/DbEchoBackend.php';
+$wgAutoloadClasses['MWRedisEchoBackend'] = $dir . 
'includes/RedisEchoBackend.php';
 $wgAutoloadClasses['MWEchoDbFactory'] = $dir . 'includes/EchoDbFactory.php';
 $wgAutoloadClasses['MWEchoNotifUser'] = $dir . 'includes/NotifUser.php';
 
diff --git a/includes/RedisEchoBackend.php b/includes/RedisEchoBackend.php
new file mode 100644
index 0000000..74ff9f9
--- /dev/null
+++ b/includes/RedisEchoBackend.php
@@ -0,0 +1,266 @@
+<?php
+
+/**
+ * Implements the Echo backend with Redis
+ * It is expected that your setup is persistent
+ * otherwise this won't really work.
+ *
+ */
+class MWRedisEchoBackend extends MWEchoBackend {
+
+       /**
+        * Store new notification
+        * @param array $row
+        */
+       public function createNotification( $row ) {
+               global $wgMemc;
+
+               // Store the event type with the notification so we don't need
+               // a separate lookup later on
+               $eventKey = wfMemcKey( 'echo-event', $row['notification_event'] 
);
+               $event = $wgMemc->get( $eventKey );
+               $type = $event['event_type'];
+               $row['event_type'] = $type;
+
+               $id = MWCryptRand::generateHex( 16 );
+               $key = wfMemcKey( 'echo-notification', $id );
+               $wgMemc->set( $key, $row );
+               // Note that this won't work for IPs...
+               $userKey = self::getUserCacheKey( $row['notification_user'] );
+               $userData = $wgMemc->get( $userKey );
+               if ( $userData === false ) {
+                       $new = array( 'notifs' => array( $id ) );
+               } else {
+                       $new = $userData;
+                       $new['notifs'][] = $id;
+               }
+               $wgMemc->set( $userKey, $new );
+
+               // @todo this isn't backend specific, move it somewhere else
+               $user = User::newFromId( $row['notification_user'] );
+               MWEchoNotifUser::newFromUser( $user )->resetNotificationCount( 
DB_MASTER );
+       }
+
+       /**
+        * Gets the cache key for a user id or user object
+        * @param User|int $user
+        * @return String
+        */
+       private static function getUserCacheKey( $user ) {
+               if ( $user instanceof User ) {
+                       $user = $user->getId();
+               }
+               return wfMemcKey( 'echo-notifs-user', $user );
+       }
+
+       /**
+        * Load some notifications
+        * @param User $user
+        * @param int $limit
+        * @param string $continue
+        * @param string $outputFormat
+        * @return array
+        *
+        * @fixme implement $continue
+        */
+       public function loadNotifications( $user, $limit, $continue, 
$outputFormat = 'web' ) {
+               global $wgMemc;
+
+               // @todo this isn't backend specific, move it somewhere else
+               $eventTypesToLoad = 
EchoNotificationController::getUserEnabledEvents( $user, $outputFormat );
+               if ( !$eventTypesToLoad ) {
+                       return array();
+               }
+
+               // @todo this code is duplicated in multiple places
+               $key = self::getUserCacheKey( $user );
+               $index = $wgMemc->get( $key );
+               if ( $index === false ) {
+                       return array();  // No notifications
+               }
+               $notifs = array();
+               foreach( $index['notifs'] as $id ) {
+                       $key = wfMemcKey( 'echo-notification', $id );
+                       $row = $wgMemc->get( $key );
+                       if ( $row !== false && in_array( $row['event_type'], 
$eventTypesToLoad ) ) {
+                               $eventKey = wfMemcKey( 'echo-event', 
$row['notification_event'] );
+                               $event = $wgMemc->get( $eventKey );
+                               $notifs[] = (object)array_merge( $row, $event );
+                               $limit--;
+                               if ( $limit == 0 ) {
+                                       break;
+                               }
+                       }
+
+               }
+
+               return $notifs;
+       }
+
+       /**
+        * @param User $user
+        * @param string $bundleHash
+        * @param string $type
+        * @param string $order
+        * @param int $limit
+        * @return bool|ResultWrapper
+        */
+       public function getRawBundleData( $user, $bundleHash, $type = 'web', 
$order = 'DESC', $limit = 250 ) {
+               // @fixme implement this
+       }
+
+       /**
+        * @param User $user
+        * @param string $bundleHash
+        * @return bool|ResultWrapper
+        */
+       public function getLastBundleStat( $user, $bundleHash ) {
+               // @fixme implement this
+       }
+
+       /**
+        * Add a new Event to the database
+        *
+        * @param array $row
+        * @return int
+        */
+       public function createEvent( $row ) {
+               global $wgMemc;
+               $idKey = wfMemcKey( 'echo-event-next-id' );
+               $id = $wgMemc->incr( $idKey );
+               if ( $id === false ) { // @fixme this is intended for first 
key, but not failure
+                       $id = 1;
+                       $wgMemc->set( 'echo-event-next-id', 2 );
+               }
+
+               $row['event_id'] = $id;
+               $key = wfMemcKey( 'echo-event', $id );
+               $wgMemc->set( $key, $row );
+               return $id;
+       }
+
+       /**
+        * Loads an Event from storage
+        * @param int $id
+        * @param bool $fromMaster This value is ignored since there is no 
concept of "master"
+        * @throws MWException
+        * @return array
+        */
+       public function loadEvent( $id, $fromMaster = true ) {
+               global $wgMemc;
+               $key = wfMemcKey( 'echo-event', $id );
+               $data = $wgMemc->get( $key );
+               if ( $data === false ) {
+                       throw new MWException( "No EchoEvent found with ID: 
$id" );
+               }
+
+               return (object)$data;
+       }
+
+       /**
+        * @param EchoEvent $event
+        */
+       public function updateEventExtra( $event ) {
+               global $wgMemc;
+               $key = wfMemcKey( 'echo-event', $event->getId() );
+               $data = $wgMemc->get( $key );
+               $data['event_extra'] = $event->serializeExtra();
+               $wgMemc->set( $key, $data );
+       }
+
+       /**
+        * Mark the given events as read for the user
+        * @param User $user
+        * @param array $eventIDs
+        */
+       public function markRead( $user, $eventIDs ) {
+               global $wgMemc;
+
+               $key = self::getUserCacheKey( $user );
+               $index = $wgMemc->get( $key );
+               if ( $index === false ) {
+                       return;  // No notifications
+               }
+               foreach( $index['notifs'] as $id ) {
+                       $key = wfMemcKey( 'echo-notification', $id );
+                       $row = $wgMemc->get( $key );
+                       if ( in_array( $row['notification_event'], $eventIDs ) 
) {
+                               $row['notification_read_timestamp'] = 
wfTimestampNow();
+                               $wgMemc->set( $key, $row );
+                       }
+               }
+       }
+
+       /**
+        * Mark all unread notifications for a user as read
+        * @param User $user
+        */
+       public function markAllRead( $user ) {
+               global $wgMemc;
+
+               $key = self::getUserCacheKey( $user );
+               $index = $wgMemc->get( $key );
+               if ( $index === false ) {
+                       return;  // No notifications
+               }
+               foreach( $index['notifs'] as $id ) {
+                       $key = wfMemcKey( 'echo-notification', $id );
+                       $row = $wgMemc->get( $key );
+                       if ( !isset( $row['notification_read_timestamp'] ) ) {
+                               $row['notification_read_timestamp'] = 
wfTimestampNow();
+                               $wgMemc->set( $key, $row );
+                       }
+               }
+       }
+
+       /**
+        * Get number of unread notifications for a user
+        * @param User $user
+        * @param string $dbSource This is not used
+        * @return int
+        */
+       public function getNotificationCount( $user, $dbSource ) {
+               global $wgMemc;
+               $count = 0;
+               $key = self::getUserCacheKey( $user );
+               $index = $wgMemc->get( $key );
+               if ( $index === false ) {
+                       return $count;  // No notifications
+               }
+               foreach( $index['notifs'] as $id ) {
+                       $key = wfMemcKey( 'echo-notification', $id );
+                       $row = $wgMemc->get( $key );
+                       if ( !isset( $row['notification_read_timestamp'] ) ) {
+                               $count += 1;
+                       }
+               }
+               return $count;
+       }
+
+       /**
+        * Get array event ids of unread notifications for the user
+        * @param User $user
+        * @param string $type
+        * @return array
+        */
+       public function getUnreadNotifications( $user, $type ) {
+               global $wgMemc;
+               $notifs = array();
+               $key = self::getUserCacheKey( $user );
+               $index = $wgMemc->get( $key );
+               if ( $index === false ) {
+                       return $notifs;  // No notifications
+               }
+               foreach( $index['notifs'] as $id ) {
+                       $key = wfMemcKey( 'echo-notification', $id );
+                       $row = $wgMemc->get( $key );
+                       if ( !isset( $row['notification_read_timestamp'] ) && 
$row['event_type'] == $type ) {
+                               $notifs[$row['notification_event']] = 
$row['notification_event'];
+                       }
+               }
+               return $notifs;
+
+       }
+
+
+}
\ No newline at end of file

-- 
To view, visit https://gerrit.wikimedia.org/r/92248
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I3ee409be59cf31fe2e3e88221394cc05999eb8d3
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Echo
Gerrit-Branch: master
Gerrit-Owner: Legoktm <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to