Elixir: Making Concurrent API Calls 
angelcool@fedora-laptop$
angelcool@fedora-laptop$date
Fri Apr 12 07:51:16 PM PDT 2024
angelcool@fedora-laptop$ls lib/
coolprogram.ex coordinator.ex worker.ex
angelcool@fedora-laptop$cat lib/coolprogram.ex
defmodule CoolProgram do
def temperature_of(cities) do
coordinator_pid = spawn(CoolProgram.Coordinator, :loop, [[], Enum.count(cities)])
cities |> Enum.each(fn city ->
worker_pid = spawn(CoolProgram.Worker, :loop, [])
send(worker_pid, {coordinator_pid, city})
end)
end
end
angelcool@fedora-laptop$cat lib/coordinator.ex
defmodule CoolProgram.Coordinator do

def loop(results \\ [], results_expected) do
receive do
{:ok, result} ->
new_results = [result|results]
if results_expected == Enum.count(new_results) do
send(self(), :exit)
end
loop(new_results, results_expected)
:exit ->
IO.puts(results |> Enum.sort |> Enum.join(", "))
_->
loop(results, results_expected)
end
end

end
angelcool@fedora-laptop$cat lib/worker.ex
defmodule CoolProgram.Worker do

def temperature_of(location) do
result = url_for(location)
|> HTTPoison.get
|> parse_response
case result do
{:ok, temp} ->
"#{location}: #{temp}° C"
:error ->
"#{location} not found"
end
end

defp url_for(location) do
location = URI.encode(location)
"http://api.openweathermap.org/data/2.5/weather?q=#{location}&appid=#{apikey()}"
end

defp parse_response({:ok, %HTTPoison.Response{body: body, status_code: 200}}) do
body
|> JSON.decode!
|> compute_temperature()
end

defp parse_response(_) do
:error
end

defp compute_temperature(json) do
try do
temp = (json["main"]["temp"]-273.15)
|> Float.round(1)
{:ok, temp}
rescue
_-> :error
end
end

defp apikey do
"XXXXXXXXXXXXXXXXXXXXXXXXXXXX"
end

def loop do
receive do
{sender_pid, location}->
send(sender_pid, {:ok, temperature_of(location)})
_->
IO.puts "don't know how to process this message"
end
loop()
end
end
angelcool@fedora-laptop$
angelcool@fedora-laptop$iex --version
IEx 1.15.7 (compiled with Erlang/OTP 26)
angelcool@fedora-laptop$iex -S mix
Compiling 1 file (.ex)
Erlang/OTP 26 [erts-14.2.2] [source] [64-bit] [smp:16:16] [ds:16:16:10] [async-threads:1] [jit:ns]

Interactive Elixir (1.15.7) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> cities=["San Diego", "Merida", "Singapore", "Los Angeles", "Mexico City", "Miami", "Temecula", "Buenos Aires", "Ojai" ]
["San Diego", "Merida", "Singapore", "Los Angeles", "Mexico City", "Miami",
"Temecula", "Buenos Aires", "Ojai"]
iex(2)> CoolProgram.temperature_of(cities)
:ok
Buenos Aires: 17.0° C, Los Angeles: 14.7° C, Merida: 25.0° C, Mexico City: 22.8° C, Miami: 22.0° C, Ojai: 14.2° C, San Diego: 15.2° C, Singapore: 30.8° C, Temecula: 13.1° C
iex(3)>


[ view entry ] ( 29 views )   |  print article
Elixir: Miscellaneous Notes 
# Filtering files in a directory by filename
angelcool@fedora-laptop$date
Fri Apr 12 12:02:42 PM PDT 2024
angelcool@fedora-laptop$iex
...
iex(90)> "/home/angelcool/Downloads" \
...(90)> |> Path.join("**/*.rpm") \
...(90)> |> Path.wildcard \
...(90)> |> Enum.filter(fn fname -> String.contains?(Path.basename(fname),"dbeaver") end)
["/home/angelcool/Downloads/dbeaver-ce-24.0.2-stable.x86_64.rpm"]


# Making an HTTP GET request
iex(18)> :inets.start()
:ok
iex(19)> :ssl.start()
:ok
iex(20)> :httpc.request(:get, {'https://www.angelcool.net', []}, [ssl: :httpc.ssl_verify_host_options(true)], [])
...


[ view entry ] ( 25 views )   |  print article
Elixir: Clustering Elixir Nodes - Updating Shared State. 

angelcool@fedora-laptop$ # Let's get the date and versions used
angelcool@fedora-laptop$date
Sat Apr 6 11:51:08 AM PDT 2024
angelcool@fedora-laptop$iex --version
IEx 1.15.7 (compiled with Erlang/OTP 26)
angelcool@fedora-laptop$mix --version
Erlang/OTP 26 [erts-14.2.2] [source] [64-bit] [smp:16:16] [ds:16:16:10] [async-threads:1] [jit:ns]

