【发布时间】:2018-06-25 10:45:23
【问题描述】:
看了this的演讲,我明白了如何分离Web界面和OTP应用程序,但是如果有的话,应该如何分离OTP应用程序和Ecto代码呢?
目前我正在编写一个调用 Ecto 函数或 Ecto 函数的包装函数的 OTP 应用程序,在handle_call/3 回调中:
@doc """
Generates a workout.
iex> Pullapi.Database.delete_workouts()
iex> Pullapi.Database.delete_sets()
iex> result = Pullapi.GenServerWorker.handle_call({:initial_workout, 1, 20, 25}, nil, %{})
iex> {:reply, [{:ok, %Pullapi.Set{__meta__: _, action: action, id: _, inserted_at: _, order: _, units: _, updated_at: _}}| rest], %{}} = result
iex> action
"Pullups"
"""
def handle_call({:initial_workout, user_id, maxreps, goal}, _from, state) do
# insert Goal
%Pullapi.Goal{user_id: user_id, units: goal}
|> Pullapi.Database.insert_if_not_exists
# get Inital config
config = Application.get_env(:pullapi, Initial)
# retrieve id from inserted Workout row
result = %Pullapi.Workout{user_id: user_id} |> Pullapi.Database.insert_if_not_exists
case result do
{:ok, workout} ->
%Pullapi.Workout{__meta__: _, id: workout_id, inserted_at: _, updated_at: _, user_id: _} = workout
inserted_sets = maxreps
|> (&(&1*config[:max_reps_percent]/100 |> max(1))).()
|> round
|> Pullapi.Numbers.gaussian(
config[:standard_deviation],
config[:cap_percent],
config[:cut]
)
|> Pullapi.Database.make_pullup_sets(workout_id)
|> Pullapi.Database.add_rest_sets(config[:rest_intervals])
|> Enum.map(&Pullapi.Repo.insert/1)
{:error, _} ->
inserted_sets = []
end
{:reply, inserted_sets, state}
end
这种方法是否将两者结合得太紧密了?
使用了数据库,因为 GenServer 回复是使用先前生成的用户特定数据计算得出的 - 我希望应用在重新启动后仍然存在。
【问题讨论】:
-
这可能是一个过于宽泛的问题,包括示例将有助于回答它。请注意,仅出于包装 Ecto 调用和组织代码的目的而创建 GenServer 是不可以的。这篇文章可能会提供一些指导:theerlangelist.com/article/spawn_or_not
-
我们还在 Adopting Elixir 书中介绍了类似的主题:pragprog.com/book/tvmelixir/adopting-elixir(免责声明:我是作者之一)。
-
谢谢,我添加了一个例子。也会阅读这篇文章。
标签: elixir phoenix-framework ecto erlang-otp decoupling