예제 #1
0
 def trade(self, user_1, content_1, user_2, content_2):
     update_1 = utils.build_update_obj(content_2, neg=content_1)
     update_2 = utils.build_update_obj(content_1, neg=content_2)
     self.mongodb.portofolio.update({"user": user_1}, {"$inc": update_1},
                                    safe=True)
     self.mongodb.portofolio.update({"user": user_2}, {"$inc": update_2},
                                    safe=True)
    def trade(self, user1, content1, user2, content2): 
        trade_order = {}
        trade_order['user_1'] = user1
        trade_order['content_1'] = content1
        trade_order['user_2'] = user2
        trade_order['content_2'] = content2   
        credit_for_1 = utils.build_update_obj(content2)
        debit_for_1 = utils.build_update_obj(content1, sign=-1)
        credit_for_2 = utils.build_update_obj(content1, sign=1)
        debit_for_2 = utils.build_update_obj(content2, sign=-1)    
        check_1 = utils.build_check_obj(content1)
        check_2 = utils.build_check_obj(content2)
    
        # Insert the transaction in base
        trade_order['state'] = "running"
        t_id =  self.mongodb.transaction.insert(trade_order, safe=True)
    
        check_1.update({ "user":user1,  "debited" : { "$ne" : t_id}})
        check_2.update({ "user":user2,  "debited" : { "$ne" : t_id}})
    
        ## Try to apply all the debits 
        ret = self.mongodb.portofolio.update(check_1, { "$inc" : debit_for_1, "$push" : { "debited" : t_id} }, safe=True )
        if not ret['updatedExisting']:
            self.mongodb.transaction.update({"_id" : t_id}, {"$set" : {"state" : "failed" }})
            raise Exception()
        ret = self.mongodb.portofolio.update(check_2, { "$inc" : debit_for_2, "$push" : { "debited" : t_id } }, safe=True )
        if not ret['updatedExisting']:
            ## Rollback debit on 1 
            self.mongodb.portofolio.update({"user":user1 } , { "$inc":credit_for_2, "$pull" : { "debited" : t_id }}, safe=True)
            ## Notify failed transaction
            self.mongodb.transaction.update({"_id" : t_id}, {"$set" : {"state" : "failed" }}, safe=True)
            raise Exception() 

        # Notify Sucessfull debits. 
        self.mongodb.transaction.update({"_id" : t_id}, {"$set" : {"state" : "debited" }}, safe=True)
        if not ret['updatedExisting']:
             # Rollback
             ret = self.mongodb.portofolio.update({"user":user1 } , { "$inc":credit_for_2, "$pull" : { "debited" : t_id }}, safe=True)
             ret = self.mongodb.portofolio.update({"user":user2 } , { "$inc":credit_for_1, "$pull" : { "debited" : t_id }}, safe=True)
             self.mongodb.transaction.update({"_id" : t_id}, {"$set" : {"state" : "failed" }}, safe=True)
             raise Exception()

        # Apply all the credits    
        ret = self.mongodb.portofolio.update({"user": user1}, { "$inc" : credit_for_1,"$pull" : { "debited" : t_id }}, safe=True)
        if not ret['updatedExisting']:
            raise Exception()
        ret = self.mongodb.portofolio.update({"user": user2}, { "$inc" : credit_for_2,"$pull" : { "debited" : t_id }}, safe=True)
        if not ret['updatedExisting']:
            raise Exception()
        
        # Notify Sucessfull transaction. 
        self.mongodb.transaction.update({"_id" : t_id}, {"$set" : {"state" : "done" }}, safe=True)
        if not ret['updatedExisting']:
             raise Exception()        
    def trade(self, user_1, content_1, user_2, content_2):
        update_1 = utils.build_update_obj(content_2, neg=content_1)
        update_2 = utils.build_update_obj(content_1, neg=content_2)
        check_1 = build_check_obj(content_1)
        check_2 = build_check_obj(content_2)
        check_1.update({"user": user_1, "_locked": 1})
        check_2.update({"user": user_2, "_locked": 1})
        ## Acquire a lock on object.
        while True:
            t = time.time()
            elasped = t - 30
            # To lock an object, we set a _locked attributed and a _lock_time
            # The lock is considered to be  valid for only 30 seconds.
            # A expiring lock is necessary to protect from crash of this thread in mid-air.
            lock_check_expr = {"$or": [{"_locked": {"$ne": 1}}, {"$le": {"_lock_time": elasped}}]}
            ret = self.mongodb.portofolio.update(
                {"$and": [{"user": user_1}, lock_check_expr]}, {"$set": {"_locked": 1, "_lock_time": t}}, safe=True
            )
            if not ret["updatedExisting"]:
                # Unable to lock the object : retry
                # (A better implementation would check that the object actually exists in the database, and have some retry limit)
                time.sleep(0.5)
                continue
            ret = self.mongodb.portofolio.update(
                {"$and": [{"user": user_2}, lock_check_expr]}, {"$set": {"_locked": 1, "_lock_time": t}}, safe=True
            )
            if not ret["updatedExisting"]:
                # Release lock on 1
                self.mongodb.portofolio.update({"user": user_1, "_locked": 1}, {"$unset": {"_locked": 1}}, safe=True)
                time.sleep(0.5)
                continue
            break

        ## We perform atomically a check on availability and update on each objects, under the common lock
        ret = self.mongodb.portofolio.update(check_1, {"$inc": update_1}, safe=True)
        if not ret["updatedExisting"]:
            raise Exception()
        ret = self.mongodb.portofolio.update(check_2, {"$inc": update_2}, safe=True)
        if not ret["updatedExisting"]:
            raise Exception()
        ## Release the lock on objects
        self.mongodb.portofolio.update({"user": user_1, "_locked": 1}, {"$unset": {"_locked": 1}}, safe=True)
        self.mongodb.portofolio.update({"user": user_2, "_locked": 1}, {"$unset": {"_locked": 1}}, safe=True)
 def distribute(self, user, content):
     update_obj = utils.build_update_obj(content)
     ret = self.mongodb.portofolio.update({"user": user},
                                          {"$inc": update_obj},
                                          safe=True)
     if not ret['updatedExisting']:
         self.mongodb.portofolio.insert({
             "user": user,
             "content": content
         },
                                        safe=True)
    def trade(self, user_1, content_1, user_2, content_2):
        update_1 = utils.build_update_obj(content_2, neg=content_1)
        update_2 = utils.build_update_obj(content_1, neg=content_2)
        check_1 = build_check_obj(content_1)
        check_2 = build_check_obj(content_2)
        check_1.update({"user": user_1, "_locked": 1})
        check_2.update({"user": user_2, "_locked": 1})
        ## Acquire a lock on object.
        while True:
            t = time.time()
            elasped = t - 30
            # To lock an object, we set a _locked attributed and a _lock_time
            # The lock is considered to be  valid for only 30 seconds.
            # A expiring lock is necessary to protect from crash of this thread in mid-air.
            lock_check_expr = {
                '$or': [{
                    "_locked": {
                        "$ne": 1
                    }
                }, {
                    "$le": {
                        "_lock_time": elasped
                    }
                }]
            }
            ret = self.mongodb.portofolio.update(
                {"$and": [{
                    "user": user_1
                }, lock_check_expr]},
                {"$set": {
                    "_locked": 1,
                    "_lock_time": t
                }},
                safe=True)
            if not ret['updatedExisting']:
                # Unable to lock the object : retry
                # (A better implementation would check that the object actually exists in the database, and have some retry limit)
                time.sleep(0.5)
                continue
            ret = self.mongodb.portofolio.update(
                {"$and": [{
                    "user": user_2
                }, lock_check_expr]},
                {"$set": {
                    "_locked": 1,
                    "_lock_time": t
                }},
                safe=True)
            if not ret['updatedExisting']:
                # Release lock on 1
                self.mongodb.portofolio.update({
                    "user": user_1,
                    "_locked": 1
                }, {"$unset": {
                    "_locked": 1
                }},
                                               safe=True)
                time.sleep(0.5)
                continue
            break

        ## We perform atomically a check on availability and update on each objects, under the common lock
        ret = self.mongodb.portofolio.update(check_1, {"$inc": update_1},
                                             safe=True)
        if not ret['updatedExisting']:
            raise Exception()
        ret = self.mongodb.portofolio.update(check_2, {"$inc": update_2},
                                             safe=True)
        if not ret['updatedExisting']:
            raise Exception()
        ## Release the lock on objects
        self.mongodb.portofolio.update({
            "user": user_1,
            "_locked": 1
        }, {"$unset": {
            "_locked": 1
        }},
                                       safe=True)
        self.mongodb.portofolio.update({
            "user": user_2,
            "_locked": 1
        }, {"$unset": {
            "_locked": 1
        }},
                                       safe=True)
 def distribute(self, user, content):
     update_obj = utils.build_update_obj(content)
     ret = self.mongodb.portofolio.update({"user": user}, {"$inc": update_obj}, safe=True)
     if not ret["updatedExisting"]:
         self.mongodb.portofolio.insert({"user": user, "content": content}, safe=True)
 def trade(self, user_1, content_1, user_2, content_2):
     update_1 = utils.build_update_obj(content_2, neg=content_1)
     update_2 = utils.build_update_obj(content_1, neg=content_2)
     self.mongodb.portofolio.update({ "user":user_1 }, { "$inc" : update_1 }, safe=True )
     self.mongodb.portofolio.update({ "user":user_2 }, { "$inc" : update_2 }, safe=True )
