diff --git a/.circleci/config.yml b/.circleci/config.yml index 78b729e..b4923dc 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,26 +1,25 @@ -version: 2 +version: 2.1 + jobs: build: docker: - image: elixir:1.8.2-alpine - name: app + name: app environment: - MIX_ENV: test - DATABASE_USER: user - DATABASE_PASSWORD: pass - DATABASE_PORT: 5432 - DATABASE_HOST: db - DATABASE_NAME: ecto_job_scheduler_test - DATABASE_POOL_SIZE: 5 - depends_on: - - db + MIX_ENV: test + DATABASE_USER: user + DATABASE_PASSWORD: pass + DATABASE_PORT: "5432" + DATABASE_HOST: db + DATABASE_NAME: ecto_job_scheduler_test + DATABASE_POOL_SIZE: "5" - image: postgres:9.6-alpine name: db environment: POSTGRES_USER: user POSTGRES_PASSWORD: pass POSTGRES_DB: ecto_job_scheduler_test - + working_directory: ~/app steps: @@ -29,20 +28,31 @@ jobs: - run: mix do deps.get, compile --warnings-as-errors - run: mix format --check-formatted - run: mix credo --strict + - run: sh -c 'while true; do nc -z db 5432; if [[ "$?" == 0 ]]; then break; fi; sleep 1; done' - run: mix do ecto.create, ecto.migrate - run: mix coveralls.html + - restore_cache: + keys: + - plt-cache-{{ checksum "mix.lock" }}-{{ .Branch }} + - plt-cache-{{ checksum "mix.lock" }} - run: MIX_ENV=dev mix dialyzer --plt + - save_cache: + key: plt-cache-{{ checksum "mix.lock" }}-{{ .Branch }} + paths: + - _dialyzer/ecto-job-scheduler.plt + - save_cache: + key: plt-cache-{{ checksum "mix.lock" }} + paths: + - _dialyzer/ecto-job-scheduler.plt + - run: MIX_ENV=dev mix dialyzer --format short - store_artifacts: path: cover/ - - + workflows: version: 2 build-and-deploy: jobs: - build: filters: - branches: - only: /.*/ tags: only: /.*/ diff --git a/.gitignore b/.gitignore index 972d40d..bcc4ef9 100644 --- a/.gitignore +++ b/.gitignore @@ -24,5 +24,4 @@ ecto_job_scheduler-*.tar .elixir_ls/* # Dialyzer -/priv/plts/*.plt -/priv/plts/*.plt.hash +_dialyzer/* diff --git a/CHANGELOG.md b/CHANGELOG.md index 1848c24..af26fbc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,5 @@ # Changelog + All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), @@ -6,25 +7,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.1.0] + +## Added + +- Support for new_relic instrumentation for the jobs + ## [1.0.2] - 2020-02-18 -### Fixes +### Fixes - Perform result ## [1.0.1] - 2020-02-11 -### Fixes +### Fixes - Allow MFA tuple to be given sanitizer config ## [1.0.0] - 2020-01-22 -### Added +### Added - Added support for ecto_job 3 -[Unreleased]: https://github.com/rai200890/ecto-job-scheduler/compare/v1.0.2...HEAD +[Unreleased]: https://github.com/rai200890/ecto-job-scheduler/compare/v1.1.0...HEAD +[1.1.0]: https://github.com/rai200890/ecto-job-scheduler/compare/v1.0.2...1.1.0 [1.0.2]: https://github.com/rai200890/ecto-job-scheduler/compare/v1.0.1...v1.0.2 [1.0.1]: https://github.com/rai200890/ecto-job-scheduler/compare/v1.0.0...v1.0.1 -[1.0.0]: https://github.com/rai200890/ecto-job-scheduler/compare/v0.7.0...v1.0.0 \ No newline at end of file +[1.0.0]: https://github.com/rai200890/ecto-job-scheduler/compare/v0.7.0...v1.0.0 diff --git a/README.md b/README.md index 7cf42cb..1a34ba1 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Helpers for scheduling Jobs defined in [EctoJob](https://github.com/mbuhot/ecto_job) -Thanks [joaothallis](https://github.com/joaothallis), [ramondelemos](https://github.com/ramondelemos), [victorprs](https://github.com/victorprs) +Thanks [joaothallis](https://github.com/joaothallis), [ramondelemos](https://github.com/ramondelemos), [victorprs](https://github.com/victorprs) ## Installation @@ -59,6 +59,20 @@ defmodule MyApplication.MyJobQueue do end ``` +If you want new_relic instrumentation in your jobs, add new_relic_agent to the deps and + +```elixir +defmodule MyApplication.MyJobQueue do + @moduledoc false + use EctoJobScheduler.JobQueue, + table_name: "test_jobs", + jobs: [ + MyApplication.MyJob + ], + instrumenter: :new_relic +end +``` + ### Define scheduler module for job queue ```elixir @@ -92,4 +106,4 @@ config :my_application, MyApplication.MyJob, max_attempts: "15" multi = Multi.run(:do_my_thing, fn _repo, _changes -> {:ok, :xablau} end) multi = MyJobScheduler.schedule(multi, MyJob, %{"input" => "a"}) result = MyJobScheduler.run(multi) -``` \ No newline at end of file +``` diff --git a/VERSION b/VERSION index ee90284..9084fa2 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.0.4 +1.1.0 diff --git a/config/test.exs b/config/test.exs index a83e335..9db27ab 100644 --- a/config/test.exs +++ b/config/test.exs @@ -21,3 +21,7 @@ end config :ecto_job_scheduler, sanitizer: sanitize_fun config :logger, level: :warn + +config :ecto_job_scheduler, EctoJobScheduler.NewRelic.JobInstrumenter, + transaction: TransactionMock, + reporter: ReporterMock diff --git a/lib/job_queue.ex b/lib/job_queue.ex index 520a5ad..d05f831 100644 --- a/lib/job_queue.ex +++ b/lib/job_queue.ex @@ -3,21 +3,44 @@ defmodule EctoJobScheduler.JobQueue do Defines EctoJob.JobQueue based on defined EctoJobScheduler.Job """ + # credo:disable-for-this-file Credo.Check.Refactor.Nesting + defmacro __using__(options \\ []) do table_name = options[:table_name] jobs = options[:jobs] + instrumenter = options[:instrumenter] - quote bind_quoted: [table_name: table_name, jobs: jobs] do + quote bind_quoted: [table_name: table_name, jobs: jobs, instrumenter: instrumenter], + location: :keep do use EctoJob.JobQueue, table_name: table_name require Logger alias Ecto.Multi + alias EctoJobScheduler.NewRelic.JobInstrumenter Enum.each(jobs, fn job -> type = job |> Atom.to_string() |> String.split(".") |> List.last() - def perform(%Multi{} = multi, %{"type" => unquote(type)} = job_params) do - apply(unquote(job), :perform, [multi, job_params]) + case instrumenter do + :new_relic -> + def perform(%Multi{} = multi, %{"type" => unquote(type)} = job_params) do + case job_params["request_id"] do + nil -> + nil + + request_id -> + Logger.metadata(request_id: request_id) + end + + JobInstrumenter.transaction("job/#{unquote(type)}", fn -> + apply(unquote(job), :perform, [multi, job_params]) + end) + end + + _ -> + def perform(%Multi{} = multi, %{"type" => unquote(type)} = job_params) do + apply(unquote(job), :perform, [multi, job_params]) + end end end) end diff --git a/lib/new_relic/job_instrumenter.ex b/lib/new_relic/job_instrumenter.ex new file mode 100644 index 0000000..bdb0682 --- /dev/null +++ b/lib/new_relic/job_instrumenter.ex @@ -0,0 +1,78 @@ +defmodule EctoJobScheduler.NewRelic.JobInstrumenter do + @moduledoc """ + Tool for capture metrics to NewRelic. + """ + + @doc """ + Execute a function and capture metrics to NewRelic from it. + The metrics is grouped with name parameter. + + Example of use: + + NewRelic.JobInstrumenter.transaction("job/1", fn -> + ... + end) + """ + @spec transaction( + name :: String.t(), + function :: (() -> {:error, term()} | any() | no_return()) + ) :: + term() + def transaction(name, function) do + start() + + add_attributes( + other_transaction_name: name, + request_id: get_request_id() + ) + + case function.() do + {:error, reason} -> + {:current_stacktrace, stack} = Process.info(self(), :current_stacktrace) + fail(:error, reason, stack) + complete() + {:error, reason} + + result -> + complete() + result + end + rescue + exception -> + fail(exception.__struct__, Exception.message(exception), __STACKTRACE__) + complete() + reraise exception, __STACKTRACE__ + end + + defp start do + reporter().start() + end + + defp add_attributes(attributes) do + reporter().add_attributes(attributes) + end + + defp fail(kind, reason, stack) do + reporter().fail(self(), %{ + kind: kind, + reason: reason, + stack: stack + }) + end + + defp complete do + transaction().stop_transaction() + end + + defp get_request_id do + Keyword.get(Logger.metadata(), :request_id) + end + + defp reporter, + do: + Application.get_env(:ecto_job_scheduler, __MODULE__)[:reporter] || + NewRelic.Transaction.Reporter + + defp transaction, + do: Application.get_env(:ecto_job_scheduler, __MODULE__)[:transaction] || NewRelic.Transaction +end diff --git a/lib/new_relic/reporter.ex b/lib/new_relic/reporter.ex new file mode 100644 index 0000000..3b74d21 --- /dev/null +++ b/lib/new_relic/reporter.ex @@ -0,0 +1,11 @@ +defmodule EctoJobScheduler.NewRelic.Reporter do + @moduledoc false + + @callback start() :: term() + + @callback add_attributes(keyword()) :: term() + + @callback fail(pid(), map()) :: term() + + @callback complete(pid(), atom()) :: term() +end diff --git a/lib/new_relic/transaction.ex b/lib/new_relic/transaction.ex new file mode 100644 index 0000000..57df2d0 --- /dev/null +++ b/lib/new_relic/transaction.ex @@ -0,0 +1,5 @@ +defmodule EctoJobScheduler.NewRelic.TransactionBehaviour do + @moduledoc false + + @callback stop_transaction() :: :ok +end diff --git a/mix.exs b/mix.exs index d2da433..69b5041 100644 --- a/mix.exs +++ b/mix.exs @@ -24,7 +24,7 @@ defmodule EctoJobScheduler.MixProject do extras: ["README.md"] ], dialyzer: [ - plt_file: {:no_warn, "priv/plts/dialyzer.plt"}, + plt_file: {:no_warn, "_dialyzer/ecto-job-scheduler.plt"}, remove_defaults: [:unknown] ] ] @@ -56,10 +56,13 @@ defmodule EctoJobScheduler.MixProject do defp deps do [ {:ecto_job, "~> 3.0"}, - {:credo, "~> 1.1", only: [:dev, :test], runtime: false}, + {:ecto_sql, "~> 3.4"}, + {:credo, "~> 1.4", only: [:dev, :test], runtime: false}, {:excoveralls, "~> 0.10", only: :test}, {:ex_doc, "~> 0.14", only: :dev, runtime: false}, - {:dialyxir, "~> 1.0", only: [:dev], runtime: false} + {:dialyxir, "~> 1.0", only: [:dev], runtime: false}, + {:new_relic_agent, "~> 1.19", optional: true}, + {:mox, "~> 0.5", only: [:dev, :test], runtime: false} ] end end diff --git a/mix.lock b/mix.lock index f809e28..3d9d88d 100644 --- a/mix.lock +++ b/mix.lock @@ -2,28 +2,33 @@ "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"}, "certifi": {:hex, :certifi, "2.5.1", "867ce347f7c7d78563450a18a6a28a8090331e77fa02380b4a21962a65d36ee5", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm", "805abd97539caf89ec6d4732c91e62ba9da0cda51ac462380bbd28ee697a8c42"}, "connection": {:hex, :connection, "1.0.4", "a1cae72211f0eef17705aaededacac3eb30e6625b04a6117c1b2db6ace7d5976", [:mix], [], "hexpm", "4a0850c9be22a43af9920a71ab17c051f5f7d45c209e40269a1938832510e4d9"}, - "credo": {:hex, :credo, "1.1.0", "e0c07b2fd7e2109495f582430a1bc96b2c71b7d94c59dfad120529f65f19872f", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "7338d04b30026e30adbcaaedbf0eb7e4d749510d90c2708ff8cc100fa9c8291f"}, - "db_connection": {:hex, :db_connection, "2.2.0", "e923e88887cd60f9891fd324ac5e0290954511d090553c415fbf54be4c57ee63", [:mix], [{:connection, "~> 1.0.2", [hex: :connection, repo: "hexpm", optional: false]}], "hexpm", "bdf196feedfa6b83071e808b2b086fb113f8a1c4c7761f6eff6fe4b96aba0086"}, + "credo": {:hex, :credo, "1.4.0", "92339d4cbadd1e88b5ee43d427b639b68a11071b6f73854e33638e30a0ea11f5", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "1fd3b70dce216574ce3c18bdf510b57e7c4c85c2ec9cad4bff854abaf7e58658"}, + "db_connection": {:hex, :db_connection, "2.2.2", "3bbca41b199e1598245b716248964926303b5d4609ff065125ce98bcd368939e", [:mix], [{:connection, "~> 1.0.2", [hex: :connection, repo: "hexpm", optional: false]}], "hexpm", "642af240d8a8affb93b4ba5a6fcd2bbcbdc327e1a524b825d383711536f8070c"}, "decimal": {:hex, :decimal, "1.8.1", "a4ef3f5f3428bdbc0d35374029ffcf4ede8533536fa79896dd450168d9acdf3c", [:mix], [], "hexpm", "3cb154b00225ac687f6cbd4acc4b7960027c757a5152b369923ead9ddbca7aec"}, "dialyxir": {:hex, :dialyxir, "1.0.0", "6a1fa629f7881a9f5aaf3a78f094b2a51a0357c843871b8bc98824e7342d00a5", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "aeb06588145fac14ca08d8061a142d52753dbc2cf7f0d00fc1013f53f8654654"}, "earmark": {:hex, :earmark, "1.3.2", "b840562ea3d67795ffbb5bd88940b1bed0ed9fa32834915125ea7d02e35888a5", [:mix], [], "hexpm", "e3be2bc3ae67781db529b80aa7e7c49904a988596e2dbff897425b48b3581161"}, - "ecto": {:hex, :ecto, "3.3.1", "82ab74298065bf0c64ca299f6c6785e68ea5d6b980883ee80b044499df35aba1", [:mix], [{:decimal, "~> 1.6", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "e6c614dfe3bcff2d575ce16d815dbd43f4ee1844599a83de1eea81976a31c174"}, + "ecto": {:hex, :ecto, "3.4.5", "2bcd262f57b2c888b0bd7f7a28c8a48aa11dc1a2c6a858e45dd8f8426d504265", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "8c6d1d4d524559e9b7a062f0498e2c206122552d63eacff0a6567ffe7a8e8691"}, "ecto_job": {:hex, :ecto_job, "3.0.0", "ae3da338fce92d58f76dcaa04400678453298c466897b07f775f646ca16ac41a", [:make, :mix], [{:ecto_sql, "~> 3.2", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:gen_stage, "~> 0.14", [hex: :gen_stage, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.15", [hex: :postgrex, repo: "hexpm", optional: false]}], "hexpm", "fe7795aaeab3d81c0381bcf1aad6484b834e468941fa48f64fa897cfba54538c"}, - "ecto_sql": {:hex, :ecto_sql, "3.3.2", "92804e0de69bb63e621273c3492252cb08a29475c05d40eeb6f41ad2d483cfd3", [:mix], [{:db_connection, "~> 2.2", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.3", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.3.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.15.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "b82d89d4e6a9f7f7f04783b07e8b0af968e0be2f01ee4b39047fe727c5c07471"}, + "ecto_sql": {:hex, :ecto_sql, "3.4.4", "d28bac2d420f708993baed522054870086fd45016a9d09bb2cd521b9c48d32ea", [:mix], [{:db_connection, "~> 2.2", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.4.3", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.3.0 or ~> 0.4.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.15.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.0", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "edb49af715dd72f213b66adfd0f668a43c17ed510b5d9ac7528569b23af57fe8"}, "erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"}, "ex_doc": {:hex, :ex_doc, "0.20.2", "1bd0dfb0304bade58beb77f20f21ee3558cc3c753743ae0ddbb0fd7ba2912331", [:mix], [{:earmark, "~> 1.3", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.10", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm", "8e24fc8ff9a50b9f557ff020d6c91a03cded7e59ac3e0eec8a27e771430c7d27"}, "excoveralls": {:hex, :excoveralls, "0.11.1", "dd677fbdd49114fdbdbf445540ec735808250d56b011077798316505064edb2c", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "493daf5a2dd92d022a1c29e7edcc30f1bce1ffe10fb3690fac63889346d3af2f"}, "gen_stage": {:hex, :gen_stage, "0.14.3", "d0c66f1c87faa301c1a85a809a3ee9097a4264b2edf7644bf5c123237ef732bf", [:mix], [], "hexpm", "8453e2289d94c3199396eb517d65d6715ef26bcae0ee83eb5ff7a84445458d76"}, "hackney": {:hex, :hackney, "1.15.1", "9f8f471c844b8ce395f7b6d8398139e26ddca9ebc171a8b91342ee15a19963f4", [:rebar3], [{:certifi, "2.5.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.4", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm", "c2790c9f0f7205f4a362512192dee8179097394400e745e4d20bab7226a8eaad"}, "idna": {:hex, :idna, "6.0.0", "689c46cbcdf3524c44d5f3dde8001f364cd7608a99556d8fbd8239a5798d4c10", [:rebar3], [{:unicode_util_compat, "0.4.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "4bdd305eb64e18b0273864920695cb18d7a2021f31a11b9c5fbcd9a253f936e2"}, - "jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fdf843bca858203ae1de16da2ee206f53416bbda5dc8c9e78f43243de4bc3afe"}, + "jason": {:hex, :jason, "1.2.1", "12b22825e22f468c02eb3e4b9985f3d0cb8dc40b9bd704730efa11abd2708c44", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "b659b8571deedf60f79c5a608e15414085fa141344e2716fbd6988a084b5f993"}, "makeup": {:hex, :makeup, "0.8.0", "9cf32aea71c7fe0a4b2e9246c2c4978f9070257e5c9ce6d4a28ec450a839b55f", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "5fbc8e549aa9afeea2847c0769e3970537ed302f93a23ac612602e805d9d1e7f"}, "makeup_elixir": {:hex, :makeup_elixir, "0.13.0", "be7a477997dcac2e48a9d695ec730b2d22418292675c75aa2d34ba0909dcdeda", [:mix], [{:makeup, "~> 0.8", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "adf0218695e22caeda2820eaba703fa46c91820d53813a2223413da3ef4ba515"}, "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"}, + "mime": {:hex, :mime, "1.3.1", "30ce04ab3175b6ad0bdce0035cba77bba68b813d523d1aac73d9781b4d193cf8", [:mix], [], "hexpm", "6cbe761d6a0ca5a31a0931bf4c63204bceb64538e664a8ecf784a9a6f3b875f1"}, "mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"}, + "mox": {:hex, :mox, "0.5.2", "55a0a5ba9ccc671518d068c8dddd20eeb436909ea79d1799e2209df7eaa98b6c", [:mix], [], "hexpm", "df4310628cd628ee181df93f50ddfd07be3e5ecc30232d3b6aadf30bdfe6092b"}, + "new_relic_agent": {:hex, :new_relic_agent, "1.19.1", "843d19f361c3261e68308449124aa5b5cc4ef9aa5a9da2b7dfc1ff0e66c5834d", [:mix], [{:ecto, ">= 3.4.1", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_sql, ">= 3.4.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:redix, ">= 0.11.0", [hex: :redix, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "6f87fd44c39eebc8a845b4b8a031c884226d5386599f70e2812d8880724898e8"}, "nimble_parsec": {:hex, :nimble_parsec, "0.5.0", "90e2eca3d0266e5c53f8fbe0079694740b9c91b6747f2b7e3c5d21966bba8300", [:mix], [], "hexpm", "5c040b8469c1ff1b10093d3186e2e10dbe483cd73d79ec017993fb3985b8a9b3"}, "parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm", "17ef63abde837ad30680ea7f857dd9e7ced9476cdd7b0394432af4bfc241b960"}, - "postgrex": {:hex, :postgrex, "0.15.3", "5806baa8a19a68c4d07c7a624ccdb9b57e89cbc573f1b98099e3741214746ae4", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "4737ce62a31747b4c63c12b20c62307e51bb4fcd730ca0c32c280991e0606c90"}, + "plug": {:hex, :plug, "1.10.3", "c9cebe917637d8db0e759039cc106adca069874e1a9034fd6e3fdd427fd3c283", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "01f9037a2a1de1d633b5a881101e6a444bcabb1d386ca1e00bb273a1f1d9d939"}, + "plug_crypto": {:hex, :plug_crypto, "1.1.2", "bdd187572cc26dbd95b87136290425f2b580a116d3fb1f564216918c9730d227", [:mix], [], "hexpm", "6b8b608f895b6ffcfad49c37c7883e8df98ae19c6a28113b02aa1e9c5b22d6b5"}, + "postgrex": {:hex, :postgrex, "0.15.5", "aec40306a622d459b01bff890fa42f1430dac61593b122754144ad9033a2152f", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "ed90c81e1525f65a2ba2279dbcebf030d6d13328daa2f8088b9661eb9143af7f"}, "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.4", "f0eafff810d2041e93f915ef59899c923f4568f4585904d010387ed74988e77b", [:make, :mix, :rebar3], [], "hexpm", "603561dc0fd62f4f2ea9b890f4e20e1a0d388746d6e20557cafb1b16950de88c"}, "telemetry": {:hex, :telemetry, "0.4.1", "ae2718484892448a24470e6aa341bc847c3277bfb8d4e9289f7474d752c09c7f", [:rebar3], [], "hexpm", "4738382e36a0a9a2b6e25d67c960e40e1a2c95560b9f936d8e29de8cd858480f"}, "unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm", "1d1848c40487cdb0b30e8ed975e34e025860c02e419cb615d255849f3427439d"}, diff --git a/test/job_queue_test.exs b/test/job_queue_test.exs index 964c31a..30cf15b 100644 --- a/test/job_queue_test.exs +++ b/test/job_queue_test.exs @@ -6,110 +6,130 @@ defmodule EctoJobScheduler.JobQueueTest do alias EctoJobScheduler.Test.EctoJobHelpers alias EctoJobScheduler.Test.Repo alias EctoJobScheduler.Test.TestJobQueue + alias EctoJobScheduler.Test.TestJobQueueNewRelic @moduletag :capture_log describe "perform/3" do - test "when job returns multi and return is successful, should delete job" do - job_args = %{ - "type" => "TestJob", - "little master" => "Rai99", - "cpf" => "12345678910", - "xablau" => "jo", - "context" => %{some: :thing} - } + Enum.each([TestJobQueue, TestJobQueueNewRelic], fn job_queue -> + setup do + if unquote(job_queue) == TestJobQueueNewRelic do + ReporterMock + |> Mox.expect(:start, fn -> :ok end) + |> Mox.expect(:add_attributes, fn _ -> :ok end) - EctoJobHelpers.build_initial_multi(Repo, TestJobQueue, job_args) + Mox.expect(TransactionMock, :stop_transaction, fn -> :ok end) + end - job = Repo.one(TestJobQueue) + %{} + end - assert {:ok, %{test_job: :xablau}} = EctoJobHelpers.dispatch_job(Repo, TestJobQueue, job) + test "#{job_queue} when job returns multi and return is successful, should delete job" do + job_args = %{ + "type" => "TestJob", + "little master" => "Rai99", + "cpf" => "12345678910", + "xablau" => "jo", + "context" => %{some: :thing} + } - assert Repo.all(TestJobQueue) == [] + EctoJobHelpers.build_initial_multi(Repo, unquote(job_queue), job_args) - assert [ - params: %{"type" => "TestJob"}, - max_attempts: 5, - attempt: 1, - some: "thing" - ] = Context.get() - end + job = Repo.one(unquote(job_queue)) - test "when job returns multi and return fails, should update job attempt" do - job_args = %{ - "type" => "TestJobError", - "context" => %{some: :thing} - } + assert {:ok, %{test_job: :xablau}} = + EctoJobHelpers.dispatch_job(Repo, unquote(job_queue), job) - EctoJobHelpers.build_initial_multi(Repo, TestJobQueue, job_args) + assert Repo.all(unquote(job_queue)) == [] - job = Repo.one(TestJobQueue) + assert [ + params: %{"type" => "TestJob"}, + max_attempts: 5, + attempt: 1, + some: "thing" + ] = Context.get() + end + + test "#{job_queue} when job returns multi and return fails, should update job attempt" do + job_args = %{ + "type" => "TestJobError", + "context" => %{some: :thing} + } + + EctoJobHelpers.build_initial_multi(Repo, unquote(job_queue), job_args) + + job = Repo.one(unquote(job_queue)) - assert {:error, :test_job, :xablau, %{}} = - EctoJobHelpers.dispatch_job(Repo, TestJobQueue, job) + assert {:error, :test_job, :xablau, %{}} = + EctoJobHelpers.dispatch_job(Repo, unquote(job_queue), job) - assert [ - %TestJobQueue{ + assert [ + %unquote(job_queue){ + attempt: 1, + params: %{"context" => %{"some" => "thing"}, "type" => "TestJobError"} + } + ] = Repo.all(unquote(job_queue)) + + assert [ + params: %{"type" => "TestJobError"}, + max_attempts: 5, attempt: 1, - params: %{"context" => %{"some" => "thing"}, "type" => "TestJobError"} - } - ] = Repo.all(TestJobQueue) + some: "thing" + ] = Context.get() + end + + test "#{job_queue} when job doesn't return multi and return is successful, should delete job" do + job_args = %{ + "type" => "TestJobNotMultiSuccessful", + "context" => %{some: :thing} + } - assert [ - params: %{"type" => "TestJobError"}, - max_attempts: 5, - attempt: 1, - some: "thing" - ] = Context.get() - end + EctoJobHelpers.build_initial_multi(Repo, unquote(job_queue), job_args) - test "when job doesn't return multi and return is successful, should delete job" do - job_args = %{ - "type" => "TestJobNotMultiSuccessful", - "context" => %{some: :thing} - } + job = Repo.one(unquote(job_queue)) - EctoJobHelpers.build_initial_multi(Repo, TestJobQueue, job_args) + assert {:ok, :xablau} == EctoJobHelpers.dispatch_job(Repo, unquote(job_queue), job) - job = Repo.one(TestJobQueue) + assert Repo.all(unquote(job_queue)) == [] - assert {:ok, :xablau} == EctoJobHelpers.dispatch_job(Repo, TestJobQueue, job) + assert [ + params: %{"type" => "TestJobNotMultiSuccessful"}, + max_attempts: 5, + attempt: 1, + some: "thing" + ] = Context.get() + end - assert Repo.all(TestJobQueue) == [] + test "#{job_queue} when job doesn't return multi and fails, should update job attempt" do + if unquote(job_queue) == TestJobQueueNewRelic do + Mox.expect(ReporterMock, :fail, fn _, _ -> :ok end) + end - assert [ - params: %{"type" => "TestJobNotMultiSuccessful"}, - max_attempts: 5, - attempt: 1, - some: "thing" - ] = Context.get() - end + job_args = %{ + "type" => "TestJobNotMultiError", + "context" => %{some: :thing} + } - test "when job doesn't return multi and fails, should update job attempt" do - job_args = %{ - "type" => "TestJobNotMultiError", - "context" => %{some: :thing} - } + EctoJobHelpers.build_initial_multi(Repo, unquote(job_queue), job_args) - EctoJobHelpers.build_initial_multi(Repo, TestJobQueue, job_args) + job = Repo.one(unquote(job_queue)) - job = Repo.one(TestJobQueue) + assert {:error, :sad_keanu} == EctoJobHelpers.dispatch_job(Repo, unquote(job_queue), job) - assert {:error, :sad_keanu} == EctoJobHelpers.dispatch_job(Repo, TestJobQueue, job) + assert [ + %unquote(job_queue){ + attempt: 1, + params: %{"context" => %{"some" => "thing"}, "type" => "TestJobNotMultiError"} + } + ] = Repo.all(unquote(job_queue)) - assert [ - %TestJobQueue{ + assert [ + params: %{"type" => "TestJobNotMultiError"}, + max_attempts: 5, attempt: 1, - params: %{"context" => %{"some" => "thing"}, "type" => "TestJobNotMultiError"} - } - ] = Repo.all(TestJobQueue) - - assert [ - params: %{"type" => "TestJobNotMultiError"}, - max_attempts: 5, - attempt: 1, - some: "thing" - ] = Context.get() - end + some: "thing" + ] = Context.get() + end + end) end end diff --git a/test/mocks.ex b/test/mocks.ex new file mode 100644 index 0000000..a321a72 --- /dev/null +++ b/test/mocks.ex @@ -0,0 +1,2 @@ +Mox.defmock(ReporterMock, for: EctoJobScheduler.NewRelic.Reporter) +Mox.defmock(TransactionMock, for: EctoJobScheduler.NewRelic.TransactionBehaviour) diff --git a/test/support/test_job.ex b/test/support/test_job.ex index a8fa3a2..fcb1e33 100644 --- a/test/support/test_job.ex +++ b/test/support/test_job.ex @@ -53,6 +53,20 @@ defmodule EctoJobScheduler.Test.TestJobQueue do max_attempts: "5" end +defmodule EctoJobScheduler.Test.TestJobQueueNewRelic do + @moduledoc false + use EctoJobScheduler.JobQueue, + table_name: "test_jobs", + jobs: [ + EctoJobScheduler.Test.TestJob, + EctoJobScheduler.Test.TestJobError, + EctoJobScheduler.Test.TestJobNotMultiSuccessful, + EctoJobScheduler.Test.TestJobNotMultiError + ], + max_attempts: "5", + instrumenter: :new_relic +end + defmodule EctoJobScheduler.Test.TestJobScheduler do @moduledoc false use EctoJobScheduler.JobScheduler, diff --git a/test/test_helper.exs b/test/test_helper.exs index 8531b9d..ae214fd 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -1,3 +1,4 @@ EctoJobScheduler.Test.Repo.start_link() +Application.ensure_all_started(:mox) ExUnit.start()