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

