Dynamic sets of atoms used as keys

While writing an Elixir application I’ve found twice now - using Quantum to create schedules and using Poolex to create worker pools - that these entities are keyed by atoms.

The problem is that the set of schedules or pools should correspond to database records in the application I’m writing, so it would be most natural to key them by the UUID of those records.

Knowing that the application may be long running, atoms are not garbage collected, and the set of ids will change over time, I’ve written a module to map from arbitrary terms (strings in this case) to dynamically generated atoms - the idea being that when an element is deleted from the map, the corresponding atom goes into a free set for reuse, so that the number of atoms allocated over time is no larger than the maximum number of dynamic elements in play.

It seems to me this must have been solved before but I haven’t found the library to reach for. Also, is there a good reason for these hex packages to key their elements by atom?

Skimming the source of Poolex, it seems like the pool_id value is always used as the first argument to GenServer.call and GenServer.cast.

Dialyzer will complain, but you could pass anything from GenServer.name() there - for instance, a :via tuple against a Registry that tracks pools by UUID.

1 Like

Adding onto the above: I’ve tried this out locally, and it almost works.

One sticking point is in Poolex.Private.Monitoring on line 9:

This crashes if pool_id is a tuple because the tuple doesn’t work with String.Chars.

“Fixing” it by using :"#{inspect(pool_id)}_references" seems to work, but ends up right back at the making-atoms-dynamically-at-runtime mess we were trying to avoid. :thinking:

Going to poke at this a bit more when I’ve got time this week.

2 Likes