Still new to elixir and exploring so here is something I could use some help with
I have an ets with following definition
:ets.new(table, [
data_type,
:public,
:named_table,
read_concurrency: true,
write_concurrency: true
])
All are initializsed as follows upon application startup
:ets.insert(table, {:uptime, DateTime.utc_now() |> DateTime.to_string()})
:ets.insert(table, {:total_msg_count, 0})
:ets.insert(table, {:replied_msg_count, 0})
:ets.insert(table, {:forwarded_msg_count, 0})
:ets.insert(table, {:total_attachments_downloaded, 0})
:ets.insert(table, {:total_messages_slacked, 0})
Here is a my code that I use to manage ets in my project.
require Logger
defmodule Ultronex.Realtime.TermStorage do
@moduledoc """
Documentation for Ultronex.RealtimeTermStorage
"""
def initialize do
ets_initialize()
initialize_stats()
end
def initialize_stats do
output = ets_initialize(:stats, :set)
case output do
{:error, _} ->
Ultronex.BotX.ets_initialize()
_ ->
Logger.debug(":ets : stats loaded from file")
end
end
def ets_initialize(table \\ :track, data_type \\ :bag) do
Logger.info("Creating :ets : #{table} , type : #{data_type}")
output = :ets.file2tab('tab/#{table}.tab')
case output do
{:error, _} ->
Logger.info(":ets : #{table} created from fresh")
:ets.new(table, [
data_type,
:public,
:named_table,
read_concurrency: true,
write_concurrency: true
])
{:ok, _} ->
Logger.info(":ets : #{table} created from file")
_ ->
Logger.debug(":ets : #{table} - WTF !!!!!!")
end
output
end
def ets_incr(table \\ :stats, key \\ :total_msg_count) do
:ets.update_counter(table, key, {2, 1})
end
def ets_lookup(table \\ :stats, key \\ :total_msg_count) do
:ets.lookup(table, key)[key]
end
def ets_tab2file(table) do
Logger.info("Saving.... :ets : #{table} to file")
:ets.tab2file(table, 'tab/#{table}.tab')
end
end
The error happens for the following key :total_messages_slacked
only on update_counter
and that to randomly from the looks as its not happening on all updates
All are updated in following manner
TermStorage.ets_incr(:stats, :replied_msg_count)
TermStorage.ets_incr(:stats, :forwarded_msg_count)
TermStorage.ets_incr(:stats, :total_messages_slacked)
The additional thing to know is that :total_messages_slacked
is updated by a different process than the one that owns the ets table, but as its public it should work and does like 99% of the time.
coming to the error that is happening and :total_messages_slacked
is only updated in one place
(Protocol.UndefinedError) protocol String.Chars not implemented for {%ArgumentError{message: "argument error"}, [{:ets, :update_counter, [:stats, :total_messages_slacked, {2, 1}], []}, {Ultronex.Realtime.TermStorage, :ets_incr, 2, [file: 'lib/ultronex/realtime/term_storage.ex', line: 52]}, {Ultronex.BotX, :relay_msg_to_slack, 4, [file: 'lib/ultronex/bot_x.ex', line: 77]}]} of type Tuple. This protocol is implemented for the following type(s): List, Date, Version, URI, Integer, BitString, Time, Version.Requirement, Float, DateTime, NaiveDateTime, Atom
Wierd thing is not sure what its complaing about at times as its not possible for the value to be of different type suddenly for a process.