Ejegg has submitted this change and it was merged. ( 
https://gerrit.wikimedia.org/r/349117 )

Change subject: Update libs - upstream PHP-Queue
......................................................................


Update libs - upstream PHP-Queue

Change-Id: Ibb1365c1e214b6b368239e1124abe841eaaad014
---
D coderkungfu/php-queue/.gitreview
M coderkungfu/php-queue/README.md
M coderkungfu/php-queue/composer.json
M coderkungfu/php-queue/demo/queues/BeanstalkSampleQueue.php
M coderkungfu/php-queue/demo/runners/README.md
M coderkungfu/php-queue/src/PHPQueue/Backend/Beanstalkd.php
M coderkungfu/php-queue/src/PHPQueue/Backend/IronMQ.php
M coderkungfu/php-queue/src/PHPQueue/Backend/Memcache.php
M coderkungfu/php-queue/src/PHPQueue/Backend/MongoDB.php
M coderkungfu/php-queue/src/PHPQueue/Backend/PDO.php
M coderkungfu/php-queue/src/PHPQueue/Backend/Predis.php
M coderkungfu/php-queue/src/PHPQueue/Backend/Stomp.php
D coderkungfu/php-queue/src/PHPQueue/Interfaces/IndexedFifoQueueStore.php
D coderkungfu/php-queue/src/PHPQueue/Interfaces/KeyValueStore.php
M coderkungfu/php-queue/test/PHPQueue/Backend/PredisTest.php
D coderkungfu/php-queue/test/PHPQueue/Backend/PredisZsetTest.php
M composer/autoload_classmap.php
M composer/autoload_static.php
M composer/installed.json
M wikimedia/smash-pig/Core/Configuration.php
M wikimedia/smash-pig/Core/DataFiles/CsvReader.php
M wikimedia/smash-pig/Core/Logging/LogContextHandler.php
M wikimedia/smash-pig/Maintenance/RequeueDelayedMessages.php
M wikimedia/smash-pig/PaymentProviders/PayPal/Job.php
M wikimedia/smash-pig/PaymentProviders/PayPal/RefundMessage.php
A 
wikimedia/smash-pig/PaymentProviders/PayPal/Tests/Data/recurring_payment_profile_created.json
A 
wikimedia/smash-pig/PaymentProviders/PayPal/Tests/Data/recurring_payment_profile_created_transformed.json
A wikimedia/smash-pig/PaymentProviders/PayPal/Tests/Data/refund_ec.json
A 
wikimedia/smash-pig/PaymentProviders/PayPal/Tests/Data/refund_ec_transformed.json
A 
wikimedia/smash-pig/PaymentProviders/PayPal/Tests/Data/refund_recurring_ec.json
A 
wikimedia/smash-pig/PaymentProviders/PayPal/Tests/Data/refund_recurring_ec_transformed.json
M wikimedia/smash-pig/PaymentProviders/PayPal/Tests/config_test.yaml
M 
wikimedia/smash-pig/PaymentProviders/PayPal/Tests/phpunit/CaptureIncomingMessageTest.php
M wikimedia/smash-pig/SmashPig.yaml
M wikimedia/smash-pig/composer.json
M wikimedia/smash-pig/composer.lock
36 files changed, 277 insertions(+), 473 deletions(-)

Approvals:
  Ejegg: Verified; Looks good to me, approved



diff --git a/coderkungfu/php-queue/.gitreview b/coderkungfu/php-queue/.gitreview
deleted file mode 100644
index ffb389a..0000000
--- a/coderkungfu/php-queue/.gitreview
+++ /dev/null
@@ -1,6 +0,0 @@
-[gerrit]
-host=gerrit.wikimedia.org
-port=29418
-project=wikimedia/fundraising/php-queue.git
-defaultbranch=master
-defaultrebase=0
diff --git a/coderkungfu/php-queue/README.md b/coderkungfu/php-queue/README.md
index c69cef1..74ff0e7 100644
--- a/coderkungfu/php-queue/README.md
+++ b/coderkungfu/php-queue/README.md
@@ -1,4 +1,4 @@
-#PHP-Queue#
+# PHP-Queue #
 [![Gitter](https://badges.gitter.im/Join 
Chat.svg)](https://gitter.im/CoderKungfu/php-queue?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
 
 A unified front-end for different queuing backends. Includes a REST server, 
CLI interface and daemon runners.
@@ -190,16 +190,6 @@
 * FifoQueueStore
 
 A first in first out queue accessed by push and pop.
-
-* IndexedFifoQueueStore
-
-Messages are indexed along one column as they are pushed into a FIFO queue,
-otherwise these behave like FifoQueueStore. clear() deletes records by index.
-There is no get() operation, you'll need a KeyValueStore for that.
-
-* KeyValueStore
-
-Jobs can be retrieved and deleted by their index.
 
 ---
 ## License ##
diff --git a/coderkungfu/php-queue/composer.json 
b/coderkungfu/php-queue/composer.json
index f75d7ef..085c069 100644
--- a/coderkungfu/php-queue/composer.json
+++ b/coderkungfu/php-queue/composer.json
@@ -23,21 +23,19 @@
         "clio/clio": "0.1.*"
     },
     "require-dev": {
-        "jakub-onderka/php-parallel-lint": "0.9",
-        "phpunit/phpunit": "4.4.*"
-    },
-    "scripts": {
-        "test": [
-            "parallel-lint . --exclude vendor",
-            "phpunit"
-        ]
+        "mrpoundsign/pheanstalk-5.3": "dev-master",
+        "aws/aws-sdk-php": "dev-master",
+        "amazonwebservices/aws-sdk-for-php": "dev-master",
+        "predis/predis": "1.*",
+        "iron-io/iron_mq": "dev-master",
+        "ext-memcache": "*",
+        "microsoft/windowsazure": "dev-master"
     },
     "suggest": {
         "predis/predis": "For Redis backend support",
         "mrpoundsign/pheanstalk-5.3": "For Beanstalkd backend support",
         "aws/aws-sdk-php": "For AWS SQS backend support",
         "amazonwebservices/aws-sdk-for-php": "For AWS SQS backend support 
(legacy version)",
-        "ext-memcache": "*",
         "pecl-mongodb": "For MongoDB backend support",
         "clio/clio": "Support for daemonizing PHP CLI runner",
         "iron-io/iron_mq": "For IronMQ backend support",
diff --git a/coderkungfu/php-queue/demo/queues/BeanstalkSampleQueue.php 
b/coderkungfu/php-queue/demo/queues/BeanstalkSampleQueue.php
index 158f339..9335e4f 100644
--- a/coderkungfu/php-queue/demo/queues/BeanstalkSampleQueue.php
+++ b/coderkungfu/php-queue/demo/queues/BeanstalkSampleQueue.php
@@ -19,10 +19,10 @@
                         );
     }
 
-    public function addJob($newJob = null)
+    public function addJob($newJob = null, $DEFAULT_PRIORITY=1024, 
$DEFAULT_DELAY=0, $DEFAULT_TTR=60)
     {
         $formatted_data = array('worker'=>$this->queueWorker, 'data'=>$newJob);
-        $this->dataSource->add($formatted_data);
+        $this->dataSource->add($formatted_data, $DEFAULT_PRIORITY, 
$DEFAULT_DELAY, $DEFAULT_TTR);
 
         return true;
     }
