バージョン選択

フォーラム

メニュー

オンライン状況

67 人のユーザが現在オンラインです。 (54 人のユーザが フォーラム を参照しています。)
登録ユーザ: 0
ゲスト: 67
もっと...

サイト内検索

バグ報告 > その他 > 在庫戻し処理の重複

その他

新規スレッドを追加する

スレッド表示 | 新しいものから 前のトピック | 次のトピック | 下へ
投稿者 スレッド
maekawapis
投稿日時: 2014/9/23 20:23
対応状況: −−−
新米
登録日: 2014/9/11
居住地:
投稿: 6
Re: 在庫戻し処理の重複【別対策案】
遅くなりましたが、別の対処法が見つかりました。

cronで行おうとしていましたが、
checkDbMyPendignOrderやcheckSessionPendingOrderがセッションを使っているため、
cronから触るのはよくないと考え、別の対処法を検討しました。

同タイミングだとselectで同じデータが2つ取れてしまうのが根本原因なので、ロックをかけるようにする方法です。

postgresであれば、FOR UPDATEをselect文に追記することで、行ロックが行えます。
※他DBにも同様の機能はあるかと思います。


$objQuery->setOption('FOR UPDATE');
各select
$objQuery->setOption('');


これでselect後にsleepを入れて恣意的に重複させても
後から入ったcheck*****PendignOrderは
先のトランザクションがcommitされるまで待たされ、
select結果として決済処理中のデータを取得できないようになります。

全ての影響は検証できていませんが、
みなさんのご意見伺いたいです。



