├── priv
├── plts
│ └── .gitkeep
└── tables
│ └── .gitkeep
├── .github
├── FUNDING.yml
└── workflows
│ └── elixir.yml
├── test
├── test_helper.exs
└── quantum_storage_ets_test.exs
├── .formatter.exs
├── lib
├── quantum_storage_ets
│ └── state.ex
└── quantum_storage_ets.ex
├── config
└── .credo.exs
├── CHANGELOG.md
├── .gitignore
├── mix.exs
├── README.md
└── LICENSE
/priv/plts/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/priv/tables/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | open_collective: quantum
2 |
--------------------------------------------------------------------------------
/test/test_helper.exs:
--------------------------------------------------------------------------------
1 | ExUnit.start(capture_log: true)
2 |
--------------------------------------------------------------------------------
/.formatter.exs:
--------------------------------------------------------------------------------
1 | [
2 | inputs: [".formatter.exs", "mix.exs", "{config,lib,test}/**/*.{ex,exs}"]
3 | ]
4 |
--------------------------------------------------------------------------------
/lib/quantum_storage_ets/state.ex:
--------------------------------------------------------------------------------
1 | defmodule QuantumStoragePersistentEts.State do
2 | @moduledoc false
3 |
4 | @type t :: %__MODULE__{table: :ets.tid()}
5 |
6 | @enforce_keys [:table]
7 | defstruct @enforce_keys
8 | end
9 |
--------------------------------------------------------------------------------
/config/.credo.exs:
--------------------------------------------------------------------------------
1 | %{
2 | configs: [
3 | %{
4 | name: "default",
5 | files: %{
6 | included: ["lib/", "test/", "mix.exs"],
7 | excluded: []
8 | },
9 | checks: [
10 | # For others you can also set parameters
11 | {Credo.Check.Readability.MaxLineLength, priority: :low, max_length: 120},
12 | {Credo.Check.Design.TagTODO, false}
13 | ]
14 | }
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 | All notable changes to this project will be documented in this file.
3 | This project adheres to [Semantic Versioning](http://semver.org/).
4 |
5 | ## Unreleased
6 |
7 | Diff for [unreleased](https://github.com/quantum-elixir/quantum-storage-persistent-ets/compare/v1.0.0...HEAD)
8 |
9 | ## v1.0.0
10 |
11 | Diff for [v1.0.0](https://github.com/quantum-elixir/quantum-storage-persistent-ets/compare/v1.0.0-rc.1...v1.0.0)
12 |
13 | ## v1.0.0-rc.1
14 |
15 | ### Added
16 |
17 | * Initial Commit
18 |
19 | Files for [v1.0.0-rc.1](https://github.com/quantum-elixir/quantum-storage-persistent-ets/tree/v1.0.0-rc.1)
20 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # The directory Mix will write compiled artifacts to.
2 | /_build/
3 |
4 | # If you run "mix test --cover", coverage assets end up here.
5 | /cover/
6 |
7 | # The directory Mix downloads your dependencies sources to.
8 | /deps/
9 |
10 | # Where 3rd-party dependencies like ExDoc output generated docs.
11 | /doc/
12 |
13 | # Ignore .fetch files in case you like to edit your project deps locally.
14 | /.fetch
15 |
16 | # If the VM crashes, it generates a dump, let's ignore it too.
17 | erl_crash.dump
18 |
19 | # Also ignore archive artifacts (built via "mix archive.build").
20 | *.ez
21 |
22 | # Ignore package tarball (built via "mix hex.build").
23 | quantum_storage_persistent_ets-*.tar
24 |
25 | # Ignore mix.lock
26 | /mix.lock
27 |
28 | # Ets Tables
29 | /priv/tables/**/*.tab
30 |
31 | # Dialyzer
32 | /priv/plts/*.plt
33 | /priv/plts/*.hash
--------------------------------------------------------------------------------
/mix.exs:
--------------------------------------------------------------------------------
1 | defmodule QuantumStoragePersistentEts.MixProject do
2 | @moduledoc false
3 |
4 | use Mix.Project
5 |
6 | @version "1.0.0"
7 |
8 | def project do
9 | [
10 | app: :quantum_storage_persistent_ets,
11 | version: @version,
12 | elixir: "~> 1.8",
13 | build_embedded: Mix.env() == :prod,
14 | start_permanent: Mix.env() == :prod,
15 | deps: deps(),
16 | docs: docs(),
17 | name: "Quantum Storage Persistent ETS",
18 | description: "Quantum Storage Adapter based on Persistent ETS",
19 | elixirc_paths: elixirc_paths(Mix.env()),
20 | package: package(),
21 | test_coverage: [tool: ExCoveralls],
22 | build_embedded: (System.get_env("BUILD_EMBEDDED") || "false") in ["1", "true"],
23 | dialyzer:
24 | [
25 | ignore_warnings: "dialyzer.ignore-warnings"
26 | ] ++
27 | if (System.get_env("DIALYZER_PLT_PRIV") || "false") in ["1", "true"] do
28 | [
29 | plt_file: {:no_warn, "priv/plts/dialyzer.plt"}
30 | ]
31 | else
32 | []
33 | end
34 | ]
35 | end
36 |
37 | # Run "mix help compile.app" to learn about applications.
38 | def application do
39 | [
40 | extra_applications: [:logger]
41 | ]
42 | end
43 |
44 | defp elixirc_paths(:test), do: ["lib", "test/support"]
45 | defp elixirc_paths(_), do: ["lib"]
46 |
47 | defp package do
48 | %{
49 | maintainers: [
50 | "Jonatan Männchen"
51 | ],
52 | licenses: ["Apache License 2.0"],
53 | exclude_patterns: [~r[priv/(tables|plts)]],
54 | links: %{
55 | "Changelog" =>
56 | "https://github.com/quantum-elixir/quantum-storage-persistent-ets/blob/master/CHANGELOG.md",
57 | "GitHub" => "https://github.com/quantum-elixir/quantum-storage-persistent-ets"
58 | }
59 | }
60 | end
61 |
62 | defp docs do
63 | [
64 | main: "readme",
65 | source_ref: "v#{@version}",
66 | source_url: "https://github.com/quantum-elixir/quantum-storage-persistent-ets",
67 | extras: [
68 | "README.md",
69 | "CHANGELOG.md"
70 | ]
71 | ]
72 | end
73 |
74 | # Run "mix help deps" to learn about dependencies.
75 | defp deps do
76 | [
77 | {:persistent_ets, "~> 0.2"},
78 | {:quantum, "~> 3.0"},
79 | {:ex_doc, "~> 0.13", only: [:dev, :docs], runtime: false},
80 | {:excoveralls, "~> 0.13", only: [:dev, :test], runtime: false},
81 | {:dialyxir, "~> 1.0", only: [:dev, :test], runtime: false},
82 | {:credo, "~> 1.4", only: [:dev, :test], runtime: false}
83 | ]
84 | end
85 | end
86 |
--------------------------------------------------------------------------------
/test/quantum_storage_ets_test.exs:
--------------------------------------------------------------------------------
1 | defmodule QuantumStoragePersistentEtsTest do
2 | @moduledoc false
3 |
4 | use ExUnit.Case
5 | doctest QuantumStoragePersistentEts
6 |
7 | defmodule Scheduler do
8 | @moduledoc false
9 |
10 | use Quantum, otp_app: :quantum_storage_persistent_ets
11 | end
12 |
13 | setup %{test: test} do
14 | storage =
15 | start_supervised!({QuantumStoragePersistentEts, name: Module.concat(__MODULE__, test)})
16 |
17 | assert :ok = QuantumStoragePersistentEts.purge(storage)
18 |
19 | {:ok, storage: storage}
20 | end
21 |
22 | describe "purge/1" do
23 | test "purges correct module", %{storage: storage} do
24 | assert :ok = QuantumStoragePersistentEts.add_job(storage, Scheduler.new_job())
25 | assert :ok = QuantumStoragePersistentEts.purge(storage)
26 | assert :not_applicable = QuantumStoragePersistentEts.jobs(storage)
27 | end
28 | end
29 |
30 | describe "add_job/2" do
31 | test "adds job", %{storage: storage} do
32 | job = Scheduler.new_job()
33 | assert :ok = QuantumStoragePersistentEts.add_job(storage, job)
34 | assert [^job] = QuantumStoragePersistentEts.jobs(storage)
35 | end
36 | end
37 |
38 | describe "delete_job/2" do
39 | test "deletes job", %{storage: storage} do
40 | job = Scheduler.new_job()
41 | assert :ok = QuantumStoragePersistentEts.add_job(storage, job)
42 | assert :ok = QuantumStoragePersistentEts.delete_job(storage, job.name)
43 | assert [] = QuantumStoragePersistentEts.jobs(storage)
44 | end
45 |
46 | test "does not fail when deleting unknown job", %{storage: storage} do
47 | job = Scheduler.new_job()
48 | assert :ok = QuantumStoragePersistentEts.add_job(storage, job)
49 |
50 | assert :ok = QuantumStoragePersistentEts.delete_job(storage, make_ref())
51 | end
52 | end
53 |
54 | describe "update_job_state/2" do
55 | test "updates job", %{storage: storage} do
56 | job = Scheduler.new_job()
57 | assert :ok = QuantumStoragePersistentEts.add_job(storage, job)
58 | assert :ok = QuantumStoragePersistentEts.update_job_state(storage, job.name, :inactive)
59 | assert [%{state: :inactive}] = QuantumStoragePersistentEts.jobs(storage)
60 | end
61 |
62 | test "does not fail when updating unknown job", %{storage: storage} do
63 | job = Scheduler.new_job()
64 | assert :ok = QuantumStoragePersistentEts.add_job(storage, job)
65 |
66 | assert :ok = QuantumStoragePersistentEts.update_job_state(storage, make_ref(), :inactive)
67 | end
68 | end
69 |
70 | describe "update_last_execution_date/2" do
71 | test "sets time on scheduler", %{storage: storage} do
72 | date = NaiveDateTime.utc_now()
73 | assert :ok = QuantumStoragePersistentEts.update_last_execution_date(storage, date)
74 | assert ^date = QuantumStoragePersistentEts.last_execution_date(storage)
75 | end
76 | end
77 |
78 | describe "last_execution_date/1" do
79 | test "gets time", %{storage: storage} do
80 | date = NaiveDateTime.utc_now()
81 | assert :ok = QuantumStoragePersistentEts.update_last_execution_date(storage, date)
82 | assert ^date = QuantumStoragePersistentEts.last_execution_date(storage)
83 | end
84 |
85 | test "get unknown otherwise", %{storage: storage} do
86 | assert :unknown = QuantumStoragePersistentEts.last_execution_date(storage)
87 | end
88 | end
89 | end
90 |
--------------------------------------------------------------------------------
/lib/quantum_storage_ets.ex:
--------------------------------------------------------------------------------
1 | defmodule QuantumStoragePersistentEts do
2 | @moduledoc """
3 | `PersistentEts` based implementation of a `Quantum.Storage`.
4 | """
5 |
6 | use GenServer
7 |
8 | require Logger
9 |
10 | alias __MODULE__.State
11 |
12 | @behaviour Quantum.Storage
13 |
14 | @doc false
15 | def start_link(opts),
16 | do: GenServer.start_link(__MODULE__, opts, opts)
17 |
18 | @doc false
19 | @impl GenServer
20 | def init(opts) do
21 | table_name =
22 | opts
23 | |> Keyword.fetch!(:name)
24 | |> Module.concat(Table)
25 |
26 | path =
27 | Application.app_dir(
28 | :quantum_storage_persistent_ets,
29 | "priv/tables/#{table_name}.tab"
30 | )
31 |
32 | File.mkdir_p!(Path.dirname(path))
33 |
34 | table =
35 | PersistentEts.new(table_name, path, [
36 | :named_table,
37 | :ordered_set,
38 | :protected
39 | ])
40 |
41 | {:ok, %State{table: table}}
42 | end
43 |
44 | @doc false
45 | @impl Quantum.Storage
46 | def jobs(storage_pid), do: GenServer.call(storage_pid, :jobs)
47 |
48 | @doc false
49 | @impl Quantum.Storage
50 | def add_job(storage_pid, job), do: GenServer.cast(storage_pid, {:add_job, job})
51 |
52 | @doc false
53 | @impl Quantum.Storage
54 | def delete_job(storage_pid, job_name), do: GenServer.cast(storage_pid, {:delete_job, job_name})
55 |
56 | @doc false
57 | @impl Quantum.Storage
58 | def update_job_state(storage_pid, job_name, state),
59 | do: GenServer.cast(storage_pid, {:update_job_state, job_name, state})
60 |
61 | @doc false
62 | @impl Quantum.Storage
63 | def last_execution_date(storage_pid), do: GenServer.call(storage_pid, :last_execution_date)
64 |
65 | @doc false
66 | @impl Quantum.Storage
67 | def update_last_execution_date(storage_pid, last_execution_date),
68 | do: GenServer.cast(storage_pid, {:update_last_execution_date, last_execution_date})
69 |
70 | @doc false
71 | @impl Quantum.Storage
72 | def purge(storage_pid), do: GenServer.cast(storage_pid, :purge)
73 |
74 | @doc false
75 | @impl GenServer
76 | def handle_cast({:add_job, job}, %State{table: table} = state) do
77 | :ets.insert(table, entry = {job_key(job.name), job})
78 | :ets.insert(table, {:init_jobs})
79 |
80 | Logger.debug(fn ->
81 | "[#{inspect(Node.self())}][#{__MODULE__}] inserting [#{inspect(entry)}] into Persistent ETS table [#{
82 | table
83 | }]"
84 | end)
85 |
86 | {:noreply, state}
87 | end
88 |
89 | def handle_cast({:delete_job, job_name}, %State{table: table} = state) do
90 | :ets.delete(table, job_key(job_name))
91 |
92 | {:noreply, state}
93 | end
94 |
95 | def handle_cast({:update_job_state, job_name, job_state}, %State{table: table} = state) do
96 | table
97 | |> :ets.lookup(job_key(job_name))
98 | |> Enum.map(&{elem(&1, 0), %{elem(&1, 1) | state: job_state}})
99 | |> Enum.each(&:ets.update_element(table, elem(&1, 0), {2, elem(&1, 1)}))
100 |
101 | {:noreply, state}
102 | end
103 |
104 | def handle_cast(
105 | {:update_last_execution_date, last_execution_date},
106 | %State{table: table} = state
107 | ) do
108 | :ets.insert(table, {:last_execution_date, last_execution_date})
109 |
110 | {:noreply, state}
111 | end
112 |
113 | def handle_cast(:purge, %State{table: table} = state) do
114 | :ets.delete_all_objects(table)
115 |
116 | {:noreply, state}
117 | end
118 |
119 | @doc false
120 | @impl GenServer
121 | def handle_call(:jobs, _from, %State{table: table} = state) do
122 | {:reply,
123 | table
124 | |> :ets.lookup(:init_jobs)
125 | |> case do
126 | [{:init_jobs}] ->
127 | table
128 | |> :ets.match({{:job, :_}, :"$1"})
129 | |> List.flatten()
130 |
131 | [] ->
132 | :not_applicable
133 | end, state}
134 | end
135 |
136 | def handle_call(:last_execution_date, _from, %State{table: table} = state) do
137 | {:reply,
138 | table
139 | |> :ets.lookup(:last_execution_date)
140 | |> case do
141 | [] -> :unknown
142 | [{:last_execution_date, date} | _t] -> date
143 | end, state}
144 | end
145 |
146 | defp job_key(job_name) do
147 | {:job, job_name}
148 | end
149 | end
150 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Quantum Storage Persistent Ets
2 |
3 | [](https://opencollective.com/quantum)
4 | [](https://hex.pm/packages/quantum_storage_persistent_ets)
5 | [](https://hexdocs.pm/quantum_storage_persistent_ets)
6 | 
7 | [](https://coveralls.io/r/quantum-elixir/quantum-storage-persistent-ets?branch=master)
8 | [](https://hex.pm/packages/quantum_storage_persistent_ets)
9 |
10 | Adds a persistent storage adapter for ETS.
11 |
12 | ## Installation
13 |
14 | The package can be installed by adding `quantum_storage_persistent_ets` to your list
15 | of dependencies in `mix.exs`:
16 |
17 | ```elixir
18 | def deps do
19 | [
20 | {:quantum_storage_persistent_ets, "~> 1.0"}
21 | ]
22 | end
23 | ```
24 |
25 | To enable the storage adpater, add this to your `config.exs`:
26 |
27 | ```elixir
28 | use Mix.Config
29 |
30 | config :quantum_test, QuantumTest.Scheduler,
31 | storage: QuantumStoragePersistentEts
32 | ```
33 |
34 | The docs can be found at [https://hexdocs.pm/quantum_storage_persistent_ets](https://hexdocs.pm/quantum_storage_persistent_ets).
35 |
36 | ## Contribution
37 |
38 | This project uses the [Collective Code Construction Contract (C4)](http://rfc.zeromq.org/spec:42/C4/)
39 | for all code changes.
40 |
41 | > "Everyone, without distinction or discrimination, SHALL have an equal right to become a Contributor under the
42 | terms of this contract."
43 |
44 | ### tl;dr
45 |
46 | 1. Check for [open issues](https://github.com/quantum-elixir/quantum-storage-persistent-ets/issues) or [open a new issue](https://github.com/quantum-elixir/quantum-storage-persistent-ets/issues/new) to start
47 | a discussion around [a problem](https://www.youtube.com/watch?v=_QF9sFJGJuc).
48 | 2. Issues SHALL be named as "Problem: _description of the problem_".
49 | 3. Fork the [quantum-storage-persistent-ets repository on GitHub](https://github.com/quantum-elixir/quantum-storage-persistent-ets) to start making your changes
50 | 4. If possible, write a test which shows that the problem was solved.
51 | 5. Send a pull request.
52 | 6. Pull requests SHALL be named as "Solution: _description of your solution_"
53 | 7. Your pull request is merged and you are added to the [list of contributors](https://github.com/quantum-elixir/quantum-storage-persistent-ets/graphs/contributors)
54 |
55 | ### Code Contributors
56 |
57 | This project exists thanks to all the people who contribute.
58 |
59 |
60 | ### Financial Contributors
61 |
62 | Become a financial contributor and help us sustain our community. [[Contribute](https://opencollective.com/quantum/contribute)]
63 |
64 | #### Individuals
65 |
66 |
67 |
68 | #### Organizations
69 |
70 | Support this project with your organization. Your logo will show up here with a link to your website. [[Contribute](https://opencollective.com/quantum/contribute)]
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 | ## License
84 |
85 | [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0)
86 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/.github/workflows/elixir.yml:
--------------------------------------------------------------------------------
1 | on:
2 | - push
3 | - pull_request
4 |
5 | env:
6 | BUILD_EMBEDDED: true
7 | DIALYZER_PLT_PRIV: true
8 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
9 |
10 | jobs:
11 | deps:
12 | name: Install Deps
13 |
14 | runs-on: ubuntu-latest
15 |
16 | steps:
17 | - uses: actions/checkout@v2
18 | - uses: actions/setup-elixir@v1
19 | with:
20 | otp-version: 22.3
21 | elixir-version: 1.10.3
22 | - uses: actions/cache@v2
23 | id: cache
24 | with:
25 | path: deps
26 | key: deps-${{ runner.os }}-${{ github.ref }}
27 | restore-keys: |
28 | deps-${{ runner.os }}-
29 | deps-
30 | - run: mix deps.get
31 | - uses: actions/upload-artifact@v1
32 | with:
33 | name: deps
34 | path: deps
35 | - uses: actions/upload-artifact@v1
36 | with:
37 | name: deps_lock
38 | path: mix.lock
39 |
40 | compile_dev:
41 | name: Compile Dev Environment
42 |
43 | runs-on: ubuntu-latest
44 |
45 | needs: ['deps']
46 |
47 | steps:
48 | - uses: actions/checkout@v2
49 | - uses: actions/setup-elixir@v1
50 | with:
51 | otp-version: 22.3
52 | elixir-version: 1.10.3
53 | - uses: actions/download-artifact@v1
54 | with:
55 | name: deps
56 | path: deps
57 | - uses: actions/download-artifact@v1
58 | with:
59 | name: deps_lock
60 | path: .
61 | - uses: actions/cache@v2
62 | id: cache
63 | with:
64 | path: _build/dev
65 | key: compile_dev-${{ runner.os }}-${{ github.ref }}
66 | restore-keys: |
67 | compile_dev-${{ runner.os }}-
68 | compile_dev-
69 | - run: mix deps.compile
70 | env:
71 | MIX_ENV: dev
72 | - run: mix compile --warning-as-errors
73 | env:
74 | MIX_ENV: dev
75 | - uses: actions/upload-artifact@v1
76 | with:
77 | name: compile_dev
78 | path: _build/dev
79 |
80 | compile_docs:
81 | name: Compile Docs Environment
82 |
83 | runs-on: ubuntu-latest
84 |
85 | needs: ['deps']
86 |
87 | steps:
88 | - uses: actions/checkout@v2
89 | - uses: actions/setup-elixir@v1
90 | with:
91 | otp-version: 22.3
92 | elixir-version: 1.10.3
93 | - uses: actions/download-artifact@v1
94 | with:
95 | name: deps
96 | path: deps
97 | - uses: actions/download-artifact@v1
98 | with:
99 | name: deps_lock
100 | path: .
101 | - uses: actions/cache@v2
102 | id: cache
103 | with:
104 | path: _build/docs
105 | key: compile_docs${{ runner.os }}-${{ github.ref }}
106 | restore-keys: |
107 | compile_docs-${{ runner.os }}-
108 | compile_docs-
109 | - run: mix deps.compile
110 | env:
111 | MIX_ENV: docs
112 | - run: mix compile --warning-as-errors
113 | env:
114 | MIX_ENV: docs
115 | - uses: actions/upload-artifact@v1
116 | with:
117 | name: compile_docs
118 | path: _build/docs
119 |
120 | compile_test:
121 | name: Compile Test Environment (OTP ${{matrix.otp}} / Elixir ${{matrix.elixir}})
122 |
123 | runs-on: ubuntu-latest
124 |
125 | needs: ['deps']
126 |
127 | strategy:
128 | fail-fast: false
129 | matrix:
130 | otp: [21.3, 22.3, 23.0]
131 | elixir: [1.8.2, 1.9.4, 1.10.3]
132 |
133 | steps:
134 | - uses: actions/checkout@v2
135 | - uses: actions/setup-elixir@v1
136 | with:
137 | otp-version: ${{matrix.otp}}
138 | elixir-version: ${{matrix.elixir}}
139 | - uses: actions/download-artifact@v1
140 | with:
141 | name: deps
142 | path: deps
143 | - uses: actions/download-artifact@v1
144 | with:
145 | name: deps_lock
146 | path: .
147 | - uses: actions/cache@v2
148 | id: cache
149 | with:
150 | path: _build/test
151 | key: compile_test-${{matrix.otp}}-${{matrix.elixir}}-${{ runner.os }}-${{ github.ref }}
152 | restore-keys: |
153 | compile_test-${{matrix.otp}}-${{matrix.elixir}}-${{ runner.os }}-
154 | compile_test-${{matrix.otp}}-${{matrix.elixir}}-
155 | - run: mix deps.compile
156 | env:
157 | MIX_ENV: test
158 | - run: mix compile --warning-as-errors
159 | env:
160 | MIX_ENV: test
161 | - uses: actions/upload-artifact@v1
162 | with:
163 | name: compile_test-${{matrix.otp}}-${{matrix.elixir}}
164 | path: _build/test
165 |
166 | compile_prod:
167 | name: Compile Prod Environment
168 |
169 | runs-on: ubuntu-latest
170 |
171 | needs: ['deps']
172 |
173 | steps:
174 | - uses: actions/checkout@v2
175 | - uses: actions/setup-elixir@v1
176 | with:
177 | otp-version: 22.3
178 | elixir-version: 1.10.3
179 | - uses: actions/download-artifact@v1
180 | with:
181 | name: deps
182 | path: deps
183 | - uses: actions/download-artifact@v1
184 | with:
185 | name: deps_lock
186 | path: .
187 | - uses: actions/cache@v2
188 | id: cache
189 | with:
190 | path: _build/prod
191 | key: compile_prod-${{ runner.os }}-${{ github.ref }}
192 | restore-keys: |
193 | compile_prod-${{ runner.os }}-
194 | compile_prod-
195 | - run: mix deps.compile
196 | env:
197 | MIX_ENV: prod
198 | - run: mix compile --warning-as-errors
199 | env:
200 | MIX_ENV: prod
201 | - uses: actions/upload-artifact@v1
202 | with:
203 | name: compile_prod
204 | path: _build/prod
205 |
206 | format:
207 | name: Check Formatting
208 |
209 | runs-on: ubuntu-latest
210 |
211 | needs: ['deps']
212 |
213 | steps:
214 | - uses: actions/checkout@v2
215 | - uses: actions/setup-elixir@v1
216 | with:
217 | otp-version: 22.3
218 | elixir-version: 1.10.3
219 | - uses: actions/download-artifact@v1
220 | with:
221 | name: deps
222 | path: deps
223 | - uses: actions/download-artifact@v1
224 | with:
225 | name: deps_lock
226 | path: .
227 | - run: mix format --check-formatted
228 | env:
229 | MIX_ENV: dev
230 |
231 | test:
232 | name: Run Tests & Submit Coverage (OTP ${{matrix.otp}} / Elixir ${{matrix.elixir}})
233 |
234 | runs-on: ubuntu-latest
235 |
236 | strategy:
237 | fail-fast: false
238 | matrix:
239 | otp: [21.3, 22.3, 23.0]
240 | elixir: [1.8.2, 1.9.4, 1.10.3]
241 |
242 | needs: ['deps', 'compile_test']
243 |
244 | steps:
245 | - uses: actions/checkout@v2
246 | - uses: actions/setup-elixir@v1
247 | with:
248 | otp-version: ${{matrix.otp}}
249 | elixir-version: ${{matrix.elixir}}
250 | - uses: actions/download-artifact@v1
251 | with:
252 | name: deps
253 | path: deps
254 | - uses: actions/download-artifact@v1
255 | with:
256 | name: deps_lock
257 | path: .
258 | - uses: actions/download-artifact@v1
259 | with:
260 | name: compile_test-${{matrix.otp}}-${{matrix.elixir}}
261 | path: _build/test
262 | - run: mix coveralls.github
263 | env:
264 | MIX_ENV: test
265 |
266 | credo:
267 | name: Check Credo
268 |
269 | runs-on: ubuntu-latest
270 |
271 | needs: ['deps', 'compile_dev']
272 |
273 | steps:
274 | - uses: actions/checkout@v2
275 | - uses: actions/setup-elixir@v1
276 | with:
277 | otp-version: 22.3
278 | elixir-version: 1.10.3
279 | - uses: actions/download-artifact@v1
280 | with:
281 | name: deps
282 | path: deps
283 | - uses: actions/download-artifact@v1
284 | with:
285 | name: deps_lock
286 | path: .
287 | - uses: actions/download-artifact@v1
288 | with:
289 | name: compile_dev
290 | path: _build/dev
291 | - run: mix credo --strict
292 | env:
293 | MIX_ENV: dev
294 |
295 | dialyzer_plt:
296 | name: Generate Dialyzer PLT
297 |
298 | runs-on: ubuntu-latest
299 |
300 | needs: ['deps', 'compile_dev']
301 |
302 | steps:
303 | - uses: actions/checkout@v2
304 | - uses: actions/setup-elixir@v1
305 | with:
306 | otp-version: 22.3
307 | elixir-version: 1.10.3
308 | - uses: actions/download-artifact@v1
309 | with:
310 | name: deps
311 | path: deps
312 | - uses: actions/download-artifact@v1
313 | with:
314 | name: deps_lock
315 | path: .
316 | - uses: actions/download-artifact@v1
317 | with:
318 | name: compile_dev
319 | path: _build/dev
320 | - uses: actions/cache@v2
321 | id: cache
322 | with:
323 | path: priv/plts/
324 | key: dialyzer_plt_dev-${{ runner.os }}-${{ github.ref }}
325 | restore-keys: |
326 | dialyzer_plt_dev-${{ runner.os }}-
327 | dialyzer_plt_dev-
328 | - run: mix dialyzer --plt
329 | env:
330 | MIX_ENV: dev
331 | - uses: actions/upload-artifact@v1
332 | with:
333 | name: dialyzer_plt_dev
334 | path: priv/plts/
335 |
336 | dialyzer_test:
337 | name: "Check Dialyzer"
338 |
339 | runs-on: ubuntu-latest
340 |
341 | needs: ['deps', 'compile_dev', 'dialyzer_plt']
342 |
343 | steps:
344 | - uses: actions/checkout@v2
345 | - uses: actions/setup-elixir@v1
346 | with:
347 | otp-version: 22.3
348 | elixir-version: 1.10.3
349 | - uses: actions/download-artifact@v1
350 | with:
351 | name: deps
352 | path: deps
353 | - uses: actions/download-artifact@v1
354 | with:
355 | name: deps_lock
356 | path: .
357 | - uses: actions/download-artifact@v1
358 | with:
359 | name: compile_dev
360 | path: _build/dev
361 | - uses: actions/download-artifact@v1
362 | with:
363 | name: dialyzer_plt_dev
364 | path: priv/plts/
365 | - run: mix dialyzer --halt-exit-status
366 | env:
367 | MIX_ENV: dev
368 |
369 | docs:
370 | name: "Generate Docs"
371 |
372 | runs-on: ubuntu-latest
373 |
374 | needs: ['deps', 'compile_docs']
375 |
376 | steps:
377 | - uses: actions/checkout@v2
378 | - uses: actions/setup-elixir@v1
379 | with:
380 | otp-version: 22.3
381 | elixir-version: 1.10.3
382 | - uses: actions/download-artifact@v1
383 | with:
384 | name: deps
385 | path: deps
386 | - uses: actions/download-artifact@v1
387 | with:
388 | name: deps_lock
389 | path: .
390 | - uses: actions/download-artifact@v1
391 | with:
392 | name: compile_docs
393 | path: _build/docs
394 | - run: mix docs
395 | env:
396 | MIX_ENV: docs
397 | - uses: actions/upload-artifact@v1
398 | with:
399 | name: docs
400 | path: doc
--------------------------------------------------------------------------------