0

出于无趣的原因,我不得不在我们还想使用 Amazon Simple Workflow (SWF) 的特定项目中使用 jRuby。我在 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 源代码中遇到了更多与 Fibers 相关的异常,并且上下文不存在:

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 一起工作?如果是这样,是否有我可以指出的步骤和解决方法列表?到目前为止,谷歌搜索“SWF 和 jRuby”还没有出现任何结果,我已经完成了 1 1/2 天的任务。

4

3 回答 3

0

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

1.2.1

经测试的 Ruby 运行时 AWS Flow Framework for Ruby 已使用官方 Ruby 1.9 运行时(也称为 YARV)进行了测试。其他版本的 Ruby 运行时可能会工作,但不受支持。

于 2015-02-19T18:24:44.640 回答
0

我对自己的问题有部分答案。“可以让 SWF 在 jRuby 上工作”的答案是“是的……是的”。

事实上,我能够让工作流端到端工作(甚至通过 JDBC 调用数据库,这是我必须这样做的最初原因)。所以,这就是答案的“是”部分。是的,SWF 可以在 jRuby 上运行。

这是答案的“ish”部分。

我在上面发布的堆栈跟踪是 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

当您的活动引发异常时,您在上面看到的“详细信息”变量将填充一个字符串。MRI 非常乐意将字符串作为 set_backtrace() 的参数,但 jRuby 不是,并且 jRuby 会抛出异常,说“详细信息”必须是字符串数组。 这个异常贯穿了 SWF 库的所有很好的错误捕获逻辑,并进入了这段试图与 Fiber 库不兼容的事情的代码。 然后该代码会引发后续异常并完全终止活动工作线程。

因此,只要您的活动和工作流代码从不抛出异常,您就可以在 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

希望对和我有同样情况的人有所帮助。

于 2015-02-19T21:55:29.323 回答
0

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

于 2016-05-19T15:18:38.323 回答