Powered by AppSignal & Oban Pro

9. Fledex: Job

livebooks/9_fledex_jobs.livemd

9. Fledex: Job

Mix.install([
  {:fledex, "~>0.6"},
  {:jason, "~>1.2"}
])

Setup

Let’s start with the usual setup

use Fledex

Clock with job

In the last couple of examples it was always a bit cumbersome to get those updates in regular intervals. Either we had to calculate at every screen refresh, or created a decently complicated GenServer to do tasks in regular intervals. As we have seen in the last example there is an easier way to do this by using the job macro.

Let me now introduce you properly to the job macro. It allows us to take care of repetitive work by easily specifying a cron-job. All you need are:

  • a name for the job that identifies it uniquely
  • a schedule when the job should run (see this cheatsheet for the possibilities)
  • and a function that should be executed, probably one that will at the end publish an event with Fledex.Utils.PubSub.broadcast_trigger/1

The example here implements our clock example with the Fledex.Component.Clock component (see the previous chapter) and uses the job macro to schedule the updates.

alias Fledex.Component.Clock

led_strip :nested_components2, Kino do
  component(
    :clock,
    Clock,
    trigger_name: {:clock_hour, :clock_minute, :clock_second}
  )

  job :clock, ~e[@secondly]e do
    date_time = DateTime.utc_now()

    broadcast_trigger(%{
      clock_hour: date_time.hour,
      clock_minute: date_time.minute,
      clock_second: date_time.second
    })
  end
end

Weather station with job

Our weather station example becomes now much easier, because we don’t have to implement the timer functinality ourselves. We can simply implement a job for that.

As before we need to make sure we can make http calls by starting the appropriate services

:inets.start()
:ssl.start()

Now we are ready to define our new simplified weather station using:

  • defining an Fledex.led_strip
  • using the Fledex.Component.Thermometer component as Fledex.component
  • and defining a Fledex.job that runs every 15min (making sure we call it as soon as we define it even though it might not be time for it yet, by specifying run_once: true)

> #### Note > > We are using the normal crontab job pattern, whereas above we used the extended version > (with second precision), indicated by the extra trailing e.

alias Fledex.Component.Thermometer

led_strip :john, Kino do
  component(:thermo, Thermometer,
    range: -20..40,
    trigger: :temperature,
    negative: :blue,
    null: :may_green,
    positive: :red,
    marker: :davy_s_grey
  )

  job :fetcher, ~e[*/15 * * * * *], run_once: true do
    url =
      ~c"https://api.open-meteo.com/v1/forecast?latitude=47.4729344&longitude=19.0468802&current=temperature_2m"

    {:ok, resp} =
      :httpc.request(:get, {url, []}, [], body_format: :binary)

    {{_, 200, ~c"OK"}, _headers, body} = resp
    json = Jason.decode!(body)
    temperature = json["current"]["temperature_2m"]
    broadcast_trigger(%{temperature: temperature})
  end
end