Current section

Files

Jump to
compox lib docker services.ex
Raw

lib/docker/services.ex

defmodule Compox.Docker.Services do
@moduledoc """
Provides functions to work with [Compox
services](`Compox.Docker.Services.Service`).
"""
require Logger
alias Compox.Docker.Services.Service
alias Compox.Docker.API.Containers
alias Compox.Docker.Upcheck
@doc """
Starts [services](`t:Compox.Docker.Service.t/0`) from the `docker compose`.
Each service is started independently.
After all services are launch, returns the list of services updated with each
container id.
"""
@spec start([Service.t()]) :: [Service.t()]
def start(services) when is_list(services) do
Enum.map(services, &start/1)
end
@spec start(Service.t()) :: Service.t()
def start(%Service{name: service_name} = service) do
service =
case Containers.get_id(service_name) do
nil ->
container_id = start_container(service_name)
%{service | container_id: container_id}
container_id ->
Mix.shell().info(
"[compox] Found a container for #{service_name}, reusing it"
)
reuse_container(container_id)
%{service | container_id: container_id, reused: true}
end
Upcheck.maybe_do_upcheck(service_name)
service
end
@doc """
Stops the given [services](`t:Compox.Docker.Service.t/0`).
In order to stop the containers, sends a `SIGKILL` message to all the
container process.
"""
@spec stop([Service.t()]) :: :ok
def stop(services) when is_list(services) do
Enum.each(services, &stop/1)
end
@spec stop(Service.t()) :: :ok
def stop(%Service{
name: service_name,
container_id: container_id,
reused: reused
}) do
stop_or_kill =
:compox
|> Application.get_env(:kill_on_finish, false)
|> case do
true -> "kill"
false -> "stop"
end
# XXX: give some time to ecto processes to finish. 1 of 100 times there
# are connections and error logs are thrown
Process.sleep(200)
case {reused, stop_or_kill} do
{true, "kill"} ->
Containers.kill(container_id)
{true, "stop"} ->
Containers.stop(container_id)
{false, _} ->
System.cmd("docker-compose", [stop_or_kill, service_name])
end
Upcheck.wait_until_down(container_id)
Mix.shell().info("[compox] Service #{service_name} killed")
end
#
# Private functions
#
@spec reuse_container(Containers.container_id()) :: Containers.container_id()
defp reuse_container(container_id) do
case Containers.start(container_id) do
:ok ->
container_id
{:error, reason} ->
Mix.shell().error("[compox] Error trying to reuse container: #{reason}")
container_id
end
end
# If there container id
@spec start_container(service_name :: String.t()) :: Containers.container_id()
defp start_container(service_name) do
Mix.shell().info("[compox] Starting service #{service_name}...")
System.cmd("docker-compose", ["up", "--no-deps", "-d", service_name])
container_id = Containers.get_id(service_name)
Upcheck.wait_until_up(container_id)
container_id
end
end