diff --git a/coderkungfu/php-queue/demo/runners/README.md 
b/coderkungfu/php-queue/demo/runners/README.md
index 9c91041..5ddab8d 100644
--- a/coderkungfu/php-queue/demo/runners/README.md
+++ b/coderkungfu/php-queue/demo/runners/README.md
@@ -185,7 +185,7 @@
 1. Add this to the top of your script:
 
        ```
-#!/usr/bin/php
+# !/usr/bin/php
 <?php
 #
 # BeanstalkSampleDaemon    Starts the PHP-Queue runner for BeanstalkSample
diff --git a/coderkungfu/php-queue/src/PHPQueue/Backend/Beanstalkd.php 
b/coderkungfu/php-queue/src/PHPQueue/Backend/Beanstalkd.php
index 2d9210f..f763e08 100644
--- a/coderkungfu/php-queue/src/PHPQueue/Backend/Beanstalkd.php
+++ b/coderkungfu/php-queue/src/PHPQueue/Backend/Beanstalkd.php
@@ -3,11 +3,11 @@
 
 use PHPQueue\Exception\BackendException;
 use PHPQueue\Exception\JobNotFoundException;
-use PHPQueue\Interfaces\IndexedFifoQueueStore;
+use PHPQueue\Interfaces\FifoQueueStore;
 
 class Beanstalkd
     extends Base
-    implements IndexedFifoQueueStore
+    implements FifoQueueStore
 {
     public $server_uri;
     public $tube;
@@ -34,9 +34,9 @@
      * @param  array   $data
      * @return boolean Status of saving
      */
-    public function add($data=array())
+    public function add($data=array(), $DEFAULT_PRIORITY=1024, 
$DEFAULT_DELAY=0, $DEFAULT_TTR=60)
     {
-        $this->push($data);
+        $this->push($data, $DEFAULT_PRIORITY, $DEFAULT_DELAY, $DEFAULT_TTR);
         return true;
     }
 
@@ -44,10 +44,10 @@
      * @param array $data
      * @return integer Primary ID of the new record.
      */
-    public function push($data)
+    public function push($data, $DEFAULT_PRIORITY=1024, $DEFAULT_DELAY=0, 
$DEFAULT_TTR=60)
     {
         $this->beforeAdd();
-        $response = 
$this->getConnection()->useTube($this->tube)->put(json_encode($data));
+        $response = 
$this->getConnection()->useTube($this->tube)->put(json_encode($data), 
$DEFAULT_PRIORITY, $DEFAULT_DELAY, $DEFAULT_TTR);
         if (!$response) {
             throw new BackendException("Unable to save job.");
         }
diff --git a/coderkungfu/php-queue/src/PHPQueue/Backend/IronMQ.php 
b/coderkungfu/php-queue/src/PHPQueue/Backend/IronMQ.php
index eb195fd..0cbefd9 100644
--- a/coderkungfu/php-queue/src/PHPQueue/Backend/IronMQ.php
+++ b/coderkungfu/php-queue/src/PHPQueue/Backend/IronMQ.php
@@ -2,11 +2,11 @@
 namespace PHPQueue\Backend;
 
 use PHPQueue\Exception\BackendException;
-use PHPQueue\Interfaces\IndexedFifoQueueStore;
+use PHPQueue\Interfaces\FifoQueueStore;
 
 class IronMQ
     extends Base
-    implements IndexedFifoQueueStore
+    implements FifoQueueStore
 {
     public $token = null;
     public $project_id = null;
diff --git a/coderkungfu/php-queue/src/PHPQueue/Backend/Memcache.php 
b/coderkungfu/php-queue/src/PHPQueue/Backend/Memcache.php
index a210972..b7c03f1 100644
--- a/coderkungfu/php-queue/src/PHPQueue/Backend/Memcache.php
+++ b/coderkungfu/php-queue/src/PHPQueue/Backend/Memcache.php
@@ -2,11 +2,9 @@
 namespace PHPQueue\Backend;
 
 use PHPQueue\Exception\BackendException;
-use PHPQueue\Interfaces\KeyValueStore;
 
 class Memcache
     extends Base
-    implements KeyValueStore
 {
     public $servers;
     public $is_persistent = false;
diff --git a/coderkungfu/php-queue/src/PHPQueue/Backend/MongoDB.php 
b/coderkungfu/php-queue/src/PHPQueue/Backend/MongoDB.php
index 86fc6c1..6a4440f 100644
--- a/coderkungfu/php-queue/src/PHPQueue/Backend/MongoDB.php
+++ b/coderkungfu/php-queue/src/PHPQueue/Backend/MongoDB.php
@@ -5,11 +5,9 @@
 
 use PHPQueue\Exception\BackendException;
 use PHPQueue\Exception\JobNotFoundException;
-use PHPQueue\Interfaces\KeyValueStore;
 
 class MongoDB
     extends Base
-    implements KeyValueStore
 {
     public $server_uri;
     public $db_name;
diff --git a/coderkungfu/php-queue/src/PHPQueue/Backend/PDO.php 
b/coderkungfu/php-queue/src/PHPQueue/Backend/PDO.php
index fe41689..86593b0 100644
--- a/coderkungfu/php-queue/src/PHPQueue/Backend/PDO.php
+++ b/coderkungfu/php-queue/src/PHPQueue/Backend/PDO.php
@@ -4,15 +4,11 @@
 use PHPQueue\Exception\BackendException;
 use PHPQueue\Interfaces\AtomicReadBuffer;
 use PHPQueue\Interfaces\FifoQueueStore;
-use PHPQueue\Interfaces\IndexedFifoQueueStore;
-use PHPQueue\Interfaces\KeyValueStore;
 
 class PDO
     extends Base
     implements AtomicReadBuffer,
-        FifoQueueStore,
-        IndexedFifoQueueStore,
-        KeyValueStore
+        FifoQueueStore
 {
     private $connection_string;
     private $db_user;
diff --git a/coderkungfu/php-queue/src/PHPQueue/Backend/Predis.php 
b/coderkungfu/php-queue/src/PHPQueue/Backend/Predis.php
index aaeb9bd..26e1306 100644
--- a/coderkungfu/php-queue/src/PHPQueue/Backend/Predis.php
+++ b/coderkungfu/php-queue/src/PHPQueue/Backend/Predis.php
@@ -6,34 +6,20 @@
 
 use PHPQueue\Exception\BackendException;
 use PHPQueue\Interfaces\AtomicReadBuffer;
-use PHPQueue\Interfaces\KeyValueStore;
 use PHPQueue\Interfaces\FifoQueueStore;
 use PHPQueue\Json;
 
 /**
- * Wraps several styles of redis use:
- *     - If constructed with a "order_key" option, the data will be accessible
- *       as a key-value store, and will also provide pop and push using
- *       $data[$order_key] as the FIFO ordering.  If the ordering value is a
- *       timestamp, for example, then the queue will have real-world FIFO
- *       behavior over time, and even if the data comes in out of order, we 
will
- *       always pop the true oldest record.
- *       If you wish to push to this type of store, you'll also need to provide
- *       the "correlation_key" option so the random-access key can be
- *       extracted from data.
+ * Wraps redis use:
  *     - Pushing scalar data will store it as a queue under queue_name.
  *     - Setting scalar data will store it under the key.
  *     - If data is an array, setting will store it as a hash, under the key.
- *
- * TODO: The different behaviors should be modeled as several backends which
- * perhaps inherit from an AbstractPredis.
  */
 class Predis
     extends Base
     implements
         AtomicReadBuffer,
-        FifoQueueStore,
-        KeyValueStore
+        FifoQueueStore
 {
     const TYPE_STRING='string';
     const TYPE_HASH='hash';
@@ -41,15 +27,10 @@
     const TYPE_SET='set';
     const TYPE_NONE='none';
 
-    // Internal sub-key to hold the ordering.
-    const FIFO_INDEX = 'fifo';
-
     public $servers;
     public $redis_options = array();
     public $queue_name;
     public $expiry;
-    public $order_key;
-    public $correlation_key;
 
     public function __construct($options=array())
     {
@@ -65,13 +46,6 @@
         }
         if (!empty($options['expiry'])) {
             $this->expiry = $options['expiry'];
-        }
-        if (!empty($options['order_key'])) {
-            $this->order_key = $options['order_key'];
-            $this->redis_options['prefix'] = $this->queue_name . ':';
-        }
-        if (!empty($options['correlation_key'])) {
-            $this->correlation_key = $options['correlation_key'];
         }
     }
 
@@ -100,60 +74,10 @@
             throw new BackendException("No queue specified.");
         }
         $encoded_data = json_encode($data);
-        if ($this->order_key) {
-            if (!$this->correlation_key) {
-                throw new BackendException("Cannot push to indexed fifo queue 
without a correlation key.");
-            }
-            $key = $data[$this->correlation_key];
-            if (!$key) {
-                throw new BackendException("Cannot push to indexed fifo queue 
without correlation data.");
-            }
-            $status = $this->addToIndexedFifoQueue($key, $data);
-            if (!self::boolStatus($status)) {
-                throw new BackendException('Couldn\'t push to indexed fifo 
queue: ' . $status->getMessage());
-            }
-        } else {
-            // Note that we're ignoring the "new length" return value, cos I 
don't
-            // see how to make it useful.
-            $this->getConnection()->rpush($this->queue_name, $encoded_data);
-        }
-    }
 
-    /**
-     * Remove stale elements at the top of the queue and return the first real 
entry
-     *
-     * When data expires, it still leaves a queue entry linking to its
-     * correlation ID.  Clear any of these stale entries at the head of
-     * the queue.
-     *
-     * Note that we run this from inside a transaction, to make it less
-     * likely that we'll hit a race condition.
-     *
-     * @param MultiExec $tx transaction we're working within.
-     *
-     * @return string|null Top element's key, or null if the queue is empty.
-     */
-    public function peekWithCleanup(MultiExec $tx)
-    {
-        for (;;) {
-            // Look up the first element in the FIFO ordering.
-            $values = $tx->zrange(Predis::FIFO_INDEX, 0, 0);
-            if ($values) {
-                // Use that value as a key into the key-value block.
-                $key = $values[0];
-                $exists = $tx->exists($key);
-
-                if (!$exists) {
-                    // If the data is missing, then remove from the FIFO index.
-                    $tx->zrem(Predis::FIFO_INDEX, $key);
-                } else {
-                    return $key;
-                }
-            } else {
-                break;
-            }
-        }
-        return null;
+        // Note that we're ignoring the "new length" return value, cos I don't
+        // see how to make it useful.
+        $this->getConnection()->rpush($this->queue_name, $encoded_data);
     }
 
     /**
@@ -166,33 +90,7 @@
         if (!$this->hasQueue()) {
             throw new BackendException("No queue specified.");
         }
-        if ($this->order_key) {
-            // Pop the first element.
-            // Adapted from 
https://github.com/nrk/predis/blob/v1.0/examples/transaction_using_cas.php
-            $options = array(
-                'cas' => true,
-                'watch' => self::FIFO_INDEX,
-                'retry' => 3,
-            );
-            $self = $this;
-            $this->getConnection()->transaction($options, function ($tx) use 
(&$data, &$self) {
-                // Begin transaction.
-                $tx->multi();
-
-                $key = $self->peekWithCleanup($tx);
-
-                if ($key) {
-                    // Use that value as a key into the key-value block.
-                    $data = $tx->get($key);
-
-                    // Remove from both indexes.
-                    $tx->zrem(Predis::FIFO_INDEX, $key);
-                    $tx->del($key);
-                }
-            });
-        } else {
-            $data = $this->getConnection()->lpop($this->queue_name);
-        }
+        $data = $this->getConnection()->lpop($this->queue_name);
         if (!$data) {
             return null;
         }
@@ -206,9 +104,6 @@
     public function popAtomic($callback) {
         if (!$this->hasQueue()) {
             throw new BackendException("No queue specified.");
-        }
-        if ($this->order_key) {
-            throw new BackendException("atomicPop not yet supported for 
zsets");
         }
 
         // Pop and process the first element, erring on the side of
@@ -246,33 +141,12 @@
         if (!$this->hasQueue()) {
             throw new BackendException("No queue specified.");
         }
-        if ($this->order_key) {
-            // Adapted from 
https://github.com/nrk/predis/blob/v1.0/examples/transaction_using_cas.php
-            $options = array(
-                'cas' => true,
-                'watch' => self::FIFO_INDEX,
-                'retry' => 3,
-            );
-            $self = $this;
-            $this->getConnection()->transaction($options, function ($tx) use 
(&$data, &$self) {
-                // Begin transaction.
-                $tx->multi();
-
-                $key = $self->peekWithCleanup($tx);
-
-                if ($key) {
-                    // Use that value as a key into the key-value block.
-                    $data = $tx->get($key);
-                }
-            });
+        $data_range = $this->getConnection()->lrange($this->queue_name, 0, 0);
+        if (!$data_range) {
+            return null;
         } else {
-            $data_range = $this->getConnection()->lrange($this->queue_name, 0, 
0);
-            if (!$data_range) {
-                return null;
-            } else {
-                // Unpack list.
-                $data = $data_range[0];
-            }
+            // Unpack list.
+            $data = $data_range[0];
         }
         if (!$data) {
             return null;
@@ -323,9 +197,7 @@
         $this->beforeAdd();
         try {
             $status = false;
-            if ($this->order_key) {
-                $status = $this->addToIndexedFifoQueue($key, $data);
-            } elseif (is_array($data)) {
+            if (is_array($data)) {
                 // FIXME: Assert
                 $status = $this->getConnection()->hmset($key, $data);
             } elseif (is_string($data) || is_numeric($data)) {
@@ -341,36 +213,6 @@
         } catch (\Exception $ex) {
             throw new BackendException($ex->getMessage(), $ex->getCode());
         }
-    }
-
-    /**
-     * Store the data under its order and correlation keys
-     *
-     * @param string $key
-     * @param array $data
-     * @return Predis\Response\ResponseInterface
-     */
-    protected function addToIndexedFifoQueue($key, $data)
-    {
-        $options = array(
-            'cas' => true,
-            'watch' => self::FIFO_INDEX,
-            'retry' => 3,
-        );
-        $score = $data[$this->order_key];
-        $encoded_data = json_encode($data);
-        $status = false;
-        $expiry = $this->expiry;
-        $this->getConnection()->transaction($options, function ($tx) use 
($key, $score, $encoded_data, $expiry, &$status) {
-            $tx->multi();
-            $tx->zadd(Predis::FIFO_INDEX, $score, $key);
-            if ($expiry) {
-                $status = $tx->setex($key, $expiry, $encoded_data);
-            } else {
-                $status = $tx->set($key, $encoded_data);
-            }
-        });
-        return $status;
     }
 
     /** @deprecated */
@@ -394,10 +236,6 @@
             return null;
         }
         $this->beforeGet($key);
-        if ($this->order_key) {
-            $data = $this->getConnection()->get($key);
-            return Json::safe_decode($data);
-        }
         $type = $this->getConnection()->type($key);
         switch ($type) {
             case self::TYPE_STRING:
@@ -433,16 +271,7 @@
     {
         $this->beforeClear($key);
 
-        if ($this->order_key) {
-            $result = $this->getConnection()->pipeline()
-                ->zrem(self::FIFO_INDEX, $key)
-                ->del($key)
-                ->execute();
-
-            $num_removed = $result[1];
-        } else {
-            $num_removed = $this->getConnection()->del($key);
-        }
+        $num_removed = $this->getConnection()->del($key);
 
         $this->afterClearRelease();
 
diff --git a/coderkungfu/php-queue/src/PHPQueue/Backend/Stomp.php 
b/coderkungfu/php-queue/src/PHPQueue/Backend/Stomp.php
index e855af3..65bd705 100644
--- a/coderkungfu/php-queue/src/PHPQueue/Backend/Stomp.php
+++ b/coderkungfu/php-queue/src/PHPQueue/Backend/Stomp.php
@@ -7,7 +7,6 @@
 use PHPQueue\Exception\BackendException;
 use PHPQueue\Exception\JobNotFoundException;
 use PHPQueue\Interfaces\FifoQueueStore;
-use PHPQueue\Interfaces\KeyValueStore;
 
 /**
  * Wrap a STOMP queue
@@ -18,7 +17,7 @@
  */
 class Stomp
     extends Base
-    implements FifoQueueStore, KeyValueStore
+    implements FifoQueueStore
 {
     public $queue_name;
     public $uri;
diff --git 
a/coderkungfu/php-queue/src/PHPQueue/Interfaces/IndexedFifoQueueStore.php 
b/coderkungfu/php-queue/src/PHPQueue/Interfaces/IndexedFifoQueueStore.php
deleted file mode 100644
index ff06f66..0000000
--- a/coderkungfu/php-queue/src/PHPQueue/Interfaces/IndexedFifoQueueStore.php
+++ /dev/null
@@ -1,32 +0,0 @@
-<?php
-namespace PHPQueue\Interfaces;
-
-/**
- * Implemented by backends that provide queue-like access, where each message
- * also has an ID.
- */
-interface IndexedFifoQueueStore extends FifoQueueStore
-{
-    /**
-     * @param mixed $value Serializable value.
-     * @return string Message ID.
-     * @throws \Exception On failure.
-     */
-    public function push($value);
-
-    /**
-     * @return array The next available data.
-     * @throws \PHPQueue\Exception\JobNotFoundException When no data is 
available.
-     * @throws \Exception Other failures.
-     *
-     * @deprecated This is not a safe operation.  Consider using
-     *     AtomicReadBuffer::popAtomic instead.
-     */
-    public function pop();
-
-    /**
-     * @param $key string
-     * @throws \Exception
-     */
-    public function clear($key);
-}
diff --git a/coderkungfu/php-queue/src/PHPQueue/Interfaces/KeyValueStore.php 
b/coderkungfu/php-queue/src/PHPQueue/Interfaces/KeyValueStore.php
deleted file mode 100644
index b9d5823..0000000
--- a/coderkungfu/php-queue/src/PHPQueue/Interfaces/KeyValueStore.php
+++ /dev/null
@@ -1,33 +0,0 @@
-<?php
-namespace PHPQueue\Interfaces;
-
-/**
- * Implemented by backends that support key-value retrieval.
- */
-interface KeyValueStore
-{
-    /**
-     * @param $key string
-     * @param $value mixed Serializable value
-     * @param $properties array optional additional message properties
-     *     FIXME: Define better.  Are these columns the indexes?  Why separate
-     *     from the message?
-     * @throws \Exception
-     */
-    public function set($key, $value, $properties=array());
-
-    /**
-     * Look up and return a value by its index value.
-     *
-     * @param $key string
-     * @return array The data.
-     * @throws \Exception
-     */
-    public function get($key);
-
-    /**
-     * @param $key string
-     * @throws \Exception
-     */
-    public function clear($key);
-}
diff --git a/coderkungfu/php-queue/test/PHPQueue/Backend/PredisTest.php 
b/coderkungfu/php-queue/test/PHPQueue/Backend/PredisTest.php
index 5eb1527..ed35dfd 100644
--- a/coderkungfu/php-queue/test/PHPQueue/Backend/PredisTest.php
+++ b/coderkungfu/php-queue/test/PHPQueue/Backend/PredisTest.php
@@ -1,5 +1,8 @@
 <?php
 namespace PHPQueue\Backend;
+
+use PHPQueue\Exception\JsonException;
+
 class PredisTest extends \PHPUnit_Framework_TestCase
 {
     private $object;
@@ -188,13 +191,18 @@
         $this->assertNull($this->object->pop());
     }
 
+    /**
+     * @expectedException PHPQueue\Exception\JsonException
+     */
     public function testPopBadJson()
     {
         // Bad JSON
-        $data = "{'a': u'Weezle-'" . mt_rand() . "'}";
+        $data = '{"a": bad "Weezle-' . mt_rand() . '"}';
         $this->object->getConnection()->rpush($this->object->queue_name, 
$data);
 
-        $this->assertNull($this->object->pop());
+        $this->object->pop();
+
+        $this->fail();
     }
 
     public function testPopEmpty()
diff --git a/coderkungfu/php-queue/test/PHPQueue/Backend/PredisZsetTest.php 
b/coderkungfu/php-queue/test/PHPQueue/Backend/PredisZsetTest.php
deleted file mode 100644
index 32df3cb..0000000
--- a/coderkungfu/php-queue/test/PHPQueue/Backend/PredisZsetTest.php
+++ /dev/null
@@ -1,121 +0,0 @@
-<?php
-namespace PHPQueue\Backend;
-class PredisZsetTest extends \PHPUnit_Framework_TestCase
-{
-    private $object;
-
-    public function setUp()
-    {
-        parent::setUp();
-        if (!class_exists('\Predis\Client')) {
-            $this->markTestSkipped('Predis not installed');
-        } else {
-            $options = array(
-                'servers' => array('host' => '127.0.0.1', 'port' => 6379)
-                , 'queue' => 'testqueue-' . mt_rand()
-                , 'order_key' => 'timestamp'
-                , 'correlation_key' => 'txn_id'
-            );
-            $this->object = new Predis($options);
-        }
-    }
-
-    public function tearDown()
-    {
-        if ($this->object) {
-            $this->object->getConnection()->flushall();
-        }
-        parent::tearDown();
-    }
-
-    public function testSet()
-    {
-        $key = 'A0001';
-        $data = array('name' => 'Michael', 'timestamp' => 1);
-        $this->object->set($key, $data);
-
-        $key = 'A0001';
-        $data = array('name' => 'Michael Cheng', 'timestamp' => 2);
-        $this->object->set($key, $data);
-
-        $key = 'A0002';
-        $data = array('name' => 'Michael Cheng', 'timestamp' => 3);
-        $this->object->set($key, $data);
-    }
-
-    public function testGet()
-    {
-        $key = 'A0001';
-        $data1 = array('name' => 'Michael', 'timestamp' => 1);
-        $this->object->set($key, $data1);
-
-        $key = 'A0001';
-        $data2 = array('name' => 'Michael Cheng', 'timestamp' => 2);
-        $this->object->set($key, $data2);
-
-        $key = 'A0002';
-        $data3 = array('name' => 'Michael Cheng', 'timestamp' => 3);
-        $this->object->set($key, $data3);
-
-        $result = $this->object->get('A0001');
-        $this->assertEquals($data2, $result);
-
-        $result = $this->object->getKey('A0002');
-        $this->assertEquals($data3, $result);
-    }
-
-    public function testClear()
-    {
-        $key = 'A0002';
-        $data = array('name' => 'Adam Wight', 'timestamp' => 2718);
-        $result = $this->object->set($key, $data);
-
-        $result = $this->object->clear($key);
-        $this->assertTrue($result);
-
-        $result = $this->object->get($key);
-        $this->assertNull($result);
-    }
-
-    public function testClearEmpty()
-    {
-        $jobId = 'xxx';
-        $this->assertFalse($this->object->clear($jobId));
-    }
-
-    public function testPushPop()
-    {
-        $data = array(
-            'name' => 'Weezle-' . mt_rand(),
-            'timestamp' => mt_rand(),
-            'txn_id' => mt_rand(),
-        );
-        $this->object->push($data);
-
-        $this->assertEquals($data, $this->object->get($data['txn_id']));
-
-        $this->assertEquals($data, $this->object->pop());
-
-        $this->assertNull($this->object->get($data['txn_id']));
-    }
-
-    public function testPopEmpty()
-    {
-        $this->assertNull($this->object->pop());
-    }
-
-    public function testPeek()
-    {
-        $data = array(
-            'name' => 'Weezle-' . mt_rand(),
-            'timestamp' => mt_rand(),
-            'txn_id' => mt_rand(),
-        );
-        $this->object->push($data);
-
-        $this->assertEquals($data, $this->object->peek());
-
-        // Check that we didn't remove the object by peeking.
-        $this->assertEquals($data, $this->object->pop());
-    }
-}
diff --git a/composer/autoload_classmap.php b/composer/autoload_classmap.php
index 9cd52f3..247cb33 100644
--- a/composer/autoload_classmap.php
+++ b/composer/autoload_classmap.php
@@ -215,8 +215,6 @@
     'PHPQueue\\Interfaces\\Auth' => $vendorDir . 
'/coderkungfu/php-queue/src/PHPQueue/Interfaces/Auth.php',
     'PHPQueue\\Interfaces\\Config' => $vendorDir . 
'/coderkungfu/php-queue/src/PHPQueue/Interfaces/Config.php',
     'PHPQueue\\Interfaces\\FifoQueueStore' => $vendorDir . 
'/coderkungfu/php-queue/src/PHPQueue/Interfaces/FifoQueueStore.php',
-    'PHPQueue\\Interfaces\\IndexedFifoQueueStore' => $vendorDir . 
'/coderkungfu/php-queue/src/PHPQueue/Interfaces/IndexedFifoQueueStore.php',
-    'PHPQueue\\Interfaces\\KeyValueStore' => $vendorDir . 
'/coderkungfu/php-queue/src/PHPQueue/Interfaces/KeyValueStore.php',
     'PHPQueue\\Job' => $vendorDir . 
'/coderkungfu/php-queue/src/PHPQueue/Job.php',
     'PHPQueue\\JobQueue' => $vendorDir . 
'/coderkungfu/php-queue/src/PHPQueue/JobQueue.php',
     'PHPQueue\\Json' => $vendorDir . 
'/coderkungfu/php-queue/src/PHPQueue/Json.php',
diff --git a/composer/autoload_static.php b/composer/autoload_static.php
index 4cda45f..347f7ec 100644
--- a/composer/autoload_static.php
+++ b/composer/autoload_static.php
@@ -331,8 +331,6 @@
         'PHPQueue\\Interfaces\\Auth' => __DIR__ . '/..' . 
'/coderkungfu/php-queue/src/PHPQueue/Interfaces/Auth.php',
         'PHPQueue\\Interfaces\\Config' => __DIR__ . '/..' . 
'/coderkungfu/php-queue/src/PHPQueue/Interfaces/Config.php',
         'PHPQueue\\Interfaces\\FifoQueueStore' => __DIR__ . '/..' . 
'/coderkungfu/php-queue/src/PHPQueue/Interfaces/FifoQueueStore.php',
-        'PHPQueue\\Interfaces\\IndexedFifoQueueStore' => __DIR__ . '/..' . 
'/coderkungfu/php-queue/src/PHPQueue/Interfaces/IndexedFifoQueueStore.php',
-        'PHPQueue\\Interfaces\\KeyValueStore' => __DIR__ . '/..' . 
'/coderkungfu/php-queue/src/PHPQueue/Interfaces/KeyValueStore.php',
         'PHPQueue\\Job' => __DIR__ . '/..' . 
'/coderkungfu/php-queue/src/PHPQueue/Job.php',
         'PHPQueue\\JobQueue' => __DIR__ . '/..' . 
'/coderkungfu/php-queue/src/PHPQueue/JobQueue.php',
         'PHPQueue\\Json' => __DIR__ . '/..' . 
'/coderkungfu/php-queue/src/PHPQueue/Json.php',
diff --git a/composer/installed.json b/composer/installed.json
index b0b36a8..95ef25a 100644
--- a/composer/installed.json
+++ b/composer/installed.json
@@ -350,8 +350,14 @@
         "version_normalized": "9999999-dev",
         "source": {
             "type": "git",
-            "url": 
"https://gerrit.wikimedia.org/r/p/wikimedia/fundraising/php-queue.git";,
-            "reference": "d56c5bd69dad595f2e00a3e10c851736b1feb57b"
+            "url": "https://github.com/CoderKungfu/php-queue.git";,
+            "reference": "dd8412f105632d31cdd77933ec40a08640752c99"
+        },
+        "dist": {
+            "type": "zip",
+            "url": 
"https://api.github.com/repos/CoderKungfu/php-queue/zipball/dd8412f105632d31cdd77933ec40a08640752c99";,
+            "reference": "dd8412f105632d31cdd77933ec40a08640752c99",
+            "shasum": ""
         },
         "require": {
             "clio/clio": "0.1.*",
@@ -359,15 +365,19 @@
             "php": ">=5.3.0"
         },
         "require-dev": {
-            "jakub-onderka/php-parallel-lint": "0.9",
-            "phpunit/phpunit": "4.4.*"
+            "amazonwebservices/aws-sdk-for-php": "dev-master",
+            "aws/aws-sdk-php": "dev-master",
+            "ext-memcache": "*",
+            "iron-io/iron_mq": "dev-master",
+            "microsoft/windowsazure": "dev-master",
+            "mrpoundsign/pheanstalk-5.3": "dev-master",
+            "predis/predis": "1.*"
         },
         "suggest": {
             "Respect/Rest": "For a REST server to post job data",
             "amazonwebservices/aws-sdk-for-php": "For AWS SQS backend support 
(legacy version)",
             "aws/aws-sdk-php": "For AWS SQS backend support",
             "clio/clio": "Support for daemonizing PHP CLI runner",
-            "ext-memcache": "*",
             "fusesource/stomp-php": "For the STOMP backend",
             "iron-io/iron_mq": "For IronMQ backend support",
             "microsoft/windowsazure": "For Windows Azure Service Bus backend 
support",
@@ -375,7 +385,7 @@
             "pecl-mongodb": "For MongoDB backend support",
             "predis/predis": "For Redis backend support"
         },
-        "time": "2017-01-04 21:01:15",
+        "time": "2017-04-17 14:11:55",
         "type": "library",
         "extra": {
             "branch-alias": {
@@ -388,12 +398,7 @@
                 "PHPQueue": "src/"
             }
         },
-        "scripts": {
-            "test": [
-                "parallel-lint . --exclude vendor",
-                "phpunit"
-            ]
-        },
+        "notification-url": "https://packagist.org/downloads/";,
         "license": [
             "MIT"
         ],
@@ -1014,7 +1019,7 @@
         "source": {
             "type": "git",
             "url": 
"https://gerrit.wikimedia.org/r/wikimedia/fundraising/SmashPig.git";,
-            "reference": "ec6ea516530400dfb7bb02a72ef52318a40b7bb6"
+            "reference": "78a7f28dee35cb4f5df285f53c7b643eecec7d33"
         },
         "require": {
             "amzn/login-and-pay-with-amazon-sdk-php": "dev-master",
@@ -1031,7 +1036,7 @@
             "jakub-onderka/php-parallel-lint": "^0.9",
             "phpunit/phpunit": "^4.8"
         },
-        "time": "2017-04-10 22:28:50",
+        "time": "2017-04-19 21:15:22",
         "type": "library",
         "installation-source": "source",
         "autoload": {
diff --git a/wikimedia/smash-pig/Core/Configuration.php 
b/wikimedia/smash-pig/Core/Configuration.php
index f94d72c..f499aa6 100644
--- a/wikimedia/smash-pig/Core/Configuration.php
+++ b/wikimedia/smash-pig/Core/Configuration.php
@@ -325,7 +325,7 @@
         * or empty string to begin.
         * @throws SmashPigException
         */
-       private static function treeMerge( &$base, $graft, $myRoot = '' ) {
+       protected static function treeMerge( &$base, $graft, $myRoot = '' ) {
                foreach ( $graft as $graftNodeName => $graftNodeValue ) {
                        $node = ($myRoot ? "{$myRoot}/{$graftNodeName}" : 
$graftNodeName);
 
diff --git a/wikimedia/smash-pig/Core/DataFiles/CsvReader.php 
b/wikimedia/smash-pig/Core/DataFiles/CsvReader.php
index 8f3f963..9c026ed 100644
--- a/wikimedia/smash-pig/Core/DataFiles/CsvReader.php
+++ b/wikimedia/smash-pig/Core/DataFiles/CsvReader.php
@@ -24,7 +24,7 @@
        /**
         * @var string Delimiter for the csv file.
         */
-       private $delimiter = null;
+       protected $delimiter = null;
 
        /**
         * Create an iterative CSV file reader.
diff --git a/wikimedia/smash-pig/Core/Logging/LogContextHandler.php 
b/wikimedia/smash-pig/Core/Logging/LogContextHandler.php
index 50fc794..5d04579 100644
--- a/wikimedia/smash-pig/Core/Logging/LogContextHandler.php
+++ b/wikimedia/smash-pig/Core/Logging/LogContextHandler.php
@@ -6,13 +6,13 @@
 
 class LogContextHandler {
        /** @var [LogEvent[]] Stack of LogEvent arrays holding all log lines 
for a context */
-       private $contextData = array( array() );
+       protected $contextData = array( array() );
 
        /** @var string[] Stack of strings holding context names */
-       private $contextNames;
+       protected $contextNames;
 
        /** @var ILogStream[] */
-       private $logStreams;
+       protected $logStreams;
 
        public function __construct( $rootName, $logStreams ) {
                $this->contextNames = array( $rootName );
diff --git a/wikimedia/smash-pig/Maintenance/RequeueDelayedMessages.php 
b/wikimedia/smash-pig/Maintenance/RequeueDelayedMessages.php
index 1d0eb6a..70b446a 100644
--- a/wikimedia/smash-pig/Maintenance/RequeueDelayedMessages.php
+++ b/wikimedia/smash-pig/Maintenance/RequeueDelayedMessages.php
@@ -42,7 +42,7 @@
 
                foreach( $messages as $message ) {
                        $queueName = $message['original_queue'];
-                       // FIXME: getting it by alias, this will be annoying 
cos -new
+                       // FIXME: getting it by alias
                        $queue = BaseQueueConsumer::getQueue( $queueName );
                        unset( $message['original_queue'] );
                        $queue->push( $message );
diff --git a/wikimedia/smash-pig/PaymentProviders/PayPal/Job.php 
b/wikimedia/smash-pig/PaymentProviders/PayPal/Job.php
index 6e8816f..ab64a33 100644
--- a/wikimedia/smash-pig/PaymentProviders/PayPal/Job.php
+++ b/wikimedia/smash-pig/PaymentProviders/PayPal/Job.php
@@ -78,6 +78,8 @@
                // FIXME random document formats
                if ( substr( $txn_type, 0, 7 ) === 'subscr_' ) {
                        $log_id = "subscr_id:{$request['subscr_id']}";
+               } elseif ( substr( $txn_type, 0, 10 ) === 'recurring_'  ) {
+                       $log_id = 
"recurring_payment_id:{$request['recurring_payment_id']}";
                } else {
                        $log_id = "txn_id:{$request['txn_id']}";
                }
diff --git a/wikimedia/smash-pig/PaymentProviders/PayPal/RefundMessage.php 
b/wikimedia/smash-pig/PaymentProviders/PayPal/RefundMessage.php
index cbac123..98227a6 100644
--- a/wikimedia/smash-pig/PaymentProviders/PayPal/RefundMessage.php
+++ b/wikimedia/smash-pig/PaymentProviders/PayPal/RefundMessage.php
@@ -13,6 +13,14 @@
                } else {
                        $message['type'] = 'refund';
                }
-               $message['gateway'] = 'paypal';
+
+               // Express checkout puts a description in transaction_subject, 
Legacy puts a contribution
+               // tracking ID there. Chargebacks don't set the field at all.
+               if ( isset( $ipnMessage['transaction_subject'] ) && 
!is_numeric( $ipnMessage['transaction_subject'] ) ) {
+                       $message['gateway'] = 'paypal_ec';
+               } else {
+                       $message['gateway'] = 'paypal';
+               }
+
        }
 }
diff --git 
a/wikimedia/smash-pig/PaymentProviders/PayPal/Tests/Data/recurring_payment_profile_created.json
 
b/wikimedia/smash-pig/PaymentProviders/PayPal/Tests/Data/recurring_payment_profile_created.json
new file mode 100644
index 0000000..1cd1c71
--- /dev/null
+++ 
b/wikimedia/smash-pig/PaymentProviders/PayPal/Tests/Data/recurring_payment_profile_created.json
@@ -0,0 +1,30 @@
+{
+  "payment_cycle": "Monthly",
+  "txn_type": "recurring_payment_profile_created",
+  "last_name": "Fowl",
+  "next_payment_date": "03:00:00 May 18, 2017 PDT",
+  "residence_country": "US",
+  "initial_payment_amount": "0",
+  "rp_invoice_id": "47017286",
+  "currency_code": "JPY",
+  "time_created": "09:45:28 Apr 18, 2017 PDT",
+  "verify_sign": "ATZo1sTL1YpCR8SD-CzFolXviWIiAYV78oZbytx6QLNuI3z-KS8wKLqC",
+  "period_type": " Regular",
+  "payer_status": "unverified",
+  "tax": "0",
+  "payer_email": "do...@generous.net",
+  "first_name": "Fezziwig",
+  "receiver_email": "recei...@organization.org",
+  "payer_id": "8R297FE87CD8S",
+  "product_type": "1",
+  "shipping": "0",
+  "amount_per_cycle": "140",
+  "profile_status": "Active",
+  "charset": "UTF-8",
+  "notify_version": "3.8",
+  "amount": "140",
+  "outstanding_balance": "0",
+  "recurring_payment_id": "I-88J1M3DLSF0",
+  "product_name": "Monthly donation to the Wikimedia Foundation",
+  "ipn_track_id": "8999c084zz0f2"
+}
diff --git 
a/wikimedia/smash-pig/PaymentProviders/PayPal/Tests/Data/recurring_payment_profile_created_transformed.json
 
b/wikimedia/smash-pig/PaymentProviders/PayPal/Tests/Data/recurring_payment_profile_created_transformed.json
new file mode 100644
index 0000000..890f7dd
--- /dev/null
+++ 
b/wikimedia/smash-pig/PaymentProviders/PayPal/Tests/Data/recurring_payment_profile_created_transformed.json
@@ -0,0 +1,21 @@
+{
+  "subscr_id": "I-88J1M3DLSF0",
+  "txn_type": "subscr_signup",
+  "contribution_tracking_id": "47017286",
+  "order_id": "47017286",
+  "email": "do...@generous.net",
+  "first_name": "Fezziwig",
+  "middle_name": "",
+  "last_name": "Fowl",
+  "frequency_interval": "1",
+  "frequency_unit": "month",
+  "installments": 0,
+  "create_date": 1492533928,
+  "start_date": 1492533928,
+  "date": 1492533928,
+  "gateway": "paypal_ec",
+  "recurring": "1",
+  "source_name": "SmashPig",
+  "source_type": "listener",
+  "source_version": "unknown"
+}
diff --git 
a/wikimedia/smash-pig/PaymentProviders/PayPal/Tests/Data/refund_ec.json 
b/wikimedia/smash-pig/PaymentProviders/PayPal/Tests/Data/refund_ec.json
new file mode 100644
index 0000000..03b6048
--- /dev/null
+++ b/wikimedia/smash-pig/PaymentProviders/PayPal/Tests/Data/refund_ec.json
@@ -0,0 +1,37 @@
+{
+  "mc_gross": "-150",
+  "invoice": "46239229.0",
+  "protection_eligibility": "Ineligible",
+  "payer_id": "RWASDASJ2AS3A",
+  "payment_date": "09:34:59 Mar 22, 2017 PDT",
+  "payment_status": "Refunded",
+  "charset": "UTF-8",
+  "first_name": "Testy",
+  "mc_fee": "-43",
+  "notify_version": "3.8",
+  "reason_code": "refund",
+  "custom": "46239229",
+  "business": "gi...@takers.org",
+  "verify_sign": "Ar65LQ8D4i5231dnJnwTy8lT8UaGAoJGWSH0c1M93d3B86D4ZGVpax3T",
+  "payer_email": "do...@generous.net",
+  "parent_txn_id": "1V551844CE5526421",
+  "txn_id": "3HD08833MR473623T",
+  "payment_type": "instant",
+  "last_name": "McTesterson",
+  "receiver_email": "gi...@takers.org",
+  "payment_fee": "",
+  "shipping_discount": "0",
+  "receiver_id": "TWDK67ASD2XXY",
+  "insurance_amount": "0",
+  "item_name": "Donation to the Wikimedia Foundation",
+  "discount": "0",
+  "mc_currency": "JPY",
+  "item_number": "",
+  "residence_country": "US",
+  "handling_amount": "0",
+  "shipping_method": "Default",
+  "transaction_subject": "Donation to the Wikimedia Foundation",
+  "payment_gross": "",
+  "shipping": "0",
+  "ipn_track_id": "4e93f423dd88b"
+}
diff --git 
a/wikimedia/smash-pig/PaymentProviders/PayPal/Tests/Data/refund_ec_transformed.json
 
b/wikimedia/smash-pig/PaymentProviders/PayPal/Tests/Data/refund_ec_transformed.json
new file mode 100644
index 0000000..06cfd66
--- /dev/null
+++ 
b/wikimedia/smash-pig/PaymentProviders/PayPal/Tests/Data/refund_ec_transformed.json
@@ -0,0 +1,20 @@
+{
+  "date": 1490200499,
+  "gateway_parent_id": "1V551844CE5526421",
+  "gateway_txn_id": "3HD08833MR473623T",
+  "currency": "JPY",
+  "type": "refund",
+  "contribution_tracking_id": "46239229",
+  "email": "do...@generous.net",
+  "first_name": "Testy",
+  "last_name": "McTesterson",
+  "gross": "-150",
+  "fee": "-43",
+  "order_id": "46239229",
+  "gateway_refund_id": "3HD08833MR473623T",
+  "gross_currency": "JPY",
+  "gateway": "paypal_ec",
+  "source_name": "SmashPig",
+  "source_type": "listener",
+  "source_version": "unknown"
+}
diff --git 
a/wikimedia/smash-pig/PaymentProviders/PayPal/Tests/Data/refund_recurring_ec.json
 
b/wikimedia/smash-pig/PaymentProviders/PayPal/Tests/Data/refund_recurring_ec.json
new file mode 100644
index 0000000..41f7e78
--- /dev/null
+++ 
b/wikimedia/smash-pig/PaymentProviders/PayPal/Tests/Data/refund_recurring_ec.json
@@ -0,0 +1,42 @@
+{
+  "mc_gross": "-150",
+  "period_type": " Regular",
+  "outstanding_balance": "0",
+  "next_payment_date": "N\/A",
+  "protection_eligibility": "Ineligible",
+  "payment_cycle": "Monthly",
+  "payer_id": "RWASDASJ2AS3A",
+  "payment_date": "09:33:51 Mar 22, 2017 PDT",
+  "payment_status": "Refunded",
+  "product_name": "Monthly donation to the Wikimedia Foundation",
+  "charset": "UTF-8",
+  "rp_invoice_id": "45931681",
+  "recurring_payment_id": "I-DD1FNAAAUU22",
+  "first_name": "Testy",
+  "mc_fee": "-43",
+  "notify_version": "3.8",
+  "amount_per_cycle": "150",
+  "reason_code": "refund",
+  "currency_code": "JPY",
+  "business": "gi...@takers.org",
+  "verify_sign": "APvissTSNYxEsF2tvyvfCnTn10fsA3zfe8wcXg8--8099IMv8ObkEkCi",
+  "payer_email": "do...@generous.net",
+  "parent_txn_id": "4GV70894MM323713P",
+  "initial_payment_amount": "0",
+  "profile_status": "Cancelled",
+  "amount": "150",
+  "txn_id": "4CX17568KP793000L",
+  "payment_type": "instant",
+  "last_name": "McTesterson",
+  "receiver_email": "gi...@takers.org",
+  "payment_fee": "",
+  "receiver_id": "TWDK67ASD2XXY",
+  "mc_currency": "JPY",
+  "residence_country": "US",
+  "transaction_subject": "Monthly donation to the Wikimedia Foundation",
+  "payment_gross": "",
+  "shipping": "0",
+  "product_type": "1",
+  "time_created": "16:54:13 Feb 01, 2017 PST",
+  "ipn_track_id": "d86d241a67ab"
+}
\ No newline at end of file
diff --git 
a/wikimedia/smash-pig/PaymentProviders/PayPal/Tests/Data/refund_recurring_ec_transformed.json
 
b/wikimedia/smash-pig/PaymentProviders/PayPal/Tests/Data/refund_recurring_ec_transformed.json
new file mode 100644
index 0000000..3735881
--- /dev/null
+++ 
b/wikimedia/smash-pig/PaymentProviders/PayPal/Tests/Data/refund_recurring_ec_transformed.json
@@ -0,0 +1,21 @@
+{
+  "date": 1490200431,
+  "gateway_parent_id": "4GV70894MM323713P",
+  "gateway_txn_id": "4CX17568KP793000L",
+  "currency": "JPY",
+  "type": "refund",
+  "contribution_tracking_id": "45931681",
+  "email": "do...@generous.net",
+  "first_name": "Testy",
+  "last_name": "McTesterson",
+  "gross": "-150",
+  "fee": "-43",
+  "order_id": "45931681",
+  "gateway_refund_id": "4CX17568KP793000L",
+  "gross_currency": "JPY",
+  "gateway": "paypal_ec",
+  "subscr_id": "I-DD1FNAAAUU22",
+  "source_name": "SmashPig",
+  "source_type": "listener",
+  "source_version": "unknown"
+}
diff --git a/wikimedia/smash-pig/PaymentProviders/PayPal/Tests/config_test.yaml 
b/wikimedia/smash-pig/PaymentProviders/PayPal/Tests/config_test.yaml
index 9ba9920..657933e 100644
--- a/wikimedia/smash-pig/PaymentProviders/PayPal/Tests/config_test.yaml
+++ b/wikimedia/smash-pig/PaymentProviders/PayPal/Tests/config_test.yaml
@@ -24,7 +24,7 @@
                     connection_string: 'sqlite::memory:'
                     queue: recurring
 
-        refund-new:
+        refund:
             class: PHPQueue\Backend\PDO
             constructor-parameters:
                 -
diff --git 
a/wikimedia/smash-pig/PaymentProviders/PayPal/Tests/phpunit/CaptureIncomingMessageTest.php
 
b/wikimedia/smash-pig/PaymentProviders/PayPal/Tests/phpunit/CaptureIncomingMessageTest.php
index 1a64a11..f57aa9e 100644
--- 
a/wikimedia/smash-pig/PaymentProviders/PayPal/Tests/phpunit/CaptureIncomingMessageTest.php
+++ 
b/wikimedia/smash-pig/PaymentProviders/PayPal/Tests/phpunit/CaptureIncomingMessageTest.php
@@ -27,11 +27,14 @@
        static $message_data = array(
                'web_accept.json' => 'donations',
                'express_checkout.json' => 'donations',
+               'recurring_payment_profile_created.json' => 'recurring',
                'subscr_signup.json' => 'recurring',
                'subscr_payment.json' => 'recurring',
                'recurring_payment.json' => 'recurring',
-               'refund.json' => 'refund-new',
-               'chargeback_settlement.json' => 'refund-new',
+               'refund.json' => 'refund',
+               'refund_ec.json' => 'refund',
+               'refund_recurring_ec.json' => 'refund',
+               'chargeback_settlement.json' => 'refund',
                // this should not actually get written to
                // TODO 'new_case.json' => 'no-op',
        );
diff --git a/wikimedia/smash-pig/SmashPig.yaml 
b/wikimedia/smash-pig/SmashPig.yaml
index ac7159b..019294a 100644
--- a/wikimedia/smash-pig/SmashPig.yaml
+++ b/wikimedia/smash-pig/SmashPig.yaml
@@ -50,12 +50,6 @@
                     queue: recurring
 
         refund:
-            class: SmashPig\Core\DataStores\MultiQueueWriter
-            constructor-parameters:
-                -
-                    - refund-new
-
-        refund-new:
             class: PHPQueue\Backend\Predis
             constructor-parameters:
                 -
@@ -432,7 +426,7 @@
 
         refund:
             class: SmashPig\PaymentProviders\PayPal\RefundMessage
-            queue: refund-new # FIXME make the -new go away
+            queue: refund
             txn_types:
                 - adjustment
                 - refund
diff --git a/wikimedia/smash-pig/composer.json 
b/wikimedia/smash-pig/composer.json
index 85b7ee2..8b47d11 100644
--- a/wikimedia/smash-pig/composer.json
+++ b/wikimedia/smash-pig/composer.json
@@ -50,10 +50,6 @@
     },
     "repositories": [
         {
-            "type": "vcs",
-            "url": 
"https://gerrit.wikimedia.org/r/p/wikimedia/fundraising/php-queue.git";
-        },
-        {
             "type": "git",
             "url": "https://github.com/ejegg/login-and-pay-with-amazon-sdk-php";
         }
diff --git a/wikimedia/smash-pig/composer.lock 
b/wikimedia/smash-pig/composer.lock
index fb523f3..9555a05 100644
--- a/wikimedia/smash-pig/composer.lock
+++ b/wikimedia/smash-pig/composer.lock
@@ -4,8 +4,8 @@
         "Read more about it at 
https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file";,
         "This file is @generated automatically"
     ],
-    "hash": "ec39d762470b5844acb8b7cc5e9fa91e",
-    "content-hash": "f603529753b80b4b5ed3b7ff87d6d176",
+    "hash": "6c8507e66b7c74d4ba3a5d17be72b11a",
+    "content-hash": "c773f5366be4497f7a4678ac23b526d1",
     "packages": [
         {
             "name": "amzn/login-and-pay-with-amazon-sdk-php",
@@ -92,8 +92,14 @@
             "version": "dev-master",
             "source": {
                 "type": "git",
-                "url": 
"https://gerrit.wikimedia.org/r/p/wikimedia/fundraising/php-queue.git";,
-                "reference": "d56c5bd69dad595f2e00a3e10c851736b1feb57b"
+                "url": "https://github.com/CoderKungfu/php-queue.git";,
+                "reference": "dd8412f105632d31cdd77933ec40a08640752c99"
+            },
+            "dist": {
+                "type": "zip",
+                "url": 
"https://api.github.com/repos/CoderKungfu/php-queue/zipball/dd8412f105632d31cdd77933ec40a08640752c99";,
+                "reference": "dd8412f105632d31cdd77933ec40a08640752c99",
+                "shasum": ""
             },
             "require": {
                 "clio/clio": "0.1.*",
@@ -101,15 +107,19 @@
                 "php": ">=5.3.0"
             },
             "require-dev": {
-                "jakub-onderka/php-parallel-lint": "0.9",
-                "phpunit/phpunit": "4.4.*"
+                "amazonwebservices/aws-sdk-for-php": "dev-master",
+                "aws/aws-sdk-php": "dev-master",
+                "ext-memcache": "*",
+                "iron-io/iron_mq": "dev-master",
+                "microsoft/windowsazure": "dev-master",
+                "mrpoundsign/pheanstalk-5.3": "dev-master",
+                "predis/predis": "1.*"
             },
             "suggest": {
                 "Respect/Rest": "For a REST server to post job data",
                 "amazonwebservices/aws-sdk-for-php": "For AWS SQS backend 
support (legacy version)",
                 "aws/aws-sdk-php": "For AWS SQS backend support",
                 "clio/clio": "Support for daemonizing PHP CLI runner",
-                "ext-memcache": "*",
                 "fusesource/stomp-php": "For the STOMP backend",
                 "iron-io/iron_mq": "For IronMQ backend support",
                 "microsoft/windowsazure": "For Windows Azure Service Bus 
backend support",
@@ -128,12 +138,7 @@
                     "PHPQueue": "src/"
                 }
             },
-            "scripts": {
-                "test": [
-                    "parallel-lint . --exclude vendor",
-                    "phpunit"
-                ]
-            },
+            "notification-url": "https://packagist.org/downloads/";,
             "license": [
                 "MIT"
             ],
@@ -149,7 +154,7 @@
                 "queue",
                 "transaction"
             ],
-            "time": "2017-01-04 21:01:15"
+            "time": "2017-04-17 14:11:55"
         },
         {
             "name": "ircmaxell/password-compat",

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

Gerrit-MessageType: merged
Gerrit-Change-Id: Ibb1365c1e214b6b368239e1124abe841eaaad014
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/DonationInterface/vendor
Gerrit-Branch: master
Gerrit-Owner: Ejegg <eeggles...@wikimedia.org>
Gerrit-Reviewer: Ejegg <eeggles...@wikimedia.org>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to