Crash when after using the delete_entry function

iex(1)> {:ok, todo_system_pid} = Todo.System.start_link()
Starting database worker 1
Starting database worker 2
Starting database worker 3
Starting to-do cache
{:ok, #PID<0.141.0>}
iex(2)> {:ok, todo_system_pid: todo_system_pid}
{:ok, [todo_system_pid: #PID<0.141.0>]}
iex(3)> abc = Todo.Cache.server_process("abc")
Starting to-do server for abc
#PID<0.151.0>
iex(4)> Todo.Server.add_entry(abc, %{date: ~D[2020-05-19], time: ~T[00:00:00], title: "Shopping"})
:ok
iex(5)> Todo.Server.add_entry(abc, %{date: ~D[2020-05-19], time: ~T[00:01:00], title: "Hacking"})
:ok
iex(6)> Todo.Server.add_entry(abc, %{date: ~D[2020-05-20], time: ~T[00:00:00], title: "Swimming"})
:ok
iex(7)> Todo.Server.entries(abc, ~D[2020-05-19], ~T[00:00:00])
[%{date: ~D[2020-05-19], id: 22, time: ~T[00:00:00], title: "Shopping"}]
iex(8)> Todo.Server.date_check(abc, ~D[2020-05-20])
[
  %{date: ~D[2020-05-20], id: 1, time: ~T[16:52:00], title: "Shopping"},
  %{date: ~D[2020-05-20], id: 2, time: ~T[16:53:00], title: "Playing"},
  %{date: ~D[2020-05-20], id: 3, time: ~T[16:53:00], title: "swimming"},
  %{date: ~D[2020-05-20], id: 4, time: ~T[16:52:00], title: "Shopping"},
  %{date: ~D[2020-05-20], id: 5, time: ~T[16:53:00], title: "Playing"},
  %{date: ~D[2020-05-20], id: 6, time: ~T[16:53:00], title: "swimming"},
  %{date: ~D[2020-05-20], id: 7, time: ~T[16:52:00], title: "Shopping"},
  %{date: ~D[2020-05-20], id: 8, time: ~T[16:53:00], title: "Playing"},
  %{date: ~D[2020-05-20], id: 9, time: ~T[16:52:00], title: "Shopping"},
  %{date: ~D[2020-05-20], id: 10, time: ~T[16:53:00], title: "Playing"},
  %{date: ~D[2020-05-20], id: 11, time: ~T[16:53:00], title: "swimming"},
  %{date: ~D[2020-05-20], id: 12, time: ~T[16:52:00], title: "Shopping"},
  %{date: ~D[2020-05-20], id: 13, time: ~T[16:53:00], title: "Playing"},
  %{date: ~D[2020-05-20], id: 14, time: ~T[16:53:00], title: "swimming"},
  %{date: ~D[2020-05-20], id: 15, time: ~T[16:53:00], title: "Playing"},
  %{date: ~D[2020-05-20], id: 16, time: ~T[16:52:00], title: "Shopping"},
  %{date: ~D[2020-05-20], id: 17, time: ~T[16:53:00], title: "Playing"},
  %{date: ~D[2020-05-20], id: 18, time: ~T[16:53:00], title: "swimming"},
  %{date: ~D[2020-05-20], id: 19, time: ~T[16:52:00], title: "Shopping"},
  %{date: ~D[2020-05-20], id: 20, time: ~T[16:53:00], title: "Playing"},
  %{date: ~D[2020-05-20], id: 21, time: ~T[16:53:00], title: "swimming"},
  %{date: ~D[2020-05-20], id: 24, time: ~T[00:00:00], title: "Swimming"}
]
iex(9)> Todo.Server.time_check(abc, ~T[00:00:00])
[
  %{date: ~D[2020-05-19], id: 22, time: ~T[00:00:00], title: "Shopping"},
  %{date: ~D[2020-05-20], id: 24, time: ~T[00:00:00], title: "Swimming"}
]
iex(10)> Todo.Server.delete_entry(abc, 24)
:ok
iex(11)> Todo.Server.time_check(abc, ~T[00:00:00])

18:32:46.287 [error] GenServer {Todo.ProcessRegistry, {Todo.Server, "abc"}} terminating
** (ArgumentError) argument error
    :erlang.apply("abc", :entries, [])
    (todo) lib/todo/list.ex:30: Todo.List.time_check/2
    (todo) lib/todo/server.ex:58: Todo.Server.handle_call/3
    (stdlib) gen_server.erl:661: :gen_server.try_handle_call/4
    (stdlib) gen_server.erl:690: :gen_server.handle_msg/6
    (stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
Last message (from #PID<0.139.0>): {:time_check, ~T[00:00:00]}
State: {%Todo.List{auto_id: 25, entries: %{1 => %{date: ~D[2020-05-20], id: 1, time: ~T[16:52:00], title: "Shopping"}, 2 => %{date: ~D[2020-05-20], id: 2, time: ~T[16:53:00], title: "Playing"}, 3 => %{date: ~D[2020-05-20], id: 3, time: ~T[16:53:00], title: "swimming"}, 4 => %{date: ~D[2020-05-20], id: 4, time: ~T[16:52:00], title: "Shopping"}, 5 => %{date: ~D[2020-05-20], id: 5, time: ~T[16:53:00], title: "Playing"}, 6 => %{date: ~D[2020-05-20], id: 6, time: ~T[16:53:00], title: "swimming"}, 7 => %{date: ~D[2020-05-20], id: 7, time: ~T[16:52:00], title: "Shopping"}, 8 => %{date: ~D[2020-05-20], id: 8, time: ~T[16:53:00], title: "Playing"}, 9 => %{date: ~D[2020-05-20], id: 9, time: ~T[16:52:00], title: "Shopping"}, 10 => %{date: ~D[2020-05-20], id: 10, time: ~T[16:53:00], title: "Playing"}, 11 => %{date: ~D[2020-05-20], id: 11, time: ~T[16:53:00], title: "swimming"}, 12 => %{date: ~D[2020-05-20], id: 12, time: ~T[16:52:00], title: "Shopping"}, 13 => %{date: ~D[2020-05-20], id: 13, time: ~T[16:53:00], title: "Playing"}, 14 => %{date: ~D[2020-05-20], id: 14, time: ~T[16:53:00], title: "swimming"}, 15 => %{date: ~D[2020-05-20], id: 15, time: ~T[16:53:00], title: "Playing"}, 16 => %{date: ~D[2020-05-20], id: 16, time: ~T[16:52:00], title: "Shopping"}, 17 => %{date: ~D[2020-05-20], id: 17, time: ~T[16:53:00], title: "Playing"}, 18 => %{date: ~D[2020-05-20], id: 18, time: ~T[16:53:00], title: "swimming"}, 19 => %{date: ~D[2020-05-20], id: 19, time: ~T[16:52:00], title: "Shopping"}, 20 => %{date: ~D[2020-05-20], id: 20, time: ~T[16:53:00], title: "Playing"}, 21 => %{date: ~D[2020-05-20], id: 21, time: ~T[16:53:00], title: "swimming"}, 22 => %{date: ~D[2020-05-19], id: 22, time: ~T[00:00:00], title: "Shopping"}, 23 => %{date: ~D[2020-05-19], id: 23, time: ~T[00:01:00], title: "Hacking"}}}, "abc"}
Client #PID<0.139.0> is alive

    (stdlib) gen.erl:169: :gen.do_call/4
    (elixir) lib/gen_server.ex:1006: GenServer.call/3
    (stdlib) erl_eval.erl:680: :erl_eval.do_apply/6
    (elixir) src/elixir.erl:275: :elixir.eval_forms/4
    (iex) lib/iex/evaluator.ex:257: IEx.Evaluator.handle_eval/5
    (iex) lib/iex/evaluator.ex:237: IEx.Evaluator.do_eval/3
    (iex) lib/iex/evaluator.ex:215: IEx.Evaluator.eval/3
    (iex) lib/iex/evaluator.ex:103: IEx.Evaluator.loop/1
** (exit) exited in: GenServer.call(#PID<0.151.0>, {:time_check, ~T[00:00:00]}, 5000)
    ** (EXIT) an exception was raised:
        ** (ArgumentError) argument error
            :erlang.apply("abc", :entries, [])
            (todo) lib/todo/list.ex:30: Todo.List.time_check/2
            (todo) lib/todo/server.ex:58: Todo.Server.handle_call/3
            (stdlib) gen_server.erl:661: :gen_server.try_handle_call/4
            (stdlib) gen_server.erl:690: :gen_server.handle_msg/6
            (stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
    (elixir) lib/gen_server.ex:1009: GenServer.call/3
iex(11)>

so this is what i do, i was trying to use this function to delete the entry but after i check my list again, there is an error comming out, this is my code for delete_entry
list.ex

def delete_entry(todo_list, entry_id) do	  
          new_entries = Map.delete(todo_list.entries, entry_id)
          %Todo.List{todo_list | entries: new_entries}
	end

server.ex

def delete_entry(todo_server, entry_id) do
    GenServer.cast(todo_server, {:delete_entry, entry_id})
  end

@impl GenServer
  def handle_cast({:delete_entry, entry_id}, {name, todo_list}) do
    {:noreply, {Todo.List.delete_entry(todo_list, entry_id), name}}
  end

Here You are switching position in the tuple…

That is where You should find the error.

sorry but if i dont understand what switching position in the tuple meaning are you saying

def handle_cast({:delete_entry, entry_id}, {name, todo_list}) do
    {:noreply, {Todo.List.delete_entry(todo_list, entry_id), name}}
  end

changed to

def handle_cast({:delete_entry, entry_id}, {todo_list,name}) do
    {:noreply, {Todo.List.delete_entry(todo_list, entry_id), name}}
  end

?

The state of your genserver is a tuple…

Here You put

{name, todo_list}

But You return…

{Todo.List.delete_entry(todo_list, entry_id), name}

You are switching the information in the tuple, maybe this is what You want?

What is the initial state of the Genserver?

i want to remove the information in the list

Todo.Server.date_check(abc, ~D[2020-05-20])
[
  %{date: ~D[2020-05-20], **id: 1**, time: ~T[16:52:00], title: "Shopping"},
  %{date: ~D[2020-05-20], id: 2, time: ~T[16:53:00], title: "Playing"},
  %{date: ~D[2020-05-20], id: 3, time: ~T[16:53:00], title: "swimming"},
]

which i try to delete it by the id

if you talk about the init

@impl GenServer
  def init(name) do
    IO.puts("Starting to-do server for #{name}")
    {:ok, {name, Todo.Database.get(name) || Todo.List.new()}}
  end

abc = Todo.Cache.server_process(“abc”)
Starting to-do server for abc
#PID<0.151.0>

The error is in this file, at line 30…

And You should be careful what You return, because You switch the list and the name in the tuple.

29 def time_check(todo_list, time) do
30    todo_list.entries
31    |> Stream.filter(fn {_, entry} -> entry.time == time end)
32   |> Enum.map(fn {_, entry} -> entry end)
33 end

i did try change it to todo_list.time_check
but it just crash it at the first time

and if i change to this

def delete_entry(todo_list, entry_id) do
    %Todo.List{todo_list | entries: Map.delete(todo_list.entries, entry_id)}
  end

will it better? since i try to copy the add_entry format to do it

def add_entry(todo_list, entry) do
    entry = Map.put(entry, :id, todo_list.auto_id)
    new_entries = Map.put(todo_list.entries, todo_list.auto_id, entry)

    %Todo.List{todo_list | entries: new_entries, auto_id: todo_list.auto_id + 1}
  end

Try to inspect the todo_list. My guess is You don’t provide the right parameter to the function.

Let say i step by step

1.{:ok, todo_system_pid} = Todo.System.start_link()
2.{:ok, todo_system_pid: todo_system_pid}
3.a = Todo.Cache.server_process("a")
4.Todo.Server.add_entry(a, %{date: ~D[2020-05-19], time: ~T[16:52:00], title: "Shopping"})

above all return :ok
Todo.Server.entries(a, ~D[2020-05-19], ~T[16:52:00])

[%{date: ~D[2020-05-19], id: 1, time: ~T[16:52:00], title: “Shopping”}]
Todo.Server.date_check(a, ~D[2020-05-19])
[%{date: ~D[2020-05-19], id: 1, time: ~T[16:52:00], title: “Shopping”}]
Todo.Server.delete_entry(a, 1)
:ok
Todo.Server.entries(a, ~D[2020-05-19], ~T[16:52:00])
crashed

Let say You correct this wrong code…

def handle_cast({:delete_entry, entry_id}, {name, todo_list}) do
    {:noreply, {Todo.List.delete_entry(todo_list, entry_id), name}}
end

# Wrong! it should be

def handle_cast({:delete_entry, entry_id}, {name, todo_list}) do
    {:noreply, {name, Todo.List.delete_entry(todo_list, entry_id)}}
end

Let say You put an inspect, and tell us what You got…

29 def time_check(todo_list, time) do
--> IO.inspect todo_list, label: "HEY, WHAZZUP"
30    todo_list.entries
31    |> Stream.filter(fn {_, entry} -> entry.time == time end)
32   |> Enum.map(fn {_, entry} -> entry end)
33 end
1 Like

So it isn’t the input value is on the part of the Todo.List.delete_entry(todo_list, entry_id) ?
and why when the name should put it into the front make a big difference?

It is not important if You put the name first or last. but You need to keep it consistant.

{a, b} is not equal to {b, a}

unless a == b of course.

1 Like