简体   繁体   中英

How to improve Ruby structure for Shopify Script Performance

I'm using a Ruby in Shopify Scripts Editor to manage as a security measure Gift With Purchase (GWP) promotions.

The script current is:

  • Checking if the Customer is logged in as a Professional or Unlogged
  • Checking if there is a minimum amount spent in the cart
  • Ensuring that only one "Gift" product is been added to the cart
  • Removing a "Gift" product if the checkout doesn't have a "Discount Code" or the minimum set in the GWP_SETTINGS = [] obj.

The problem is that it's generating too much Production Errors like "Your script exceeded the time limit." and "Your script exceeded the cpu limit."

The current usage is CPU: 5% | Memory: 8% CPU: 5% | Memory: 8% and it's increasing dizzyingly every time we add a new GWP promotion array.

Is there a better way to structure this logic so it takes less memory to process the entire order + GWP validation?

Here is the "Line Items" structure:

cart = Input.cart

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

GWP_SETTINGS = [
    gwp_1 = { 
        "variant_id" => 98989898989898,
        "discount_code" => "DISCOUNT_CODE_1",
        "minimum_requirement" => Money.new(cents: 50 * 100),
        "user_type" => "consumer"
    },
    gwp_2 = { 
        "variant_id" => 97979797979797,
        "discount_code" => "DISCOUNT_CODE_1",
        "minimum_requirement" => Money.new(cents: 50 * 100),
        "user_type" => "consumer"
    },
    gwp_3 = { 
        "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"

    #UNLOGGED
    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

    #PRO
    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

You only have 3 settings. But a customer (an order) could have 100+ line items. You know there is only ever 1 customer, 1 order and for you, 3 GWT settings to use.

Your business logic would be smarter if you looped through the line items only once. Then you have a "this is as fast as I can go, go to town" in terms of your algorithm. You cannot go faster than that.

With things like, "does this customer have an X or Y?", you do those once , not 3 times per line item!

As you check each line item, you can do your special logic for things that might AFFECT that line item.

Basically, this is basic algorithmics. You are doing the most work possible repetitively for no reason, and Shopify is puking because of it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM