Fl4m3Ph03n1x
Background
I have an ETS table where several processes can write concurrently. This table is very very requested, so having a GenServer as a gatekeeper serializing writes is not an option (it can’t hold the load).
Problem
The solution to this, given the GenServer limitations, would be to have each write be atomic. Now, I am aware of update_counter, but there is one problem. My ETS table doesn’t save counters, it saves lists of urls:
def save_failed_request(url) do
urls = :ets.lookup(__MODULE__, :failed_urls)
case urls do
[] ->
:ets.insert(__MODULE__, {:failed_urls, [url]})
[failed_urls: list] ->
new_list = [url] ++ list
:ets.insert(__MODULE__, {:failed_urls, new_list})
end
{:ok, :saved}
end
This is the code I currently have to save an URL. Since multiple processes can be calling this function concurrently, multiple processes can be writing in the ETS table under the same key, which is not good.
Question
Is there any ETS function that allows me to make atomic updates on values stored in the table?
Or do I have to use counters ? (because the only atomic operation that exists for updates is update_counter?
Trending in Questions
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #blog-post
- #phoenix_html
- #iex
- #graphql
- #ai
- #genstage
- #elixirconf-us
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #security
- #hex











First 10 of 12 Posts
LostKobrakai
Few questions:
Fl4m3Ph03n1x
I am not interested in querying anything. All I want this table to do is to save URLs whose requests failed. Then, when the time comes, the outside process will query the table for all URLs (always all) and I just returns them and clear the table.
So, 1 key is all I need.
I don;t quite understand. The
:failed_urlskey is supposed to have a list of urls. Are you suggesting I use a:bagETS table instead of asetand then just have multiple URLs saved there?Could you elaborate?
peerreynders
Try
for each
url- laterfoldlover the entire table.Fl4m3Ph03n1x
I was actually thinking about using
http://erlang.org/doc/man/ets.html#take-2to get everything with the same key and remove it in one goLostKobrakai
:ets.delete_all_objects(tab)Fl4m3Ph03n1x
delete_all_objectsdoesn’t actually return them, which is something I want in addition to deleting themLostKobrakai
Then is really going to be a
:bagpeerreynders
i.e. may be worth dealing with duplicates after
take/2Fl4m3Ph03n1x
Could you elaborate ?
LostKobrakai
It might be better for performance to us
:duplicate_bag, which is mentioned to be faster on inserts, and deduplicate the urls after usingtake/2.