Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/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
Erlang 使用Elixir Genstage的运行时动态计算图_Erlang_Elixir_Genstage - Fatal编程技术网

Erlang 使用Elixir Genstage的运行时动态计算图

Erlang 使用Elixir Genstage的运行时动态计算图,erlang,elixir,genstage,Erlang,Elixir,Genstage,我希望能够在运行时动态更改计算管道,但GenStage似乎要求在编译时通过subscribe\u:[…]机制定义计算图。有没有办法创建动态计算图?例如,在下面的示例中,我想在运行时在管道图中的“减去7”和“减去4”顶点之间切换 这是否可能使用GenStage?我可能会有非常复杂的管道,所以我需要一个解决方案,以复杂的方式扩展到不断变化的图形,而不是特别的解决方案,例如在本例中,参数化要减去的整数。我希望能够添加或删除整个子树,在子树之间切换,并将节点添加到图形中,包括将它们拼接到任何子树(包括

我希望能够在运行时动态更改计算管道,但GenStage似乎要求在编译时通过
subscribe\u:[…]
机制定义计算图。有没有办法创建动态计算图?例如,在下面的示例中,我想在运行时在管道图中的“减去7”和“减去4”顶点之间切换

这是否可能使用GenStage?我可能会有非常复杂的管道,所以我需要一个解决方案,以复杂的方式扩展到不断变化的图形,而不是特别的解决方案,例如在本例中,参数化要减去的整数。我希望能够添加或删除整个子树,在子树之间切换,并将节点添加到图形中,包括将它们拼接到任何子树(包括主树)的中间

请参阅下面的编辑 以下是最初的制作人:

defmodule GenstageTest.Producer do
  use GenStage

  def start_link(initial \\ 1) do
    GenStage.start_link(__MODULE__, initial, name: __MODULE__)
  end

  def init(counter), do: {:producer, counter}

  def handle_demand(demand, state) do
    events = Enum.to_list(state..(state + demand - 1))
    {:noreply, events, state + demand}
  end
end
以下是生产者和消费者之一:

defmodule GenstageTest.PcTimesFive do
  use GenStage

  def start_link do
    GenStage.start_link(__MODULE__, :state_doesnt_matter, name: __MODULE__)
  end

  def init(state) do
    {:producer_consumer, state, subscribe_to: [GenstageTest.PcAddOne]}
  end

  def handle_events(events, _from, state) do
    numbers =
      events
      |> Enum.map(&(&1 * 5))
    {:noreply, numbers, state}
  end
end
这是最终消费者:

defmodule GenstageTest.Consumer do
  use GenStage

  def start_link do
    GenStage.start_link(__MODULE__, :state_doesnt_matter)
  end

  def init(state) do
    {:consumer, state, subscribe_to: [GenstageTest.PcDivTwo]}
  end

  def handle_events(events, _from, state) do
    for event <- events do
      IO.inspect({self(), event, state})
    end

    # As a consumer we never emit events
    {:noreply, [], state}
  end
end
生产者与消费者:

defmodule GenstageTest.Consumer do
  use GenStage

  def start_link do
    GenStage.start_link(__MODULE__, :state_doesnt_matter)
  end

  def init(state) do
    {:consumer, state, subscribe_to: [GenstageTest.PcDivTwo]}
  end

  def handle_events(events, _from, state) do
    for event <- events do
      IO.inspect({self(), event, state})
    end

    # As a consumer we never emit events
    {:noreply, [], state}
  end
end
defmodule GenstageTest.PcAddOne do
  use GenStage

  def start_link do
    GenStage.start_link(__MODULE__, :state_doesnt_matter, name: __MODULE__)
  end

  def init(state) do
    {:producer_consumer, state}
  end

  def handle_events(events, _from, state) do
    numbers =
      events
      |> Enum.map(&(&1 + 1))
    {:noreply, numbers, state}
  end
end
消费者:

defmodule GenstageTest.Consumer do
  use GenStage

  def start_link do
    GenStage.start_link(__MODULE__, :state_doesnt_matter)
  end

  def init(state) do
    {:consumer, state}
  end

  def handle_events(events, _from, state) do
    for event <- events do
      IO.inspect event
      #File.write("/home/tbrowne/scratch/output.txt", 
      #  Kernel.inspect(event) <> " ", [:append])
      :timer.sleep(100)
    end

    # As a consumer we never emit events
    {:noreply, [], state}
  end
end
但现在的问题是,我仍然不知道如何取消订阅。有一个,也有一个<例如,code>GenStage.stop(c)似乎没有任何作用,而我在
GenStage.cancel/3
上的各种尝试只会给出错误


总而言之,我现在需要的是能够停止某些阶段并用其他阶段取代它们。取消子脚本的语法是什么,从何处调用?文档中没有很好的解释,因为没有具体的例子。

您完全可以在运行时更改管道。还有。我认为这些足以动态管理GenStage管道。

为什么不实现自己的
GenStage.Dispatcher
?这里是

在本例中,他们似乎使用了
动态监管者对pr
消费者
进行了动态切换:。也许你能从《生产者与消费者》上得到同样的灵感?我会尽快尝试,但今天不会。问题是你想在什么情况下切换一个阶段?这取决于管道中的数据,还是由外部处理?@Hauleth的想法是,用户将能够使用不同的管道动态地“假设”,因此,管道更改将是外部事件,即:外部。事实上,它们很可能来自一个类似于lunalang的界面,我已经很好地实现了这一点。很遗憾,Genstate上的长生不老药学校没有提到这种模式。但是我有一个问题,取消是如何工作的?这是生产者/生产者/消费者内部必须发生的事情吗?IE必须在生产者和消费者内部定义和调用它吗?或者可以从外部调用GenStage.cancel?我发现所有排列都有错误。你能举例说明如何使用“取消”按钮吗?所有其他的东西我都能成功使用。我不能取消工作。“你知道它是怎么工作的吗?”托马斯布朗说,“对不起,我正忙着其他事情。”。Elixir不是OO,因此没有“从内部定义和调用…”如果我正确理解了您的意思…@ThomasBrowne(在我完成之前意外发送了评论…)您可以从文档中看到GenStage.cancel接受“from”类型作为第一个参数,单击它由pid和标记组成,后者可从GenStage.sync_subscribe获得。从外观上看,pid应该是生产者的。希望这能帮上忙。是的,我把它修好了。然而,我手工修改缓冲区的长度,使其立即停止。不过,我还有一个问题。当我使用
cancel
时,它会停止订阅,但也会关闭与其关联的使用者。为什么会这样?为什么它不停止订阅,然后让我从同一个正在运行的消费者那里重新订阅其他内容呢。
{:ok, p} = GenstageTest.Producer.start_link(0)
{:ok, a1} = GenstageTest.PcAddOne.start_link()
{:ok, c} = GenstageTest.Consumer.start_link()
{:ok, link1} = GenStage.sync_subscribe(a1, to: p, min_demand: 0, max_demand: 1, cancel: :transient)
{:ok, link2} = GenStage.sync_subscribe(c, to: a1, min_demand: 0, max_demand: 1, cancel: :transient)