diff --git a/extension/CRM/Banking/Helpers/Lock.php b/extension/CRM/Banking/Helpers/Lock.php new file mode 100644 index 00000000..574da286 --- /dev/null +++ b/extension/CRM/Banking/Helpers/Lock.php @@ -0,0 +1,36 @@ +isAcquired() before use + */ +function banking_helper_getLock($type, $id) { + if ($type=='tx') { + $timeout = 7.0; // TODO: do we need a setting here? + return new CRM_Core_Lock('org.project60.banking.tx'.'-'.$id, $timeout); + } elseif ($type=='txbatch') { + $timeout = 600.0; // 10mins, TODO: do we need a setting here? + return new CRM_Core_Lock('org.project60.banking.txbatch'.'-'.$id, $timeout); + } else { + error_log("org.project60.banking - Lock of type '$type' not known."); + return NULL; + } +} diff --git a/extension/CRM/Banking/Matcher/Engine.php b/extension/CRM/Banking/Matcher/Engine.php index 294e7e4e..75ae4851 100755 --- a/extension/CRM/Banking/Matcher/Engine.php +++ b/extension/CRM/Banking/Matcher/Engine.php @@ -25,6 +25,7 @@ */ require_once 'CRM/Banking/Helpers/OptionValue.php'; +require_once 'CRM/Banking/Helpers/Lock.php'; class CRM_Banking_Matcher_Engine { @@ -90,12 +91,20 @@ private function initPlugins() { * This will destroy all records of the execution! */ public function match( CRM_Banking_BAO_BankTransaction $btx, $override_processed = FALSE ) { + $lock = banking_helper_getLock('tx', $btx->id); + if (!$lock->isAcquired()) { + error_log("org.project60.banking - couldn't acquire lock. Timeout is ".$lock->_timeout); + return false; + } + + error_log("matching ".$btx->id); if (!$override_processed) { // don't match already executed transactions... $processed_status_id = banking_helper_optionvalueid_by_groupname_and_name('civicrm_banking.bank_tx_status', 'Processed'); $ignored_status_id = banking_helper_optionvalueid_by_groupname_and_name('civicrm_banking.bank_tx_status', 'Ignored'); if ($btx->status_id == $processed_status_id || $btx->status_id == $ignored_status_id) { // will not match already executed transactions + $lock->release(); return true; } } @@ -114,11 +123,17 @@ public function match( CRM_Banking_BAO_BankTransaction $btx, $override_processed foreach ($plugins as $plugin) { // run matchers to generate suggestions $continue = $this->matchPlugin( $plugin, $context ); - if (!$continue) return true; + if (!$continue) { + $lock->release(); + return true; + } // check if we can execute the suggestion right aways $abort = $this->checkAutoExecute($plugin, $btx); - if ($abort) return false; + if ($abort) { + $lock->release(); + return false; + } } } } @@ -129,6 +144,8 @@ public function match( CRM_Banking_BAO_BankTransaction $btx, $override_processed $btx->status_id = $newStatus; $btx->setStatus($newStatus); + error_log("done matching ".$btx->id); + $lock->release(); return false; } @@ -143,8 +160,17 @@ protected function checkAutoExecute($plugin, $btx) { foreach ($suggestions as $suggestion) { if ($suggestion->getPluginID()==$plugin->getPluginID()) { if ($suggestion->getProbability() >= $plugin->autoExecute()) { + $lock = banking_helper_getLock('tx', $btx->id); + if (!$lock->isAcquired()) { + error_log("org.project60.banking - couldn't acquire lock. Timeout is ".$lock->_timeout); + continue; + } + $btx->saveSuggestions(); - return $suggestion->execute( $btx, $plugin ); + $result = $suggestion->execute( $btx, $plugin ); + + $lock->release(); + return $result; } } }