Need some OTP coaching to use ExRated

I’m trying to use ExRated to rate limit mail. I’m struggling with two things because I don’t have a strong knowledge of OTP.

The installation instructions say to add these into mix.exs

  [{:ex_rated, "~> 2.0"}]
end
  [applications: [:ex_rated]]
end

Yep, yep … I know to add :ex_rated to “extra_applications:” since I’m on a newer version of elixir.

But here is where I get confused …

There are no instructions to add ExRated to my “children” list in the start() function of application.ex. If ExRated stores state using an OTP server, then doesn’t it need to be started and supervised?

The instructions say that I can also start it manually by calling:
{:ok, pid} = GenServer.start_link(ExRated, [ {:timeout, 10_000}, {:cleanup_rate, 10_000}, {:persistent, false} ], [name: :ex_rated])

I would prefer it to start automatically with my app. If I want it to start automatically, then don’t I need to add the module to my start children[] list in application.ex?

The other thing that is confusing for me is that he says to run:
mix test —no-start
when I do tests. I understand why, but the execution is going to get tricky.

I can’t change my mix alias for test to be “test --no-start” because I need some of my other servers to run. I was going to follow advice by @mbklein and use environment variables to only run ExRated’s OTP server if i’m not in :test mode. But I can’t set up that condition in the applixation.ex start function … if ExRated isn’t listed there.

I must be missing something. Any advice would be most appreciated.

1 Like

Adding the application should have its own Supervisor according to https://github.com/grempe/ex_rated/blob/master/lib/ex_rated_app.ex. Alternatively, you could remove it from your extra_applications and copy the information manually but it would be potentially risky as all that could theoretically change in the future.

As far as mix test --no-start it seems to make sense if you’re testing it’s functionality or via integration tests. There is also overhead in starting up your application but if you’re doing it anyway, would one more process be a problem? If all your tests pass before adding it and things go haywire then it’d be worth jumping through the hoops. It’s worth it to keep your tests lean but it’s also worth measuring first because YAGNI could also apply.

1 Like

Thank you for the help @w0rd-driven!

Is it ok for me to just add this line to my children:
{ExRated, Application.fetch_env!(:myApp, ExRated)},

I’m a bit confused about what adding :ex_rated to extra_applications does. Is that starting up the ExRated server? I thought it was just forcing it to compile when I “mixed” my project.

I see what you’re saying about testing. If I’m not testing mail going through rate-limiting, then it doesn’t make sense to start up that server. I just can’t shut off all of my Tasks. I’ll see if it really slows down testing.

Your fetch_env has to match the expected output and I personally haven’t seen config variables take the shape of a child spec. I’ve more often seen functions in application.ex built out like the link you gave.

There are 2 primers on application behavior, Elixir :applications vs :extra_applications - a guide | AmberBit Sp. z o. o. and Supervisor and Application - The Elixir programming language. I’d read all of both but I focused on the relevant starting point of the guide.

The tl;dr is by adding it as an application, it’s processes start as a dependency before your application’s supervisor.

2 Likes

Thank you!! Those links were super helpful. I’ve been climbing such a steep learning curve that I’ve only scratched the surface on some topics. Those links helped me better understand what’s happening in mix.ex. Now I understand what he was recommending. Thanks for the mentoring!

This is a tricky situation where it’s hard to find documentation because people don’t write much about not doing things.

To use ExRated as released:

  • add it to deps as already mentioned

  • put configuration in the place specified in the README:

    config :ex_rated,
      timeout: 10_000,
      cleanup_rate: 10_000,
      persistent: false,
      name: :ex_rated,
      ets_table_name: :ets_rated_test_buckets
    

Mix will pick up the application definition from ExRated’s mix.exs and ensure that it is started before your application.

The README also mentions using ExRated.start_link, but note that the API requires the process to be named :ex_rated

3 Likes