def update_user_favor_item_id_list(uid, resource_type, item_id, favor_type):
    """ update user favor item id list, @return True|False
    """
    resource_type = ResourceType.get_resource_type(item_id)
    assert(resource_type)
    errCode, kv_dict = model.get_online_user_favor_item_list(uid, [resource_type])
    if not is_valid_data(errCode, kv_dict, "online_user_favor_item_list", {"uid":uid, "resource_type":resource_type}):
        return False
    logger.debug("resource_type:%s, kv_dict:%s" % (resource_type, kv_dict))
    item_id_list_proto = ItemIdList()
    try:
        if kv_dict:
            assert(resource_type in kv_dict)
            item_id_list_proto.ParseFromString(kv_dict[resource_type])
            logger.debug("favor item_id_list:%s" % item_id_list_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
    item_id_list_proto.item_id.append(item_id)
    limit_protobuf_repeated_scala_field_size(item_id_list_proto, "item_id", MAX_FAVOR_ITEM_LIST_COUNT_PER_PERSON)
    logger.debug("new item_id_list:%s" % item_id_list_proto)
    errCode = model.set_online_user_favor_item_list(uid, resource_type, item_id_list_proto.SerializeToString())
    if not errCode:
        logger.warn("fail to set_online_user_favor_item_list, uid:%s, resource_type:%s" % (uid, resource_type))
    else:
        logger.info("successfully to set_online_user_favor_item_list, uid:%s, resource_type:%s" % (uid, resource_type))
    return errCode
def get_item_list_by_item(user_info, resource_type, count):
    """ get item_list by item recommendation
        @return RecommendItemContainer
    """
    logger.debug("begin get_item_list_by_item")
    uid = user_info.uid
    result = RecommendItemContainer()
    #get favor item_id列表
    errCode, kv_dict = model.get_online_user_favor_item_list(uid, [resource_type])
    if not is_valid_data(errCode, kv_dict, "online_user_favor_item_list", {"uid":uid, "resource_type":resource_type}):
        return result
    if not kv_dict:
        return result
    assert(resource_type in kv_dict)
    try:
        item_id_list_proto = ItemIdList()
        item_id_list_proto.ParseFromString(kv_dict[resource_type])
        reason_list = [resource_type+ITEM_RECOMMEND_FEATURE_TYPE+v for  v in item_id_list_proto.item_id]
        item_id_list = []
        for v in item_id_list_proto.item_id:
            if not check_reason(user_info, resource_type+ITEM_RECOMMEND_FEATURE_TYPE+v):
                continue
            item_id_list.append(v)
        if not item_id_list:
            logger.info("all item id list have no item2item result:%s" % item_id_list)
            return result
        #@note: use latest item first
        item_id_list.reverse()
        #recommend by item id
        errCode, kv_dict = model.get_offline_item_recommend_item_list(item_id_list)
        if not is_valid_data(errCode, kv_dict, "offline_item_recommend_item_list", {"item_id_list":"..."}):
            return result
        if not kv_dict:
            for item_id in item_id_list:
                reason = resource_type + ITEM_RECOMMEND_FEATURE_TYPE + item_id
                ignore_reason(user_info, reason)
            return result
        for item_id in item_id_list:
            if result.size() >= count:
                break
            if item_id not in kv_dict:
                logger.info("no item2itemid list for id:%s" % item_id)
                ignore_reason(user_info, reason)
                continue
            k = item_id
            v = kv_dict[k]
            reason = resource_type + ITEM_RECOMMEND_FEATURE_TYPE + k
            item_id_list_proto = ItemIdList()
            item_id_list_proto.ParseFromString(v)
            filter_and_compose_recommend_item_list(user_info, reason, item_id_list_proto, result)
    except:
        logger.error("bad get_item_list_by_item:%s" % traceback.format_exc())
    return result