Skip to content

Commit

Permalink
Merge pull request #111 from uberbrodt/master
Browse files Browse the repository at this point in the history
Turn EventStore mix tasks into generic tasks for use with Distillery
  • Loading branch information
slashdotdash authored Mar 29, 2018
2 parents 7703cf6 + 79a429a commit 9696dba
Show file tree
Hide file tree
Showing 9 changed files with 264 additions and 146 deletions.
37 changes: 37 additions & 0 deletions lib/event_store/tasks/create.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
defmodule EventStore.Tasks.Create do
@moduledoc """
Task to create the EventStore
"""

alias EventStore.Storage.Database
import EventStore.Tasks.Output

@doc """
Runs task
## Parameters
- config: the parsed EventStore config
## Opts
- is_mix: set to `true` if running as part of a Mix task
- quiet: set to `true` to silence output
"""
def exec(config, opts) do
opts = Keyword.merge([is_mix: false, quiet: false], opts)

case Database.create(config) do
:ok ->
write_info("The EventStore database has been created.", opts)

{:error, :already_up} ->
write_info("The EventStore database already exists.", opts)

{:error, term} ->
raise_msg(
"The EventStore database couldn't be created, reason given: #{inspect(term)}.",
opts
)
end
end
end
37 changes: 37 additions & 0 deletions lib/event_store/tasks/drop.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
defmodule EventStore.Tasks.Drop do
@moduledoc """
Task to drop the EventStore database.
"""

alias EventStore.Storage.Database
import EventStore.Tasks.Output

@doc """
Runs task
## Parameters
- config: the parsed EventStore config
## Opts
- is_mix: set to `true` if running as part of a Mix task
- quiet: set to `true` to silence output
"""
def exec(config, opts) do
opts = Keyword.merge([is_mix: false, quiet: false], opts)

case Database.drop(config) do
:ok ->
write_info("The EventStore database has been dropped.", opts)

{:error, :already_down} ->
write_info("The EventStore database has already been dropped.", opts)

{:error, term} ->
raise_msg(
"The EventStore database couldn't be dropped, reason given: #{inspect(term)}.",
opts
)
end
end
end
46 changes: 46 additions & 0 deletions lib/event_store/tasks/init.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
defmodule EventStore.Tasks.Init do
@moduledoc """
Task to initalize the EventStore database
"""

import EventStore.Tasks.Output
alias EventStore.Storage.Initializer

@is_events_table_exists """
SELECT EXISTS (
SELECT 1
FROM information_schema.tables
WHERE table_schema = 'public'
AND table_name = 'events'
)
"""

@doc """
Runs task
## Parameters
- config: the parsed EventStore config
## Opts
- is_mix: set to `true` if running as part of a Mix task
- quiet: set to `true` to silence output
"""
def exec(config, opts) do
opts = Keyword.merge([is_mix: false, quiet: false], opts)

{:ok, conn} = Postgrex.start_link(config)

conn_opts = [pool: DBConnection.Poolboy]

Postgrex.query!(conn, @is_events_table_exists, [], conn_opts)
|> case do
%{rows: [[true]]} ->
write_info("The EventStore database has already been initialized.", opts)

%{rows: [[false]]} ->
Initializer.run!(conn, conn_opts)
write_info("The EventStore database has been initialized.", opts)
end
end
end
101 changes: 101 additions & 0 deletions lib/event_store/tasks/migrate.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
defmodule EventStore.Tasks.Migrate do
@moduledoc """
Task to migrate EventStore
"""

alias EventStore.Storage.Database
import EventStore.Tasks.Output

@available_migrations [
"0.13.0",
"0.14.0"
]

@doc """
Run task
## Parameters
- config: the parsed EventStore config
## Opts
- is_mix: set to `true` if running as part of a Mix task
- quiet: set to `true` to silence output
"""
def exec(config, opts) do
opts = Keyword.merge([is_mix: false, quiet: false], opts)

migrations =
case event_store_schema_version(config) do
[] ->
# run all migrations
@available_migrations

[event_store_version | _] ->
# only run newer migrations
@available_migrations
|> Enum.filter(fn migration_version ->
migration_version |> Version.parse!() |> Version.compare(event_store_version) == :gt
end)
end

migrate(config, opts, migrations)
end

defp migrate(_config, opts, []) do
write_info("The EventStore database is already migrated.", opts)
end

defp migrate(config, opts, migrations) do
for migration <- migrations do
write_info("Running migration v#{migration}...", opts)

path = Application.app_dir(:eventstore, "priv/event_store/migrations/v#{migration}.sql")
script = File.read!(path)

case Database.migrate(config, script) do
:ok ->
:ok

{:error, term} ->
raise_msg(
"The EventStore database couldn't be migrated, reason given: #{inspect(term)}.",
opts
)
end
end

write_info("The EventStore database has been migrated.", opts)
end

defp event_store_schema_version(config) do
config
|> query_schema_migrations()
|> Enum.sort(fn left, right ->
case Version.compare(left, right) do
:gt -> true
_ -> false
end
end)
end