以下、SC_Helper_Purchaseの最後の4メソッドです。


    /**
     * 決済処理中スタータスの受注データのキャンセル処理
     * @param $cancel_flg 決済処理中ステータスのロールバックをするか(true:する false:しない)  
     */
    public function cancelPendingOrder($cancel_flg)
    {
        if($cancel_flg == true){
            $this->checkDbAllPendingOrder();
            $this->checkDbMyPendignOrder();
            $this->checkSessionPendingOrder();
        }
    }
    
    /**
     * 決済処理中スタータスの全受注検索
     */
    public function checkDbAllPendingOrder()
    {
        $term = PENDING_ORDER_CANCEL_TIME;
        if (!SC_Utils_Ex::isBlank($term) && preg_match("/^[0-9]+$/", $term)) {
            $target_time = strtotime('-' . $term . ' sec');
            $objQuery =& SC_Query_Ex::getSingletonInstance();
            $arrVal = array(date('Y/m/d H:i:s',$target_time), ORDER_PENDING);
            $objQuery->begin();
            $objQuery->setOption('FOR UPDATE');
            $arrOrders = $objQuery->select('order_id', 'dtb_order', 'create_date <= ? and status = ? and del_flg = 0', $arrVal);
            $objQuery->setOption('');
            if (!SC_Utils_Ex::isBlank($arrOrders)) {
                //GC_Utils_Ex::gfPrintLog('checkDbAllPendingOrder detect order_id=' . print_r($arrOrders,true));
                //sleep(10);
                foreach ($arrOrders as $arrOrder) {
                    $order_id = $arrOrder['order_id'];
                    SC_Helper_Purchase_Ex::cancelOrder($order_id, ORDER_CANCEL, true);
                    GC_Utils_Ex::gfPrintLog('order cancel.(time expire) order_id=' . $order_id);
                }
            }
            //GC_Utils_Ex::gfPrintLog('checkDbAllPendingOrder done.');
            $objQuery->commit();
        }
    }

    public function checkDbMyPendignOrder()
    {
        $objCustomer = new SC_Customer_Ex();
        if ($objCustomer->isLoginSuccess(true)) {
            $customer_id = $objCustomer->getValue('customer_id');
            $objQuery =& SC_Query_Ex::getSingletonInstance();
            $arrVal = array($customer_id, ORDER_PENDING);
            $objQuery->setOrder('create_date desc');
            $objQuery->begin();
            $objQuery->setOption('FOR UPDATE');
            $arrOrders = $objQuery->select('order_id,create_date', 'dtb_order', 'customer_id = ? and status = ? and del_flg = 0', $arrVal);
            $objQuery->setOption('');
            if (!SC_Utils_Ex::isBlank($arrOrders)) {
                //GC_Utils_Ex::gfPrintLog('checkDbMyPendignOrder detect order_id=' . print_r($arrOrders,true));
                //sleep(10);
                foreach ($arrOrders as $key => $arrOrder) {
                    $order_id = $arrOrder['order_id'];
                    if ($key == 0) {
                        $objCartSess = new SC_CartSession_Ex();
                        $cartKeys = $objCartSess->getKeys();
                        $term = PENDING_ORDER_CANCEL_TIME;
                        if (preg_match("/^[0-9]+$/", $term)) {
                            $target_time = strtotime('-' . $term . ' sec');
                            $create_time = strtotime($arrOrder['create_date']);
                            if (SC_Utils_Ex::isBlank($cartKeys) && $target_time < $create_time) {
                                SC_Helper_Purchase_Ex::rollbackOrder($order_id, ORDER_CANCEL, true);
                                GC_Utils_Ex::gfPrintLog('order rollback.(my pending) order_id=' . $order_id);
                            } else {
                                SC_Helper_Purchase_Ex::cancelOrder($order_id, ORDER_CANCEL, true);
                                if ($target_time > $create_time) {
                                    GC_Utils_Ex::gfPrintLog('order cancel.(my pending and time expire) order_id=' . $order_id);
                                } else {
                                    GC_Utils_Ex::gfPrintLog('order cancel.(my pending and set cart) order_id=' . $order_id);
                                }
                            }
                        }
                    } else {
                        SC_Helper_Purchase_Ex::cancelOrder($order_id, ORDER_CANCEL, true);
                        GC_Utils_Ex::gfPrintLog('order cancel.(my old pending) order_id=' . $order_id);
                    }
                }
            }
            //GC_Utils_Ex::gfPrintLog('checkDbMyPendignOrder done.');
            $objQuery->commit();
        }
    }

    public function checkSessionPendingOrder()
    {
        if (!SC_Utils_Ex::isBlank($_SESSION['order_id'])) {
            $order_id = $_SESSION['order_id'];
            unset($_SESSION['order_id']);
            $objQuery =& SC_Query_Ex::getSingletonInstance();
            $objQuery->begin();
            $objQuery->setOption('FOR UPDATE');
            $arrOrder =  SC_Helper_Purchase_Ex::getOrder($order_id);
            $objQuery->setOption('');
            if ($arrOrder['status'] == ORDER_PENDING) {
                //GC_Utils_Ex::gfPrintLog('checkSessionPendingOrder detect order_id=' . print_r($arrOrder,true));
                //sleep(10);
                $objCartSess = new SC_CartSession_Ex();
                $cartKeys = $objCartSess->getKeys();
                if (SC_Utils_Ex::isBlank($cartKeys)) {
                    SC_Helper_Purchase_Ex::rollbackOrder($order_id, ORDER_CANCEL, true);
                    GC_Utils_Ex::gfPrintLog('order rollback.(session pending) order_id=' . $order_id);
                } else {
                    SC_Helper_Purchase_Ex::cancelOrder($order_id, ORDER_CANCEL, true);
                    GC_Utils_Ex::gfPrintLog('order rollback.(session pending and set card) order_id=' . $order_id);
                }
            }
            //GC_Utils_Ex::gfPrintLog('checkSessionPendingOrder done.');
            $objQuery->commit();
        }
    }
« 1 (2)
スレッド表示 | 新しいものから 前のトピック | 次のトピック | トップ


 



ログイン


EC-CUBE公式 Amazon Payプラグイン

統計情報

総メンバー数は88,859名です
総投稿数は109,996件です

投稿数ランキング

1
seasoft
7367
2
468
3217
3
AMUAMU
2712
4
nanasess
2313
5
umebius
2085
6
yuh
1819
7
h_tanaka
1646
8
red
1570
9
mcontact
1294
10
tsuji
958
11
fukap
907
12
shutta
835
13
tao_s
799
14 ramrun 789
15 karin 689
16 sumida 641
17
homan
633
18 DELIGHT 572
19
patapata
502
20
flealog
485


ネットショップの壺

EC-CUBEインテグレートパートナー

Copyright© EC-CUBE CO.,LTD. All Rights Reserved.