Learning to Respect the API calls limit

From Shopify Wiki

Jump to: navigation, search

or How I taught my program to pause and resume

So you're about to submit a support ticket to ask the accommodating folks at Shopify to raise your API limit.

You're a reasonable person but here's what will likely go on in my head as I read your request if I stumble on it in support — warning: dramatized foreshadowing coming up:

File:/upload/3/32/Missive qui me tombe sur les nerfs.png

Please take a moment to reflect upon what you're about to do. Those limits exist for a reason. They're not random rules that Shopify came up with to make your life hard.

This article will show you how to tell your program to sleep using Ruby. No worries, your program doesn't need to sleep any more than necessary. It just needs to take small pauses to keep yourself a few API calls shy from the API calls limit. To guard you against a 503 crash.

File:/upload/2/2f/Plane crash.png

Automated tasks are great because you don't need to wait around while things get done. If an automated task takes 30 minutes to complete rather than 15, you won't feel the difference if you're doing something unrelated and fun.

We'll use a real-world example.

Contents

Your mission

You want to delete products that are out of stock.

What's the API call limit

500 API calls every 5 minutes.

Shopify headers with each response to an API call so that you can check how many calls you've made:

HTTP_X_SHOPIFY_SHOP_API_CALL_LIMIT (lists how many calls you've made for that particular shop)

HTTP_X_SHOPIFY_SHOP_API_CALL_LIMIT: 3/500

How many orders or products can I get with 1 API call

250 maximum.

How many orders or products can I update with 1 API call

1 (one).



Creating your program

In your code editor of choice, create a new Ruby file. Call it, say, cleanup.rb.

Add to that blank file the code below, then copy your API key, password and myshopify sub-domain in the relevant placeholders:

APIKEY = 'APIKEY'
PASSWORD = 'PASSWORD'
SHOPNAME = 'shopname'

CYCLE = 10 * 60       # 10 minutes times 60 seconds per minute.

require 'rubygems'    # Need this to use the shopify_api gem.
require 'shopify_api' # Tellement utile to speak to your shop.

Below, add your engine. This one fetches all products and deletes the ones that are not available.

# Telling your shop who's boss.
ShopifyAPI::Base.site = "http://#{APIKEY}:#{PASSWORD}@#{SHOPNAME}.myshopify.com/admin"

# How many.
product_count = ShopifyAPI::Product.count
nb_pages      = (product_count / 250.0).ceil

# Do we actually have any work to do?
puts "Yo man. You don't have any product in your shop. duh!" if product_count.zero?

# Initializing.
start_time = Time.now

# While we still have products.
1.upto(nb_pages) do |page|
  unless page == 1
    stop_time = Time.now
    puts "Last batch processing started at #{start_time.strftime('%I:%M%p')}"
    puts "The time is now #{stop_time.strftime('%I:%M%p')}"
    processing_duration = stop_time - start_time
    puts "The processing lasted #{processing_duration.to_i} seconds."
    wait_time = (CYCLE - processing_duration).ceil
    puts "We have to wait #{wait_time} seconds then we will resume."
    sleep wait_time
    start_time = Time.now
  end
  puts "Doing page #{page}/#{nb_pages}..."
  products = ShopifyAPI::Product.find( :all, :params => { :limit => 250, :page => page } )
  products.each do |product|
    puts product.title
    any_in_stock = product.variants.any? do |variant|
      variant.inventory_management == '' || variant.inventory_policy == 'continue' || variant.inventory_quantity > 0
    end
    if not any_in_stock
      puts "--- Deleting #{product.title}..."
      product.destroy
    end
  end
end

puts "Over and out."

If you remove all comments and puts, there aren't many lines of code left.

It's worth it.

Running your program

Open a Ruby Console or launch your Terminal.

Browse to your program and run it:

ruby cleanup.rb

Lame Example

My example was lame because unless the products in your shop are all out of stock you likely won't need to use a throttling mechanism in the way shown above to delete out of stock products. Nevertheless, there will be situations where it becomes critical to 'pause and resume' your program. Say you want to edit the price of all the products in your shop.

Code repository

File:/upload/d/d0/Download.jpeg

The code above is available on github: http://github.com/carolineschnapp/delete-out-of-stock-products/blob/master/cleanup.rb