r104539 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r104538‎ | r104539 | r104540 >
Date:03:08, 29 November 2011
Author:khorn
Status:ok
Tags:
Comment:
More changes for the 'limbo' queue functionality.
Now, they should delete themselves neatly from the queue on a not-abnormal end to the credit card process.
Modified paths:
  • /trunk/extensions/DonationInterface/activemq_stomp/activemq_stomp.php (modified) (history)
  • /trunk/extensions/DonationInterface/gateway_common/gateway.adapter.php (modified) (history)
  • /trunk/extensions/DonationInterface/globalcollect_gateway/globalcollect.adapter.php (modified) (history)

Diff [purge]

Index: trunk/extensions/DonationInterface/globalcollect_gateway/globalcollect.adapter.php
@@ -1085,6 +1085,7 @@
10861086 $cancelflag = false; //this will denote the thing we're trying to do with the donation attempt
10871087 $problemflag = false; //this will get set to true, if we can't continue and need to give up and just log the hell out of it.
10881088 $problemmessage = ''; //to be used in conjunction with the flag.
 1089+ $deletelimbomessageflag = false; //this tells us if we should delete this transaction's limbo queue message or not.
10891090
10901091
10911092 if ( $post_status_check ){
@@ -1131,11 +1132,13 @@
11321133 switch ( $order_status_results ){
11331134 case 'failed' :
11341135 case 'revised' :
 1136+ $deletelimbomessageflag = true;
11351137 $cancelflag = true; //makes sure we don't try to confirm.
11361138 break;
11371139 case 'complete' :
11381140 $problemflag = true; //nothing to be done.
11391141 $problemmessage = "GET_ORDERSTATUS reports that the payment is already complete.";
 1142+ $deletelimbomessageflag = true;
11401143 break;
11411144 }
11421145 }
@@ -1167,6 +1170,7 @@
11681171 $this->setTransactionResult( "Original Response Status (pre-SET_PAYMENT): " . $original_status_code, 'txn_message' );
11691172 $this->runPostProcessHooks(); //stomp is in here
11701173 $this->unsetAllSessionData();
 1174+ $deletelimbomessageflag = true;
11711175 } else {
11721176 $problemflag = true;
11731177 $problemmessage = "SET_PAYMENT couldn't communicate properly!";
@@ -1178,17 +1182,36 @@
11791183 if ( isset( $final['status'] ) && $final['status'] === true ) {
11801184 $this->setTransactionWMFStatus( 'failed' );
11811185 $this->unsetAllSessionData();
 1186+ $deletelimbomessageflag = true;
11821187 } else {
11831188 $problemflag = true;
11841189 $problemmessage = "CANCEL_PAYMENT couldn't communicate properly!";
11851190 }
11861191 }
1187 - //No else. We can't be in here if we've had problems, so the
1188 - //GET_STATUS must have told us no. No action required (in fact,
1189 - //GC will complain if we try to can something at this point).
 1192+ //No else. We can't be in here if we've had problems, so the
 1193+ //GET_STATUS must have told us no. No action required (in fact,
 1194+ //GC will complain if we try to can something at this point).
11901195 }
11911196 }
11921197
 1198+ if ( $deletelimbomessageflag ) {
 1199+ //ack the message out of the limbo queue.
 1200+
 1201+ //TODO: Test this in a batch situation. I have reason to suspect that the selectors won't work if the stomp connection isn't being reset properly.
 1202+ $limbo_messages = stompFetchMessages( 'limbo', "JMSCorrelationID = '" . $this->getCorrelationID() . "'" );
 1203+ $msgCount = count($limbo_messages);
 1204+ if ($msgCount){
 1205+ stompAckMessages($limbo_messages);
 1206+ if ($msgCount > 1){
 1207+ self::log($this->getData_Raw( 'contribution_tracking_id' ) . ':' . $this->getData_Raw( 'order_id' ) . " - Deleted $msgCount limbo messages.");
 1208+ }
 1209+ } else {
 1210+ self::log($this->getData_Raw( 'contribution_tracking_id' ) . ':' . $this->getData_Raw( 'order_id' ) . " - No limbo messages found.");
 1211+ }
 1212+
 1213+ closeDIStompConnection();
 1214+ }
 1215+
11931216 if ( $problemflag ){
11941217 //we have probably had a communication problem that could mean stranded payments.
11951218 $problemmessage = $this->getData_Raw( 'contribution_tracking_id' ) . ':' . $this->getData_Raw( 'order_id' ) . ' ' . $problemmessage;
@@ -1286,8 +1309,6 @@
12871310
12881311 $transaction = $this->getCurrentTransaction();
12891312
1290 - $this->getTransactionStatus();
1291 -
12921313 switch ( $transaction ) {
12931314 case 'INSERT_ORDERWITHPAYMENT':
12941315 $data = $this->xmlChildrenToArray( $response, 'ROW' );
@@ -2015,9 +2036,19 @@
20162037 }
20172038 }
20182039
 2040+ /**
 2041+ * post-process function for INSERT_ORDERWITHPAYMENT.
 2042+ * This gets called by executeIfFunctionExists, in do_transaction.
 2043+ */
20192044 protected function post_process_insert_orderwithpayment(){
20202045 //yeah, we absolutely want to do this for every one of these.
2021 - $this->doLimboStompTransaction();
 2046+ if ( $this->getTransactionStatus() === true ) {
 2047+ $data = $this->getTransactionData();
 2048+ $action = $this->findCodeAction( 'GET_ORDERSTATUS', 'STATUSID', $data['STATUSID'] );
 2049+ if ($action != 'failed'){
 2050+ $this->doLimboStompTransaction();
 2051+ }
 2052+ }
20222053 }
20232054
20242055 protected function pre_process_get_orderstatus(){
@@ -2059,39 +2090,4 @@
20602091 return $result;
20612092 }
20622093
2063 - /**
2064 - * Function that adds a stomp message to a special 'limbo' queue, for data
2065 - * that is either highly likely or completely guaranteed to be bifurcated by
2066 - * handing the ball to a third-party process.
2067 - * No need to override doStompTransaction in the parent class, as that has
2068 - * more logic than we need here. However, we may consider functionalizing
2069 - * some of the copied code in the parent class.
2070 - * @return void
2071 - */
2072 - protected function doLimboStompTransaction() {
2073 - if ( !$this->getGlobal( 'EnableStomp' ) ){
2074 - return;
2075 - }
2076 - $this->debugarray[] = "Attempting Limbo Stomp Transaction!";
2077 - $hook = 'gwLimboStomp';
2078 -
2079 - // send the thing.
2080 - $transaction = array(
2081 - 'response' => $this->getTransactionMessage(),
2082 - 'date' => time(),
2083 - 'gateway_txn_id' => $this->getTransactionGatewayTxnID(),
2084 - 'correlation-id' => 'GC-' . $this->getData_Raw('order_id'),
2085 - );
2086 -
2087 - $stomp_fields = $this->dataObj->getStompMessageFields();
2088 - foreach ($stomp_fields as $field){
2089 - $transaction[$field] = $this->getData_Raw($field);
2090 - }
2091 -
2092 - try {
2093 - wfRunHooks( $hook, array( $transaction ) );
2094 - } catch ( Exception $e ) {
2095 - self::log( "STOMP ERROR. Could not add message. " . $e->getMessage() , LOG_CRIT );
2096 - }
2097 - }
20982094 }
Index: trunk/extensions/DonationInterface/gateway_common/gateway.adapter.php
@@ -1512,7 +1512,52 @@
15131513 self::log( "STOMP ERROR. Could not add message. " . $e->getMessage() , LOG_CRIT );
15141514 }
15151515 }
 1516+
 1517+
 1518+ /**
 1519+ * Function that adds a stomp message to a special 'limbo' queue, for data
 1520+ * that is either highly likely or completely guaranteed to be bifurcated by
 1521+ * handing the ball to a third-party process.
 1522+ * TODO: Functionalize some of the code copied from doStompTransaction.
 1523+ * @return null
 1524+ */
 1525+ protected function doLimboStompTransaction() {
 1526+ if ( !$this->getGlobal( 'EnableStomp' ) ){
 1527+ return;
 1528+ }
 1529+ $this->debugarray[] = "Attempting Limbo Stomp Transaction!";
 1530+ $hook = 'gwLimboStomp';
15161531
 1532+ $stomp_fields = $this->dataObj->getStompMessageFields();
 1533+
 1534+ $transaction = array(
 1535+ 'response' => $this->getTransactionMessage(),
 1536+ 'date' => time(),
 1537+ 'gateway_txn_id' => $this->getTransactionGatewayTxnID(),
 1538+ 'correlation-id' => $this->getCorrelationID(),
 1539+ 'payment_method' => $this->getData_Raw('payment_method')
 1540+ );
 1541+
 1542+ $raw_data = array();
 1543+ foreach ($stomp_fields as $field){
 1544+ if (!isset($transaction[$field])){
 1545+ $raw_data[$field] = $this->getData_Raw($field);
 1546+ }
 1547+ }
 1548+
 1549+ $transaction = array_merge($transaction, $raw_data);
 1550+
 1551+ try {
 1552+ wfRunHooks( $hook, array( $transaction ) );
 1553+ } catch ( Exception $e ) {
 1554+ self::log( "STOMP ERROR. Could not add message. " . $e->getMessage() , LOG_CRIT );
 1555+ }
 1556+ }
 1557+
 1558+ protected function getCorrelationID(){
 1559+ return $this->getIdentifier() . '-' . $this->getData_Raw('order_id');
 1560+ }
 1561+
