vinhnglx / vinhnglx.github.io

0 stars 0 forks source link

TIL_07_July_2017 - Multiple server-processes in Elixir - Part 2 #17

Open vinhnglx opened 7 years ago

vinhnglx commented 7 years ago
GenServer.start(__MODULE__, nil)
defmodule Kito.Cache do
  use GenServer

  def init(_) do
    # Associates kito-type names with kito-server pids
    {:ok, Map.new}
  end

  def handle_call({:server_process, kito_type_name}, _, kito_servers) do
    case Map.fetch(kito_servers, kito_type_name) do
      {:ok, kito_server} ->
        # server exists
        {:reply, kito_server, kito_servers}

      :error ->
        # server doesn't exist so create new instance
        {:ok, new_kito_server_pid} = Kito.Server.start

        {:reply, new_kito_server_pid, Map.put(kito_servers, kito_type_name, new_kito_server_pid)}
    end
  end

  def start do
    # __MODULE__ is the name of current module.
    GenServer.start(__MODULE__, nil)
  end

  def server_process(pid, kito_type_name) do
    GenServer.call(pid, {:server_process, kito_type_name})
  end
end

and the test case may be

defmodule KitoCacheTest do
  use ExUnit.Case

  test "start a new process" do
    {:ok, cache_pid} = Kito.Cache.start

    working = Kito.Cache.server_process(cache_pid, "Working")
    assert is_pid(working) == true

    Kito.Server.add(working, %{site: "heroku", username: "johndoe", password: "abcd1234"})
    assert Kito.Server.get(working, :site, "heroku") |> length == 1

    socials = Kito.Cache.server_process(cache_pid, "Socials")

    assert Kito.Server.get(socials, :site, "facebook") |> length == 0
  end
end

So, in the future, if we have multiple clients issue requests to the single Kito.Cache process, this cause a bottleneck. Because we only have one Kito.Cache process and you can handle only one server process simultaneously, regardless of how many CPU resources you have.

In general, a single process Kito.Cache can handle only one request at a time. If the client request handling takes 1 second then you can only process 60 requests per minute - your system won't be able to handle higher loads.

vinhnglx commented 7 years ago
vinhnglx commented 7 years ago
vinhnglx commented 7 years ago
  def store(key, data) do
    # use an alias have a downside is that you can only run one instance of database server process
    GenServer.cast(:database_server, {:store, key, data})
  end

Casts allow client processes to move on immediately after a request is issued.

This comes at cost of Consistency.