You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

优化Shopify Ruby脚本结构 提升GWP促销运行性能

Shopify购即赠(GWP)脚本性能优化方案

问题背景

我使用Shopify Scripts Editor中的Ruby语言实现购即赠(GWP)促销活动的安全管控,现有逻辑如下:

  • 检查客户是否为专业用户登录状态或未登录状态
  • 验证购物车是否达到最低消费金额
  • 确保购物车中仅保留1件赠品商品
  • 若结账时无对应折扣码或未满足GWP_SETTINGS设置的最低要求,自动移除赠品商品

目前脚本在生产环境频繁触发资源超限错误:脚本超出时间限制、脚本超出CPU限制,当前资源使用率为CPU: 5% | Memory: 8%,且每新增一个GWP促销配置项,资源占用会急剧上升。需要优化逻辑结构,降低订单处理及GWP验证时的内存与CPU消耗。

原脚本代码

cart = Input.cart

PRO_TAG = 'professional-tag'
has_pro_tag = cart.customer && cart.customer.tags.include?(PRO_TAG)

GWP_SETTINGS = [
    { 
        "variant_id" => 98989898989898,
        "discount_code" => "DISCOUNT_CODE_1",
        "minimum_requirement" => Money.new(cents: 50 * 100),
        "user_type" => "consumer"
    },
    { 
        "variant_id" => 97979797979797,
        "discount_code" => "DISCOUNT_CODE_1",
        "minimum_requirement" => Money.new(cents: 50 * 100),
        "user_type" => "consumer"
    },
    { 
        "variant_id" => 96969696969696,
        "discount_code" => "DISCOUNT_CODE_1",
        "minimum_requirement" => Money.new(cents: 50 * 100),
        "user_type" => "consumer"
    }
]

def remove_GWP(cart, variant_id)
  cart.line_items.each do |item|
    next if item.variant.id != variant_id
    index = cart.line_items.find_index(item)
    cart.line_items.delete_at(index)
  end
end

def ensure_only_one_GWP_is_added(cart, variant_id)
  cart.line_items.each do |item|
    next if item.variant.id != variant_id
    item.instance_variable_set(:@quantity, 1)
  end
end

GWP_SETTINGS.each do |gwp_item_settings|
    
    customer_has_discount = cart.discount_code && cart.discount_code.code == gwp_item_settings["discount_code"]
    customer_has_minimum = cart.subtotal_price >= gwp_item_settings["minimum_requirement"]
    gwp_is_for_professional = gwp_item_settings["user_type"] == "professional-tag"

    # 普通用户逻辑
    if customer_has_discount && customer_has_minimum
        ensure_only_one_GWP_is_added(cart, gwp_item_settings["variant_id"])
    else
        remove_GWP(cart, gwp_item_settings["variant_id"])
    end

    # 专业用户逻辑
    if gwp_is_for_professional && has_pro_tag
      if customer_has_discount && customer_has_minimum
          ensure_only_one_GWP_is_added(cart, gwp_item_settings["variant_id"])
      else
          remove_GWP(cart, gwp_item_settings["variant_id"])
      end
    end

end

Output.cart = cart

优化方案及代码

关键优化点

  1. 提前构建购物车项索引:将购物车中的所有商品按variant_id整理为哈希,后续操作直接通过key访问,避免多次遍历购物车
  2. 合并重复校验逻辑:将普通用户与专业用户的资格校验合并为统一逻辑,减少冗余判断
  3. 优化购物车操作方法:使用更高效的直接删除方式移除商品,直接修改quantity属性而非通过instance_variable_set
  4. 预计算通用变量:折扣码、客户标签等全局变量仅计算一次,避免每个GWP配置重复计算

优化后代码

cart = Input.cart

PRO_TAG = 'professional-tag'
has_pro_tag = cart.customer && cart.customer.tags.include?(PRO_TAG)
applied_discount_code = cart.discount_code&.code
cart_subtotal = cart.subtotal_price

# 提前构建购物车项的variant_id索引,避免重复遍历
line_items_by_variant = cart.line_items.group_by { |item| item.variant.id }

GWP_SETTINGS = [
    { 
        "variant_id" => 98989898989898,
        "discount_code" => "DISCOUNT_CODE_1",
        "minimum_requirement" => Money.new(cents: 50 * 100),
        "user_type" => "consumer"
    },
    { 
        "variant_id" => 97979797979797,
        "discount_code" => "DISCOUNT_CODE_1",
        "minimum_requirement" => Money.new(cents: 50 * 100),
        "user_type" => "consumer"
    },
    { 
        "variant_id" => 96969696969696,
        "discount_code" => "DISCOUNT_CODE_1",
        "minimum_requirement" => Money.new(cents: 50 * 100),
        "user_type" => "consumer"
    }
]

# 处理单个GWP配置的逻辑
def process_gwp(cart, line_items_by_variant, gwp_settings, has_pro_tag, applied_discount_code, cart_subtotal)
    variant_id = gwp_settings["variant_id"]
    required_discount = gwp_settings["discount_code"]
    min_amount = gwp_settings["minimum_requirement"]
    user_type = gwp_settings["user_type"]

    # 判断当前客户是否符合该GWP的用户类型要求
    eligible_user = case user_type
                    when "consumer" then true # 普通用户/未登录用户默认符合
                    when "professional-tag" then has_pro_tag
                    else false
                    end

    # 判断是否满足折扣码和最低金额要求
    eligible_discount = applied_discount_code == required_discount
    eligible_min = cart_subtotal >= min_amount
    eligible = eligible_user && eligible_discount && eligible_min

    # 获取当前购物车中的对应赠品项
    gwp_line_items = line_items_by_variant[variant_id] || []

    if eligible
        # 确保仅保留1件赠品
        if gwp_line_items.any?
            gwp_line_items.first.quantity = 1
            # 删除多余的同赠品项(如果有多个)
            gwp_line_items.drop(1).each { |item| cart.line_items.delete(item) }
        end
    else
        # 移除所有对应赠品项
        gwp_line_items.each { |item| cart.line_items.delete(item) }
    end
end

# 批量处理所有GWP配置
GWP_SETTINGS.each do |gwp|
    process_gwp(cart, line_items_by_variant, gwp, has_pro_tag, applied_discount_code, cart_subtotal)
end

Output.cart = cart

优化效果说明

  • 遍历次数从O(n*m)降至O(n+m):原脚本每个GWP都要遍历购物车2次(移除和数量校验),n为GWP数量,m为购物车项数量;优化后仅遍历购物车1次构建索引,每个GWP直接操作索引,时间复杂度大幅降低
  • 内存占用更稳定:避免反复创建临时变量和多次遍历带来的内存波动,新增GWP配置时资源上升幅度会显著减小
  • 代码可读性提升:逻辑模块化,减少冗余代码,便于后续维护和扩展

内容的提问来源于stack exchange,提问作者Henrique Medina

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 18:16:07