Using GenServer to save maps

Im going to use GenServer first time, the map that I need to save is:

%{
    "_csrf_token" => "DhA3FRwIGxQNQiYGfC4GJgAAKSOdf2fsdPDFCqZ5lOAydRPnEmmA==",
    "_utf8" => "✓",
    "ersal" => "hozori",
    "name_family" => "مجتبی ناصری",
    "number" => "9922365", 
    "phone_number" => "0911333333",
    "price_of_card" => "1320",
    "price_of_text" => "200",
    "receive" => "person",
    "writing-kind" => "1"
  }

I use UUID to create Genserver PID for each user that needs to save their maps like that.

after that work my GenServer maps are:

%{
  "793edde3-bcc0-4719-9738-c527f168163e": %{
    "_csrf_token" => "DhA3FRwIGxQNQiYGfC4GJgAAKSOdf2fsdPDFCqZ5lOAydRPnEmmA==",
    "_utf8" => "✓",
    "ersal" => "hozori",
    "name_family" => "مجتبی ناصری",
    "number" => "9922365", 
    "phone_number" => "0911333333",
    "price_of_card" => "1320",
    "price_of_text" => "200",
    "receive" => "person",
    "writing-kind" => "1"
  },
  "963018d7-6e03-4f8d-a6f4-31298fc89128": %{
    "_csrf_token" => "DhA3FRwIGxQNQiYGfC4GJgAAKSOdf2fsdPDFCqZ5lOAydRPnEmmA==",
    "_utf8" => "✓",
    "ersal" => "hozori",
    "name_family" => "مجتبی نصیری",
    "number" => "46513", 
    "phone_number" => "0921433333",
    "price_of_card" => "13۶0",
    "price_of_text" => "200",
    "receive" => "person",
    "writing-kind" => "1"
  }
}

My GenServer module:

defmodule WeddingCard.Db.Invoice.InvoiceGenserver do
use GenServer
  
    # client api
    def start_link(init_param) do
      GenServer.start_link(__MODULE__, init_param, name: __MODULE__, debug: [:trace])
    end
    

    def init(init_param) do
        {:ok, init_param}
    end


    def load_all_params do 
        GenServer.call(__MODULE__, :load_all)
    end


    # uuid
    def load_one_params(uuid) do 
        GenServer.call(__MODULE__, {:load_one, uuid})
    end

    def save_params(uuid,params) do
        GenServer.cast(__MODULE__, {:save, uuid ,params})
    end


    def delete_one_params(uuid) do
        GenServer.cast(__MODULE__, {:delete_one, uuid})
    end


    def delete_all_params do
        GenServer.cast(__MODULE__, :delete_all)
    end

    
    #===============================================

    #server api

    def handle_call(:load_all, _from, init_param) do 
        {:reply, init_param, init_param}
    end



    def handle_call({:load_one, uuid}, _from, init_param) do 
        new_state = Map.get(init_param, String.to_atom(uuid))
        {:reply, new_state, init_param}
    end


    def handle_cast({:save, uuid, params}, init_param) do
     new_state = Map.update( 
         init_param , 
         String.to_atom(uuid) , 
         params, fn _old_map -> params end 
    )

    IO.inspect new_state;
         {:noreply, new_state }
    end



    # uuid
    def handle_cast({:delete_one, uuid}, init_param) do
        new_state = Map.delete(init_param, String.to_atom(uuid))
        {:noreply, new_state }
    end


    def handle_cast(:delete_all, _init_param) do
        {:noreply, %{}}
    end

end

I have added my Genserver in application.ex module

def start(_type, _args) do
    children = [
       {WeddingCard.Db.Invoice.InvoiceGenserver, %{}} 
    ]
end

Now I have 2 questions ,

  1. is my way true and is my each user maps value isolate?
  2. I need after the time concerned , it will be deleted, how can I do this ?

Save function:

InvoiceGenserver.save_params(uuid, params)

Thanks

To delete after the time concerned , I found these pages
send_after
https://hexdocs.pm/elixir/GenServer.html

and
https://rob.conery.io/2016/02/16/red4-store-part-3/

What are your actual requirements ?

From the basic description you gave I wouldn’t have use a GenServer, instead I would have tucked the information into :ets or Registry

1 Like

It might also be a good use case for Cachex.

1 Like

@tty @kokolegorille Hello you two and Thank you, I just want to learn OTP especially GenServer, Now I just want to know, is it my way right or not ?