Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/heroku/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 如何正确使用Sidekiq处理Rails中的后台任务_Ruby On Rails_Heroku_Sidekiq_Shopify App - Fatal编程技术网

Ruby on rails 如何正确使用Sidekiq处理Rails中的后台任务

Ruby on rails 如何正确使用Sidekiq处理Rails中的后台任务,ruby-on-rails,heroku,sidekiq,shopify-app,Ruby On Rails,Heroku,Sidekiq,Shopify App,因此,我已经使用rails应用程序生成了一个rails应用程序,并且在很大程度上使该应用程序能够按预期工作。它的目标是从外部库存管理API获取产品数量,然后使用该库存管理系统的最新数量更新Shopify中的变量数量 我的问题是,对外部API的初始POST请求会响应大量产品-有时需要15秒以上。除此之外,我的应用程序的另一部分会接受此响应,对于响应中同样存在于Shopify中的每个产品,它会向Shopify发出PUT请求,以更新变量数量。与初始请求一样,这也需要10-15秒 我的问题是,我在Her

因此,我已经使用rails应用程序生成了一个rails应用程序,并且在很大程度上使该应用程序能够按预期工作。它的目标是从外部库存管理API获取产品数量,然后使用该库存管理系统的最新数量更新Shopify中的变量数量

我的问题是,对外部API的初始
POST
请求会响应大量产品-有时需要15秒以上。除此之外,我的应用程序的另一部分会接受此响应,对于响应中同样存在于Shopify中的每个产品,它会向Shopify发出
PUT
请求,以更新变量数量。与初始请求一样,这也需要10-15秒

我的问题是,我在Heroku上托管应用程序,结果我达到了他们的30秒请求超时限制。因此,我需要使用后台工作程序将上述请求中的至少一个(可能两个)偏移到工作程序队列。我选择了被广泛推荐的Sidekiq gem,它很容易安装

我的问题是,我不知道如何从完成的Sidekiq worker工作中获得结果,然后在控制器中再次使用该结果-我也不知道这是否是最佳实践(我对Rails/应用程序开发有点陌生)

我已经在下面列出了我的控制器(在将其分解为workers之前),该控制器目前正在运行应用程序-我想我只是需要一些建议-我这样做是否正确-这些逻辑是否应该在一个模型中,如果是这样,那么该模型将如何与控制器通信,然后Sidekiq将如何适应所有这些

感谢您的建议或帮助,谢谢

class StockManagementController < ShopifyApp::AuthenticatedController

require 'uri'
require 'net/http'
require 'json'
require 'nokogiri'
require 'open-uri'
require 'rexml/document'

def new
    @token = StockManagementController.new
end

def get_token

    url = URI('https://external.api.endpoint/api/v1/AuthToken')
    http = Net::HTTP.new(url.host, url.port)
    http.use_ssl = true
    http.verify_mode = OpenSSL::SSL::VERIFY_NONE

    @HEROKU_ENV_USERNAME = ENV['HEROKU_ENV_USERNAME']
    @HEROKU_ENV_PASSWORD = ENV['HEROKU_ENV_PASSWORD']

    request = Net::HTTP::Post.new(url)
    request['content-type'] = 'application/x-www-form-urlencoded'
    request['cache-control'] = 'no-cache'
    request.body = 'username=' + @HEROKU_ENV_USERNAME + '&password=' + @HEROKU_ENV_PASSWORD + '&grant_type=password'
    response = http.request(request)
    responseJSON = JSON.parse(response.read_body)
    session[:accessToken] = responseJSON['access_token']

    if session[:accessToken]
        flash[:notice] = 'StockManagement token generation was successful.'
        redirect_to '/StockManagement/product_quantity'
    else
        flash[:alert] = 'StockManagement token generation was unsuccessful.'
    end
end

