def update_user_recent_resource_visit_info(uid, resource_type, favor_type):
    """ update user recent resource visit info, @return True|False
    """
    errCode, kv_dict = model.get_online_user_resource_visitinfo(uid, [resource_type])
    if not is_valid_data(errCode, kv_dict, "online_user_resource_visitinfo", {"uid":uid, "resource_type":resource_type}):
        return False
    logger.debug("resource_type:%s, kv_dict:%s" % (resource_type, kv_dict))
    visit_info_proto = VisitInfo()
    try:
        if kv_dict:
            assert(resource_type in kv_dict)
            visit_info_proto.ParseFromString(kv_dict[resource_type])
            logger.debug("resource_visit info,resource_type:%s,visit_info:%s" % (resource_type, visit_info_proto))
    except:
        logger.error("bad ItemIdList from get_online_user_favor_item_list:uid:%s, resource_type:%s, exception:%s" % (uid, resource_type, traceback.format_exc()))
        return False
    #TODO:define constants outside
    if favor_type in ["click", "like"]:
        logger.info("update uid:%s, click_count:%s" % (uid, visit_info_proto.click_count))
        visit_info_proto.click_count += 1
    elif favor_type == "show":
        visit_info_proto.pv_count += 1
    else:
        logger.warn("ignore unknown type:%s" % favor_type)
        return False
    errCode = model.set_online_user_resource_visitinfo(uid, resource_type, visit_info_proto.SerializeToString())
    if not errCode:
        logger.warn("fail to update_user_recent_resource_visit_info, uid:%s, resource_type:%s" % (uid, resource_type))
    else:
        logger.info("successfully to update_user_recent_resource_visit_info, uid:%s, resource_type:%s" % (uid, resource_type))
    return errCode
 def fetch(self, logger):
     """update user info, return None"""
     uid = self.uid
     #offline_resource_visit_info
     try:
         errCode, kv_dict = model.get_offline_user_resource_visitinfo(uid, ResourceType.RESOURCE_TYPE_LIST)
         if not is_valid_data(errCode, kv_dict, "offline_user_resource_visitinfo", {"uid":uid, "resource_type_list":"..."}):
             pass
         for k, v in kv_dict.iteritems():
             self.offline_resource_visit_info[k] = VisitInfo()
             self.offline_resource_visit_info[k].ParseFromString(v)
     except:
         logger.error("bad offline_resource_visit_info:%s" % traceback.format_exc())
     #recent_resource_visit_info
     try:
         errCode, kv_dict = model.get_online_user_resource_visitinfo(uid, ResourceType.RESOURCE_TYPE_LIST)
         if not is_valid_data(errCode, kv_dict, "online_user_resource_visitinfo", {"uid":uid, "resource_type_list":"..."}):
             pass
         for k, v in kv_dict.iteritems():
             self.recent_resource_visit_info[k] = VisitInfo()
             self.recent_resource_visit_info[k].ParseFromString(v)
         #final_resource_visit_info
         self.final_resource_visit_info = UserInfo.merge_offline_recent_resource_visit_info(self.offline_resource_visit_info,
                 self.recent_resource_visit_info)
     except:
         logger.error("bad recent_resource_visit_info:%s" % traceback.format_exc())
         self.final_resource_visit_info = self.offline_resource_visit_info
     #pushed_item_id_list
     try:
         errCode, v = model.get_online_user_push_item_list(uid)
         if not is_valid_data(errCode, v, "online_user_push_item_list", {"uid":uid}):
             pass
         if v:
             item_id_list_proto = ItemIdList()
             item_id_list_proto.ParseFromString(v)
             self.recent_push_item_id_list = set()
             self.recent_push_item_id_list.update(item_id_list_proto.item_id)
     except:
         logger.error("bad pushed_item_id_list:%s" % traceback.format_exc())
     #pushed_feature_list
     try:
         errCode, v = model.get_online_user_feature_reason(uid)
         if not is_valid_data(errCode, v, "online_user_feature_reason", {"uid":uid}):
             pass
         if v:
             feature_list_proto = ItemFeatureList()
             feature_list_proto.ParseFromString(v)
             for u in feature_list_proto.feature:
                 self.recent_push_reason_info[u.feature_name] = u.weight
     except:
         logger.error("bad pushed_feature_list:%s" % traceback.format_exc())
     logger.debug("user_info:%s" % self)
     return None