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