defmodule ArkePostgres do alias ArkePostgres.{Table, ArkeUnit} def init() do try do projects = Arke.QueryManager.query(arke: :arke_project, project: :arke_system) |> Arke.QueryManager.filter(:id, :eq, :arke_system, true) |> Arke.QueryManager.filter(:arke_id, :eq, "arke_project") |> Arke.QueryManager.all() Enum.map(projects, fn %{id: project_id} = _project -> start_managers(project_id) end) :ok rescue _ in DBConnection.ConnectionError -> :error _ in Postgrex.Error -> :error end end defp start_managers(project_id) do {parameters, arke_list, groups} = ArkePostgres.Query.get_manager_units(project_id) Enum.map(parameters, fn unit -> Arke.Boundary.ParameterManager.create(unit, project_id) end) arke = Arke.Boundary.ArkeManager.get(:arke, :arke_system) Enum.map(arke_list, fn unit -> base_parameters = Enum.filter(arke.data.parameters, fn %{data: %{persistence: persistence}} -> persistence == "table_column" end) unit = Arke.Core.Unit.update(unit, parameters: unit.data.parameters ++ base_parameters) Arke.Boundary.ArkeManager.create(unit, project_id) end) Enum.map(groups, fn unit -> Arke.Boundary.GroupManager.create(unit, project_id) end) end def create(project, %{arke_id: arke_id} = unit) do arke = Arke.Boundary.ArkeManager.get(arke_id, project) {:ok, unit} = handle_create(project, arke, unit) {:ok, Arke.Core.Unit.update(unit, metadata: Map.merge(unit.metadata, %{project: project}))} end defp handle_create(project, %{data: %{type: "table"}} = arke, %{data: data} = unit) do data = data |> data_as_klist Table.insert(project, arke, data) {:ok, unit} end defp handle_create(project, %{data: %{type: "arke"}} = arke, unit) do {:ok, %{id: id, inserted_at: inserted_at, updated_at: updated_at} = _} = ArkeUnit.insert(project, arke, unit) {:ok, Arke.Core.Unit.update(unit, id: id, inserted_at: inserted_at, updated_at: updated_at)} end defp handle_create(_, _, _) do {:ok, "arke type not supported"} end def update(project, %{arke_id: arke_id} = unit) do arke = Arke.Boundary.ArkeManager.get(arke_id, project) {:ok, unit} = handle_update(project, arke, unit) end def handle_update(project, %{data: %{type: "table"}} = arke, unit) do data = unit |> filter_primary_keys(false) |> data_as_klist where = unit |> filter_primary_keys(true) |> data_as_klist Table.update(project, arke, data, where) {:ok, unit} end def handle_update(project, %{data: %{type: "arke"}} = arke, unit) do ArkeUnit.update(project, arke, unit) {:ok, unit} end def handle_update(_, _, _) do {:error, "arke type not supported"} end def delete(project, %{arke_id: arke_id} = unit) do arke = Arke.Boundary.ArkeManager.get(arke_id, project) handle_delete(project, arke, unit) end defp handle_delete(project, %{data: %{type: "table"}} = arke, %{metadata: metadata} = unit) do metadata = Map.delete(metadata, :project) where = unit |> filter_primary_keys(true) |> Map.put_new(:configuration, metadata) |> data_as_klist Table.delete(project, arke, where) {:ok, nil} end defp handle_delete(project, %{data: %{type: "arke"}} = arke, unit) do ArkeUnit.delete(project, arke, unit) {:ok, nil} end defp handle_delete(_, _, _) do {:error, "arke type not supported"} end defp filter_primary_keys( %{arke_id: arke_id, metadata: %{project: project}} = unit, is_primary \\ true ) do arke = Arke.Boundary.ArkeManager.get(arke_id, project) parameters = Enum.filter(arke.data.parameters, fn %{data: param_data} -> param_data.is_primary != is_primary end) unit.data |> remove_parameters(parameters) end defp remove_parameter(data, parameter) do Map.delete(data, parameter.id) end defp remove_parameters(data, parameters) do Enum.reduce(parameters, data, fn f, new_struct -> remove_parameter(new_struct, f) end) end def data_as_klist(data) do Enum.to_list(data) end ###################################################################################################################### def create_project(%{arke_id: :arke_project, id: id} = _unit) do try do sql = "CREATE SCHEMA \"#{id}\"" Ecto.Adapters.SQL.query(ArkePostgres.Repo, sql, []) Ecto.Migrator.run(ArkePostgres.Repo, :up, all: true, prefix: id) :ok rescue _ in DBConnection.ConnectionError -> :error _ in Postgrex.Error -> :error end end # TODO handle exception def create_project(_), do: nil def delete_project(%{arke_id: :arke_project, id: id} = unit) do sql = "DROP SCHEMA \"#{id}\" CASCADE" Ecto.Adapters.SQL.query(ArkePostgres.Repo, sql, []) end # TODO handle exception def delete_project(_), do: nil end