15171562 function smooshVarsForStaging() {
15181563
15191564 foreach ( $this->staged_vars as $field ) {
Index: trunk/extensions/DonationInterface/activemq_stomp/activemq_stomp.php
@@ -142,9 +142,15 @@
143143
144144 // connect
145145 $con->connect();
 146+
 147+ $properties = array(
 148+ 'persistent' => 'true',
 149+ 'correlation-id' => $transaction['correlation-id'],
 150+ 'payment_method' => $transaction['payment_method']
 151+ );
146152
147153 // send a message to the queue
148 - $result = $con->send( "/queue/$queueName", $message, array( 'persistent' => 'true', 'correlation-id' => $transaction['correlation-id'] ) );
 154+ $result = $con->send( "/queue/$queueName", $message, $properties );
149155
150156 if ( !$result ) {
151157 wfDebugLog( 'activemq_stomp', 'Send to Q failed for this message: ' . $message );
@@ -218,3 +224,86 @@
219225
220226 return $message;
221227 }
 228+
 229+/**
 230+ * Fetches all the messages in a queue that match the supplies selector.
 231+ * Limiting to a completely arbitrary 50, just in case something goes amiss somewhere.
 232+ * @param string $queue The target queue from which we would like to fetch things.
 233+ * To simplify things, specify either 'verified', 'pending', or 'limbo'.
 234+ * @param string $selector Could be anything that STOMP will regard as a valid selector. For our purposes, we will probably do things like:
 235+ * $selector = "JMSCorrelationID = 'globalcollect-6214814668'", or
 236+ * $selector = "payment_method = 'cc'";
 237+ * @param int $limit The maximum number of messages we would like to pull off of the queue at one time.
 238+ * @return array an array of stomp messages, with a count of up to $limit.
 239+ */
 240+function stompFetchMessages( $queue, $selector = null, $limit = 50 ){
 241+ global $wgStompQueueName, $wgPendingStompQueueName, $wgLimboStompQueueName;
 242+
 243+ switch($queue){
 244+ case 'pending':
 245+ $queue = $wgPendingStompQueueName;
 246+ break;
 247+ case 'limbo':
 248+ $queue = $wgLimboStompQueueName;
 249+ break;
 250+ case 'verified':
 251+ default:
 252+ $queue = $wgStompQueueName;
 253+ break;
 254+ }
 255+
 256+ $stomp = getDIStompConnection();
 257+
 258+ $properties = array( 'ack' => 'client' );
 259+ if (!is_null($selector)){
 260+ $properties['selector'] = $selector;
 261+ }
 262+
 263+ $returned = $stomp->subscribe('/queue/' . $queue, $properties);
 264+ $message = $stomp->readFrame();
 265+
 266+ $return = array();
 267+
 268+ while ( !empty( $message ) && count( $return ) < $limit ) {
 269+ $return[] = $message;
 270+ $message = $stomp->readFrame();
 271+ }
 272+
 273+ return $return;
 274+}
 275+
 276+
 277+/**
 278+ * Ack all of the messages in the array, thereby removing them from the queue.
 279+ * @param type $messages
 280+ */
 281+function stompAckMessages( $messages = array() ){
 282+ $stomp = getDIStompConnection();
 283+ foreach ($messages as $message){
 284+ if (!array_key_exists('redelivered', $message->headers)) {
 285+ $message->headers['redelivered'] = 'true';
 286+ }
 287+ $result = $stomp->ack($message);
 288+ }
 289+}
 290+
 291+function getDIStompConnection( $renew = false ){
 292+ global $wgStompServer;
 293+ static $conn = null;
 294+ if ( $conn === null || !$conn->isConnected() || $renew ) {
 295+ if ( $conn !== null && $conn->isConnected() ){
 296+ $conn->disconnect(); //just to be safe.
 297+ }
 298+ // make a connection
 299+ require_once( "Stomp.php" );
 300+ $conn = new Stomp( $wgStompServer );
 301+ // connect
 302+ $conn->connect();
 303+ }
 304+ return $conn;
 305+}
 306+
 307+function closeDIStompConnection(){
 308+ $conn = getDIStompConnection();
 309+ $conn->disconnect();
 310+}
\ No newline at end of file

Follow-up revisions

RevisionCommit summaryAuthorDate
r104540r104539...khorn03:15, 29 November 2011
r104588r104503, r104539...khorn20:38, 29 November 2011
r104648followup r104503, r104539, r104588...khorn02:54, 30 November 2011
r104791Another round of preparatory limbo stomp changes....khorn23:45, 30 November 2011
r105350MFT r104225, r104471, r104503, r104539, r104588, r104600, r104607, r104648, ...khorn21:12, 6 December 2011
r105351MFT r104225, r104471, r104503, r104539, r104588, r104600, r104607, r104648, ...khorn21:12, 6 December 2011
r105620MFT r104539, r105534, r105584, r105593, r105594, r105600, r105611awjrichards23:56, 8 December 2011

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r104503Establishes a 'limbo' queue for data that GlobalCollect is either extremely l...khorn23:12, 28 November 2011

Status & tagging log