defp query_schema_migrations(config) do
with {:ok, conn} <- Postgrex.start_link(config) do
conn
|> Postgrex.query!(
"SELECT major_version, minor_version, patch_version FROM schema_migrations",
[],
pool: DBConnection.Poolboy
)
|> handle_response()
end
end

defp handle_response(%Postgrex.Result{num_rows: 0}), do: []

defp handle_response(%Postgrex.Result{rows: rows}) do
Enum.map(rows, fn [major_version, minor_version, patch_version] ->
Version.parse!("#{major_version}.#{minor_version}.#{patch_version}")
end)
end
end
31 changes: 31 additions & 0 deletions lib/event_store/tasks/output.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
defmodule EventStore.Tasks.Output do
@moduledoc false

def write_info(msg, opts) do
unless opts[:quiet] do
info(msg, opts[:is_mix])
end
end

defp info(msg, true) do
Mix.shell().info(msg)
end

defp info(msg, _) do
IO.puts(msg)
end

def raise_msg(msg, opts) do
unless opts[:quiet] do
do_raise(msg, opts[:is_mix])
end
end

defp do_raise(msg, true) do
Mix.raise(msg)
end

defp do_raise(msg, _) do
raise msg
end
end
23 changes: 3 additions & 20 deletions lib/mix/tasks/event_store.create.ex
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ defmodule Mix.Tasks.EventStore.Create do
use Mix.Task

alias EventStore.Config
alias EventStore.Storage.Database
alias EventStore.Tasks.Create

@shortdoc "Create the database for the EventStore"

Expand All @@ -26,25 +26,8 @@ defmodule Mix.Tasks.EventStore.Create do
config = Config.parsed()
{opts, _, _} = OptionParser.parse(args, switches: [quiet: :boolean])

create_database(config, opts)
Create.exec(config, Keyword.put(opts, :is_mix, true))

Mix.Task.reenable "event_store.create"
end

defp create_database(config, opts) do
case Database.create(config) do
:ok ->
unless opts[:quiet] do
Mix.shell.info "The EventStore database has been created."
end

{:error, :already_up} ->
unless opts[:quiet] do
Mix.shell.info "The EventStore database already exists."
end

{:error, term} ->
Mix.raise "The EventStore database couldn't be created, reason given: #{inspect term}."
end
Mix.Task.reenable("event_store.create")
end
end
16 changes: 4 additions & 12 deletions lib/mix/tasks/event_store.drop.ex
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,20 @@ defmodule Mix.Tasks.EventStore.Drop do
use Mix.Task

alias EventStore.Config
alias EventStore.Storage.Database

@shortdoc "Drop the database for the EventStore"

@doc false
def run(_args) do
config = Config.parsed()

if skip_safety_warnings?() or Mix.shell.yes?("Are you sure you want to drop the EventStore database?") do
drop_database(config)
if skip_safety_warnings?() or
Mix.shell().yes?("Are you sure you want to drop the EventStore database?") do
EventStore.Tasks.Drop.exec(config, is_mix: true)
end
end

defp skip_safety_warnings? do
Mix.Project.config[:start_permanent] != true
end

defp drop_database(config) do
case Database.drop(config) do
:ok -> Mix.shell.info "The EventStore database has been dropped."
{:error, :already_down} -> Mix.shell.info "The EventStore database has already been dropped."
{:error, term} -> Mix.raise "The EventStore database couldn't be dropped, reason given: #{inspect term}."
end
Mix.Project.config()[:start_permanent] != true
end
end
36 changes: 3 additions & 33 deletions lib/mix/tasks/event_store.init.ex
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,8 @@ defmodule Mix.Tasks.EventStore.Init do

use Mix.Task

alias EventStore.{Config, Storage}

@is_events_table_exists """
SELECT EXISTS (
SELECT 1
FROM information_schema.tables
WHERE table_schema = 'public'
AND table_name = 'events'
)
"""
alias EventStore.{Config}
alias EventStore.Tasks.Init

@shortdoc "Initialize the database for the EventStore"

Expand All @@ -34,30 +26,8 @@ defmodule Mix.Tasks.EventStore.Init do
config = Config.parsed()
{opts, _, _} = OptionParser.parse(args, switches: [quiet: :boolean])

initialize_storage!(config, opts)
Init.exec(config, Keyword.put(opts, :is_mix, true))

Mix.Task.reenable("event_store.init")
end

defp initialize_storage!(config, opts) do
{:ok, conn} = Postgrex.start_link(config)

conn_opts = [pool: DBConnection.Poolboy]

Postgrex.query!(conn, @is_events_table_exists, [], conn_opts)
|> case do
%{rows: [[true]]} ->
info("The EventStore database has already been initialized.", opts)

%{rows: [[false]]} ->
Storage.Initializer.run!(conn, conn_opts)
info("The EventStore database has been initialized.", opts)
end
end

defp info(msg, opts) do
unless opts[:quiet] do
Mix.shell().info(msg)
end
end
end
Loading

0 comments on commit 9696dba

Please sign in to comment.