defmodule Mix.Tasks.Nbx.Gen.Cache do
@shortdoc "Generates a new cache"
@moduledoc """
Generates a new cache.
The cache will be placed in the `lib` directory.
## Examples
$ mix nbx.gen.cache -c MyApp.Cache
## Command line options
* `-c`, `--cache` - The cache to generate.
"""
use Mix.Task
import Mix.Generator
import Mix.Nebulex
alias Mix.Project
@switches [
cache: [:string, :keep]
]
@aliases [
c: :cache
]
@impl true
def run(args) do
no_umbrella!("nbx.gen.cache")
{opts, _} = OptionParser.parse!(args, strict: @switches, aliases: @aliases)
cache = get_cache(opts)
config = Project.config()
underscored = Macro.underscore(inspect(cache))
base = Path.basename(underscored)
file = Path.join("lib", underscored) <> ".ex"
app = config[:app] || :YOUR_APP_NAME
opts = [mod: cache, app: app, base: base]
create_directory(Path.dirname(file))
create_file(file, cache_template(opts))
config_path = config[:config_path] || "config/config.exs"
case File.read(config_path) do
{:ok, contents} ->
check = String.contains?(contents, "import Config")
config_first_line = get_first_config_line(check) <> "\n"
new_contents = config_first_line <> "\n" <> config_template(opts)
Mix.shell().info([:green, "* updating ", :reset, config_path])
File.write!(config_path, String.replace(contents, config_first_line, new_contents))
{:error, _} ->
create_file(config_path, "import Config\n\n" <> config_template(opts))
end
Mix.shell().info("""
Don't forget to add your new cache to your supervision tree
(typically in lib/#{app}/application.ex):
def start(_type, _args) do
children = [
#{inspect(cache)},
]
For more information about configuration options, check
adapters documentation and Nebulex.Cache shared options.
""")
end
defp get_cache(opts) do
case Keyword.get_values(opts, :cache) do
[] -> Mix.raise("nbx.gen.cache expects the cache to be given as -c MyApp.Cache")
[cache] -> Module.concat([cache])
[_ | _] -> Mix.raise("nbx.gen.cache expects a single cache to be given")
end
end
defp get_first_config_line(true), do: "import Config"
defp get_first_config_line(false), do: "use Mix.Config"
embed_template(:cache, """
defmodule <%= inspect @mod %> do
use Nebulex.Cache,
otp_app: <%= inspect @app %>,
adapter: Nebulex.Adapters.Local
end
""")
embed_template(:config, """
config <%= inspect @app %>, <%= inspect @mod %>,
# Sets :shards as backend (defaults to :ets)
# backend: :shards,
# GC interval for pushing a new generation (e.g., 12 hrs)
gc_interval: :timer.hours(12),
# Max number of entries (e.g, 1 million)
max_size: 1_000_000,
# Max memory size in bytes (e.g., 2GB)
allocated_memory: 2_000_000_000,
# GC interval for checking memory and maybe evict entries (e.g., 10 sec)
gc_memory_check_interval: :timer.seconds(10)
""")
end