diff options
| author | Ben Busby <noreply+git@benbusby.com> | 2021-11-24 09:35:21 -0700 |
|---|---|---|
| committer | Ben Busby <noreply+git@benbusby.com> | 2021-11-24 09:35:21 -0700 |
| commit | ff97d258f0ac2bbd3b89df892ce3aed08b5e0a42 (patch) | |
| tree | 0a7f8452878ad0838befaf4e39f53ddc794d5338 /lib | |
| parent | d1c9212994925bbe18f5bad7070f2a6238a969f8 (diff) | |
| download | farside-ff97d258f0ac2bbd3b89df892ce3aed08b5e0a42.tar.gz | |
Use quantum core for update scheduling
Rather than requiring a traditional crontab install, the app now
leverages quantum-core (link below) to schedule the instance update/sync
task every 5 minutes. Some updates as a result:
- The new job is scheduled at runtime in server.ex.
- The update.exs script was refactored to be compiled along with the
rest of the app as instances.ex.
- Scheduler and Server modules were added for creating and executing
the new update task
- All shell scripts were removed, as they are no longer needed
https://github.com/quantum-elixir/quantum-core
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/farside/application.ex | 10 | ||||
| -rw-r--r-- | lib/farside/instances.ex | 86 | ||||
| -rw-r--r-- | lib/farside/scheduler.ex | 3 | ||||
| -rw-r--r-- | lib/farside/server.ex | 22 |
4 files changed, 117 insertions, 4 deletions
diff --git a/lib/farside/application.ex b/lib/farside/application.ex index d1c5e25..7427e89 100644 --- a/lib/farside/application.ex +++ b/lib/farside/application.ex @@ -7,7 +7,8 @@ defmodule Farside.Application do @impl true def start(_type, _args) do - plug_children = [ + + plug_children = System.get_env("FARSIDE_NO_ROUTER") && [] || [ Plug.Cowboy.child_spec( scheme: :http, plug: Farside.Router, @@ -19,9 +20,10 @@ defmodule Farside.Application do ] children = [ - {Redix, {@redis_conn, [name: :redix]}} | - System.get_env("FARSIDE_NO_ROUTER") && [] || plug_children - ] + {Redix, {@redis_conn, [name: :redix]}}, + Farside.Scheduler, + Farside.Server + ] ++ plug_children opts = [strategy: :one_for_one, name: Farside.Supervisor] Supervisor.start_link(children, opts) diff --git a/lib/farside/instances.ex b/lib/farside/instances.ex new file mode 100644 index 0000000..203ddfa --- /dev/null +++ b/lib/farside/instances.ex @@ -0,0 +1,86 @@ +defmodule Farside.Instances do + @fallback_suffix Application.fetch_env!(:farside, :fallback_suffix) + @update_file Application.fetch_env!(:farside, :update_file) + @services_json Application.fetch_env!(:farside, :services_json) + @service_prefix Application.fetch_env!(:farside, :service_prefix) + + def sync() do + File.rename(@update_file, "#{@update_file}-prev") + update() + + # Add UTC time of last update + Redix.command(:redix, [ + "SET", + "last_updated", + Calendar.strftime(DateTime.utc_now(), "%c") + ]) + end + + def request(url) do + cond do + System.get_env("FARSIDE_TEST") -> + :good + true -> + case HTTPoison.get(url) do + {:ok, %HTTPoison.Response{status_code: 200}} -> + # TODO: Add validation of results, not just status code + :good + _ -> + :bad + end + end + end + + def update() do + {:ok, file} = File.read(@services_json) + {:ok, json} = Poison.decode(file, as: [%Service{}]) + + # Loop through all instances and check each for availability + for service <- json do + IO.puts "======== " <> service.type + result = Enum.filter(service.instances, fn(instance_url) -> + IO.puts " " <> instance_url + request(instance_url <> service.test_url) == :good + end) + + add_to_redis(service, result) + log_results(service.type, result) + end + end + + def add_to_redis(service, instances) do + # Remove previous list of instances + Redix.command(:redix, [ + "DEL", + "#{@service_prefix}#{service.type}" + ]) + + # Update with new list of available instances + Redix.command(:redix, [ + "LPUSH", + "#{@service_prefix}#{service.type}" + ] ++ instances) + + # Set fallback to one of the available instances, + # or the default instance if all are "down" + if Enum.count(instances) > 0 do + Redix.command(:redix, [ + "SET", + "#{service.type}#{@fallback_suffix}", + Enum.random(instances) + ]) + else + Redix.command(:redix, [ + "SET", + "#{service.type}#{@fallback_suffix}", + service.fallback + ]) + end + end + + def log_results(service_name, results) do + {:ok, file} = File.open(@update_file, [:append, {:delayed_write, 100, 20}]) + IO.write(file, "#{service_name}: #{inspect(results)}\n") + File.close(file) + end +end diff --git a/lib/farside/scheduler.ex b/lib/farside/scheduler.ex new file mode 100644 index 0000000..4707624 --- /dev/null +++ b/lib/farside/scheduler.ex @@ -0,0 +1,3 @@ +defmodule Farside.Scheduler do + use Quantum, otp_app: :farside +end diff --git a/lib/farside/server.ex b/lib/farside/server.ex new file mode 100644 index 0000000..1d5bb76 --- /dev/null +++ b/lib/farside/server.ex @@ -0,0 +1,22 @@ +defmodule Farside.Server do + use GenServer + import Crontab.CronExpression + + def init(init_arg) do + {:ok, init_arg} + end + + def start_link(arg) do + if System.get_env("FARSIDE_TEST") do + IO.puts("Skipping sync job setup...") + else + Farside.Scheduler.new_job() + |> Quantum.Job.set_name(:sync) + |> Quantum.Job.set_schedule(~e[*/5 * * * *]) + |> Quantum.Job.set_task(fn -> Farside.Instances.sync end) + |> Farside.Scheduler.add_job() + end + + GenServer.start_link(__MODULE__, arg) + end +end |
