关于使用“重试”逻辑的Ruby设计策略

时间:2012-09-06 13:37:39

标签: ruby metaprogramming

我正在处理要求我执行以下操作的API(无法更改API):

  1. 登录服务以使用它(登录)
  2. 使用api方法从登录中传递一些令牌信息和一些api方法特定的参数(每个这样的方法调用都包含在自己的“api_user”方法中 - 见下文)。
  3. 在第2步中,api可能会导致某些异常,在这种情况下,我必须重试login方法并使用新标记再次调用相同的api。每个api方法可以具有附加参数(除了令牌参数之外)。从概念上讲,如果我已经登录,我现在可以使用令牌,可以使用一段时间。

    def api_user
      begin
        api_method1 token, x,y,z
      RetryException => e
        new_token = login
        api_method1 token, x,y,z
      end
    end
    

    我该如何优雅地做到这一点? 选项1:

    对于每个api_user方法 - 单独执行上述操作

    选项2: 使用ruby的元编程。我试图在下面显示。

    class Y
      def self.api_invoker(token,y,z)
        if token == 'old'
          raise "Old token - renew it"
        end 
        puts "Token = #{token}"
      end 
    
      def self.call_method(m, *params)
        method = Y.method(m)
        begin
          method.call(*params)
        rescue Exception => e
          if e.message.include? "Old token"
            puts "params before = #{params}"
            params[0] = "new"
            puts "params after = #{params}"
            method.call(*params)
          end 
        end 
      end 
    
    end
    

    如果您按如下方式调用上述方法,则会触发重试,并将“new”标记传递给方法的第二次调用。

    Y.call_method("api_invoker", "old",2,3)
    

    我不喜欢这个设计 1.虽然我更喜欢选项1,但它似乎有点复杂,因为它从所有api调用方法中删除了重复的重试逻辑。 2.由于ruby无法使用其名称访问参数,因此我必须强制使用token参数作为所有“api调用者”方法中的第一个参数。这样我就可以在重审时用新令牌替换该参数。

    如果ruby有办法使用他们的名字来访问参数,那么上面的设计就是可接受的。

    你能建议一个更好的方法吗?

    谢谢! PS:我可以在每个api_invoker的“哈希”中传递所有参数,然后使用令牌参数名称来访问它,无论它位于何处(类似于链接http://deepfall.blogspot.com/2008/08/named-parameters-in-ruby.html中提到的 - )但这似乎更加丑陋对我来说。

1 个答案:

答案 0 :(得分:0)

使用选项2避免重复try catch块。