Amazon Simple Workflow(SWF)可以与jRuby一起使用吗?

时间:2015-02-19 17:24:24

标签: amazon-web-services jruby amazon-swf

出于无趣的原因,我必须在特定项目中使用jRuby,我们也希望使用Amazon Simple Workflow(SWF)。我没有在jRuby部门做出选择,所以请不要说"使用MRI"。

我遇到的第一个问题是jRuby不支持分叉和SWF活动工作人员喜欢分叉。在浏览SWF ruby​​库之后,我能够弄清楚如何连接记录器并找出如何防止分叉,这非常有帮助:

AWS::Flow::ActivityWorker.new(
  swf.client, domain,"my_tasklist", MyActivities
) do |options|
    options.logger=  Logger.new("logs/swf_logger.log")
    options.use_forking = false
  end

这阻止了分叉,但现在我在SWF源代码中遇到了更多与异常有关的异常以及不存在的上下文:

Error in the poller, exception: 
AWS::Flow::Core::NoContextException: AWS::Flow::Core::NoContextException stacktrace: 

"aws-flow-2.4.0/lib/aws/flow/implementation.rb:38:in 'task'",

 "aws-flow-2.4.0/lib/aws/decider/task_poller.rb:292:in 'respond_activity_task_failed'", 

"aws-flow-2.4.0/lib/aws/decider/task_poller.rb:204:in 'respond_activity_task_failed_with_retry'", 

"aws-flow-2.4.0/lib/aws/decider/task_poller.rb:335:in 'process_single_task'", 

"aws-flow-2.4.0/lib/aws/decider/task_poller.rb:388:in 'poll_and_process_single_task'", 

"aws-flow-2.4.0/lib/aws/decider/worker.rb:447:in 'run_once'", 

"aws-flow-2.4.0/lib/aws/decider/worker.rb:419:in 'start'", 

"org/jruby/RubyKernel.java:1501:in `loop'", 

"aws-flow-2.4.0/lib/aws/decider/worker.rb:417:in 'start'", 

"/Users/trcull/dev/etl/flow/etl_runner.rb:28:in 'start_workers'"

这是该行的SWF代码:

      # @param [Future] future
  #   Unused; defaults to **nil**.
  #
  # @param block
  #   The block of code to be executed when the task is run.
  #
  # @raise [NoContextException]
  #   If the current fiber does not respond to `Fiber.__context__`.
  #
  # @return [Future]
  #   The tasks result, which is a {Future}.
  #
  def task(future = nil, &block)
    fiber = ::Fiber.current
    raise NoContextException unless fiber.respond_to? :__context__
    context = fiber.__context__
    t = Task.new(nil, &block)
    task_context = TaskContext.new(:parent => context.get_closest_containing_scope, :task => t)
    context << t
    t.result
  end

我担心这是同样的分叉问题的另一种风格,并且担心我面临着通过SWF源代码的漫长道路并解决问题,直到我最终碰到一堵墙我无法工作周围。

所以,我的问题是,有没有人真正让jRuby和SWF一起工作?如果是这样,我可以指出哪些步骤和变通方法列表?用Google搜索&#34; SWF和jRuby&#34;到目前为止还没有发现任何事情,我已经在这个任务的1 1/2天内完成了。

3 个答案:

答案 0 :(得分:0)

我认为问题可能是aws-flow-ruby不支持Ruby 2.0。我发现这是PDF日期为2015年1月22日。

  

<强> 1.2.1

     

经过测试的Ruby运行时已经测试了适用于Ruby的AWS Flow Framework   使用官方的Ruby 1.9运行时,也称为YARV。其他版本   Ruby运行时可能有效,但不受支持。

答案 1 :(得分:0)

我对自己的问题有部分答案。回答&#34;可以将SWF用于jRuby&#34;是&#34;是... ish。&#34;

我确实能够让工作流端到端工作(甚至通过JDBC调用数据库,这是我必须这样做的原因)。所以,那是&#34;是&#34;部分答案。是的,SWF可以用于jRuby。

这里是&#34; ish&#34;部分答案。

我上面发布的堆栈跟踪是由于某些活动代码中的问题导致SWF尝试引发ActivityTaskFailedException的结果。那部分是我的错。什么不是我的错,因为ActivityTaskFailedException的超类中包含以下代码:

def initialize(reason = "Something went wrong in Flow",
   details = "But this indicates that it got corrupted getting out")
   super(reason)
   @reason = reason
   @details = details
   details = details.message if details.is_a? Exception
   self.set_backtrace(details)
end

当您的活动抛出异常时,&#34;详细信息&#34;你在上面看到的变量充满了一个字符串。 MRI非常乐意将String作为set_backtrace()的参数,但jRuby不是,并且jRuby会抛出一个异常,说明&#34;详细信息&#34;必须是一个字符串数组。 这个异常会破坏SWF库的所有错误捕获逻辑以及试图与光纤库进行不兼容的代码。 代码然后抛出后续异常并完全杀死活动工作者线程。

因此,只要您的活动和工作流代码永远不会抛出异常,您就可以在jRuby上运行SWF,因为否则这些异常会终止您的工作线程(这不是SWF工作者的预期行为) )。他们设计的目的是以一种漂亮,可追踪,可恢复的方式将异常传回SWF。但是,与SWF进行通信的SWF代码本身就具有与jRuby不兼容的代码。

为了解决这个问题,我像这样修改了AWS :: Flow :: FlowException:

  def initialize(reason = "Something went wrong in Flow",
                 details = "But this indicates that it got corrupted getting out")
    super(reason)
    @reason = reason
    @details = details
    details = details.message if details.is_a? Exception
    details = [details] if details.is_a? String
    self.set_backtrace(details)
  end

希望能帮助处于与我相同情况的人。

答案 2 :(得分:0)

我正在使用JFlow,它允许您使用JRuby启动SWF流活动工作程序。