def product_quantity

    REXML::Document.entity_expansion_text_limit = 1_000_000

    @theToken = session[:accessToken]

    if @theToken

        url = URI('https://external.api.endpoint/api/v1/ProductQuantity')
        http = Net::HTTP.new(url.host, url.port)
        http.use_ssl = true
        http.verify_mode = OpenSSL::SSL::VERIFY_NONE

        request = Net::HTTP::Post.new(url)
        request['authorization'] = 'bearer ' + @theToken + ''
        request['content-type'] = 'application/xml'
        request['cache-control'] = 'no-cache'

        response = http.request(request)
        responseBody = response.read_body
        finalResponse = Hash.from_xml(responseBody).to_json
        resultQuantity = JSON.parse finalResponse

        @connectionType = resultQuantity['AutomatorResponse']['Type']
        @successResponse = resultQuantity['AutomatorResponse']['Success']
        @errorResponse = resultQuantity['AutomatorResponse']['ErrorMsg']

        productQuantityResponse = resultQuantity['AutomatorResponse']['ResponseString']
        xmlResponse = Hash.from_xml(productQuantityResponse).to_json
        jsonResponse = JSON.parse xmlResponse

        @fullResponse = jsonResponse['StockManagement']['Company']['InventoryQuantitiesByLocation']['InventoryQuantity']

        # This hash is used to store the final list of items that we need in order to display the item's we've synced, and to show the number of items we've sycned successfully.
        @finalList = Hash.new

        # This array is used to contain the available products - this is used later on as a way of only rendering
        @availableProducts = Array.new

        # Here we get all of the variant data from Shopify.
        @variants = ShopifyAPI::Variant.find(:all, params: {})

        # For each peace of variant data, we push all of the available SKUs in the store to the @availableProducts Array for use later
        @variants.each do |variant|
            @availableProducts << variant.sku
        end

        #Our final list of products which will contain details from both the Stock Management company and Shopify - we will use this list to run api calls against each item
        @finalProductList = Array.new

        puts "Final product list has #{@fullResponse.length} items."
        puts @fullResponse.inspect

        # We look through every item in the response from Company
        @fullResponse.each_with_index do |p, index|

            # We get the Quantity and Product Code
            @productQTY = p["QtyOnHand"].to_f.round
            @productCode = p["Code"].upcase

            # If the product code is found in the list of available products in the Shopify store...
            if @availableProducts.include? @productCode
                @variants.each do |variant|
                    if @productCode === variant.sku
                        if @productQTY != 0
                            @finalProductList << {
                                "sku" => variant.sku,
                                "inventory_quantity" => variant.inventory_quantity,
                                "old_inventory_quantity" => variant.old_inventory_quantity,
                                "id" => variant.id,
                                "company_sku" => @productCode,
                                "company_qty" => @productQTY
                            }
                        end
                    end
                end
            end
        end

        # If we get a successful response from StockManagement, proceed...
        if @finalProductList
            flash[:notice] = 'StockManagement product quantity check was successful.'

            puts "Final product list has #{@finalProductList.length} items."
            puts @finalProductList

            @finalProductList.each do |item|

                @productSKU = item["sku"]
                @productInventoryQuantity = item["inventory_quantity"]
                @productOldInventoryQuantity = item["old_inventory_quantity"]
                @productID = item["id"]
                @companySKU = item["company_sku"]
                @companyQTY = item["company_qty"]

                url = URI("https://example.myshopify.com/admin/variants/#{@productID}.json")

                http = Net::HTTP.new(url.host, url.port)
                http.use_ssl = true
                http.verify_mode = OpenSSL::SSL::VERIFY_NONE
                request = Net::HTTP::Put.new(url)
                request["content-type"] = 'application/json'
                request["authorization"] = 'Basic KJSHDFKJHSDFKJHSDFKJHSDFKJHSDFKJHSDFKJHSDFKJHSDFKJHSDFKJHSDF'
                request["cache-control"] = 'no-cache'
                request.body = "{\n\t\"variant\": {\n\t\t\"id\": #{@productID},\n\t\t\"inventory_quantity\": #{@companyQTY},\n\t\t\"old_inventory_quantity\": #{@productOldInventoryQuantity}\n\t}\n}"

                # This is the line that actually runs the put request to update the quantity.
                response = http.request(request)

                # Finally, we populate the finalList has with response information.
                @finalList[@companySKU] = ["","You had #{@productOldInventoryQuantity} in stock, now you have #{@companyQTY} in stock."]

            end

        else
            # If the overall sync failed, we flash an alert.
            flash[:alert] = 'Quantity synchronisation was unsuccessful.'

        end

        # Lastly we get the final number of items that were synchronised.
        @synchronisedItems = @finalList.length

        # We flash this notification, letting the user known how many products were successfully synchronised.
        flash[:notice] = "#{@synchronisedItems} product quantities were synchronised successfully."

        # We then pretty print this to the console for debugging purposes.
        pp @finalList

    else

        flash[:alert] = @errorResponse

    end
end
end
class StockManagementController变体。旧库存数量,
“id”=>variant.id,
“company_sku”=>@productCode,
“公司数量”=>@productQTY
}
结束
结束
结束
结束
结束
#如果我们从库存管理部门得到成功的回复,请继续。。。
如果@finalProductList
flash[:notice]=“库存管理产品数量检查成功。”
放置“最终产品列表包含#{@finalProductList.length}项。”
放置@finalProductList
@finalProductList.each do|项|
@产品sku=项目[“sku”]
@productInventoryQuantity=物料[“库存数量”]
@productOldInventoryQuantity=物料[“旧库存数量”]
@productID=项目[“id”]
@companySKU=it
#app_root/config/initializers/constants.rb
HEROKU_ENV_USERNAME = ENV['HEROKU_ENV_USERNAME']
HEROKU_ENV_PASSWORD = ENV['HEROKU_ENV_PASSWORD']