lib/mix/tasks/ecto.ots.migrate.ex

defmodule Mix.Tasks.Ecto.Ots.Migrate do
  use Mix.Task

  import Mix.Ecto
  import Mix.EctoTablestore

  @shortdoc "Run the table creations"

  @aliases [
    n: :step,
    r: :repo
  ]

  @switches [
    all: :boolean,
    step: :integer,
    to: :integer,
    prefix: :string,
    repo: [:keep, :string],
    migrations_path: :string
  ]

  @moduledoc """
  Runs the all migration for the given repository.

  Migrations are expected at "priv/tablestore/YOUR_REPO/migrations" directory of the current
  application, where "YOUR_REPO" is the last segment in your repository name. For example, the
  repository `MyApp.Repo` will use "priv/tablestore/repo/migrations", the repository
  `Whatever.MyRepo` will use "priv/tablestore/my_repo/migrations".

  Alibaba Tablestore is a cloud service product, there will not do any local storage, meanwhile it
  is a NoSQL data storage, the migrations mainly responsible for the creation of the table primary
  key(s).

  Currently, run migrations will execute the all defined tasks, once Tablestore's primary key(s)
  are created, the primary keys(s) cannot be modified, failed to create an existing table, we can
  ignore it.

  ## Example

      mix ecto.ots.migrate
      mix ecto.ots.migrate -r EctoTablestore.TestRepo

  ## Command line options

    * `-r`, `--repo` - the repo to migrate
  """

  @impl true
  def run(args) do
    repos = parse_repo(args)

    {opts, _} = OptionParser.parse!(args, strict: @switches, aliases: @aliases)

    opts =
      if opts[:to] || opts[:step] || opts[:all], do: opts, else: Keyword.put(opts, :all, true)

    {:ok, _} = Application.ensure_all_started(:ecto_tablestore)

    for repo <- repos do
      ensure_repo(repo, args)
      path = ensure_migrations_path(repo, opts)
      fun = &EctoTablestore.Migrator.run(&1, path, opts)

      case EctoTablestore.Migrator.with_repo(repo, fun, [mode: :temporary] ++ opts) do
        {:ok, _migrated, _apps} ->
          :ok

        {:error, error} ->
          Mix.raise("Could not start repo #{inspect(repo)}, error: #{inspect(error)}")
      end
    end
  end
end