예제 #8
0
    def trade(self, user1, content1, user2, content2):
        trade_order = {}
        trade_order['user_1'] = user1
        trade_order['content_1'] = content1
        trade_order['user_2'] = user2
        trade_order['content_2'] = content2
        credit_for_1 = utils.build_update_obj(content2)
        debit_for_1 = utils.build_update_obj(content1, sign=-1)
        credit_for_2 = utils.build_update_obj(content1, sign=1)
        debit_for_2 = utils.build_update_obj(content2, sign=-1)
        check_1 = utils.build_check_obj(content1)
        check_2 = utils.build_check_obj(content2)

        # Insert the transaction in base
        trade_order['state'] = "running"
        t_id = self.mongodb.transaction.insert(trade_order, safe=True)

        check_1.update({"user": user1, "debited": {"$ne": t_id}})
        check_2.update({"user": user2, "debited": {"$ne": t_id}})

        ## Try to apply all the debits
        ret = self.mongodb.portofolio.update(check_1, {
            "$inc": debit_for_1,
            "$push": {
                "debited": t_id
            }
        },
                                             safe=True)
        if not ret['updatedExisting']:
            self.mongodb.transaction.update({"_id": t_id},
                                            {"$set": {
                                                "state": "failed"
                                            }})
            raise Exception()
        ret = self.mongodb.portofolio.update(check_2, {
            "$inc": debit_for_2,
            "$push": {
                "debited": t_id
            }
        },
                                             safe=True)
        if not ret['updatedExisting']:
            ## Rollback debit on 1
            self.mongodb.portofolio.update({"user": user1}, {
                "$inc": credit_for_2,
                "$pull": {
                    "debited": t_id
                }
            },
                                           safe=True)
            ## Notify failed transaction
            self.mongodb.transaction.update({"_id": t_id},
                                            {"$set": {
                                                "state": "failed"
                                            }},
                                            safe=True)
            raise Exception()

        # Notify Sucessfull debits.
        self.mongodb.transaction.update({"_id": t_id},
                                        {"$set": {
                                            "state": "debited"
                                        }},
                                        safe=True)
        if not ret['updatedExisting']:
            # Rollback
            ret = self.mongodb.portofolio.update({"user": user1}, {
                "$inc": credit_for_2,
                "$pull": {
                    "debited": t_id
                }
            },
                                                 safe=True)
            ret = self.mongodb.portofolio.update({"user": user2}, {
                "$inc": credit_for_1,
                "$pull": {
                    "debited": t_id
                }
            },
                                                 safe=True)
            self.mongodb.transaction.update({"_id": t_id},
                                            {"$set": {
                                                "state": "failed"
                                            }},
                                            safe=True)
            raise Exception()

        # Apply all the credits
        ret = self.mongodb.portofolio.update({"user": user1}, {
            "$inc": credit_for_1,
            "$pull": {
                "debited": t_id
            }
        },
                                             safe=True)
        if not ret['updatedExisting']:
            raise Exception()
        ret = self.mongodb.portofolio.update({"user": user2}, {
            "$inc": credit_for_2,
            "$pull": {
                "debited": t_id
            }
        },
                                             safe=True)
        if not ret['updatedExisting']:
            raise Exception()

        # Notify Sucessfull transaction.
        self.mongodb.transaction.update({"_id": t_id},
                                        {"$set": {
                                            "state": "done"
                                        }},
                                        safe=True)
        if not ret['updatedExisting']:
            raise Exception()