Mix 1.15.7 (compiled with Erlang/OTP 26)
angelcool@fedora-laptop$mix phx.new --version
Phoenix installer v1.7.11
angelcool@fedora-laptop$
angelcool@fedora-laptop$
angelcool@fedora-laptop$
angelcool@fedora-laptop$ # The gist of this post...
angelcool@fedora-laptop$
angelcool@fedora-laptop$ # Terminal 1
angelcool@fedora-laptop$ iex --name a@127.0.0.1
iex(a@127.0.0.1)1>

angelcool@fedora-laptop$ #Terminal 2
angelcool@fedora-laptop$ iex --name b@127.0.0.1
Erlang/OTP 26 [erts-14.2.2] [source] [64-bit] [smp:16:16] [ds:16:16:10] [async-threads:1] [jit:ns]

Interactive Elixir (1.15.7) - press Ctrl+C to exit (type h() ENTER for help)
iex(b@127.0.0.1)1> Node.connect :"a@127.0.0.1"
true
iex(b@127.0.0.1)2> Node.list
[:"a@127.0.0.1"]
iex(b@127.0.0.1)3>

# Terminal 1
iex(a@127.0.0.1)> Agent.start(
fn -> %{hello: "world"} end,
name: {:global, GlobalAgent}
)
{:ok, #PID<0.116.0>}

# Terminal 2
iex(b@127.0.0.1)4> Agent.get {:global,GlobalAgent}, &(&1)
%{hello: "world"}

# Terminal 2 - Update state
iex(b@127.0.0.1)5> Agent.update {:global, GlobalAgent}, fn _ -> %{hello: "everyone!"} end
:ok
iex(b@127.0.0.1)6>

# Terminal 2 - Get new state
iex(b@127.0.0.1)6> Agent.get {:global,GlobalAgent}, &(&1)
%{hello: "everyone!"}

# Terminal 1 - Get new state
iex(a@127.0.0.1)2> Agent.get {:global,GlobalAgent}, &(&1)
%{hello: "everyone!"}


[ view entry ] ( 35 views )   |  print article
Elixir: Processes Talking Amongst Themselves 
angelcool@fedora-laptop$date
Tue Apr 2 11:31:57 AM PDT 2024
angelcool@fedora-laptop$mix new process-demo --app process_a
* creating README.md
* creating .formatter.exs
* creating .gitignore
* creating mix.exs
* creating lib
* creating lib/process_a.ex
* creating test
* creating test/test_helper.exs
* creating test/process_a_test.exs

Your Mix project was created successfully.
You can use "mix" to compile it, test it, and more:

cd process-demo
mix test

Run "mix help" for more commands.
angelcool@fedora-laptop$
angelcool@fedora-laptop$cd process-demo/
angelcool@fedora-laptop$ls -l
total 8
drwxr-xr-x. 1 angelcool angelcool 24 Apr 2 11:31 lib
-rw-r--r--. 1 angelcool angelcool 575 Apr 2 11:31 mix.exs
-rw-r--r--. 1 angelcool angelcool 476 Apr 2 11:31 README.md
drwxr-xr-x. 1 angelcool angelcool 66 Apr 2 11:31 test
angelcool@fedora-laptop$
angelcool@fedora-laptop$cat lib/process_a.ex
defmodule ProcessA do
def receiverA(count) do
receive do
{from, message} -> send(from, {"Greetings from ProcessA!.", message})
receiverA(count+1)
end
end
end
angelcool@fedora-laptop$cat lib/process_b.ex
defmodule ProcessB do
def initialize do
pid_A = spawn(ProcessA, :receiverA, [1])
recieverB(pid_A)
end

def recieverB(pid_A) do
receive do
{message} ->
send(pid_A, {self(), message})
recieverB(pid_A)
{response, originalmessage} ->
IO.puts("Response: #{response}")
IO.puts("Original Message: #{originalmessage}")
recieverB(pid_A)
end
end
end
angelcool@fedora-laptop$
angelcool@fedora-laptop$iex --version
IEx 1.15.7 (compiled with Erlang/OTP 26)
angelcool@fedora-laptop$
angelcool@fedora-laptop$mix phx.new --version
Phoenix installer v1.7.11
angelcool@fedora-laptop$
angelcool@fedora-laptop$iex -S mix
Compiling 2 files (.ex)
Generated process_a app
Erlang/OTP 26 [erts-14.2.2] [source] [64-bit] [smp:16:16] [ds:16:16:10] [async-threads:1] [jit:ns]

Interactive Elixir (1.15.7) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> pid_B = spawn(ProcessB, :initialize, [])
#PID<0.166.0>
iex(2)> send(pid_B, {"Hi! This is a message from process B!"})
Response: Greetings from ProcessA!.
{"Hi! This is a message from process B!"}
Original Message: Hi! This is a message from process B!
iex(3)>


[ view entry ] ( 39 views )   |  print article

| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |


2024 By Angel Cool