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.
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.
Going to poke at this a bit more when I’ve got time this week.
I am currently trying to solve the problem of creating anonymous pools (without setting up a pool_id). Right now, it’s unclear which way is better: generate (rotate) a set of pool_ids on initialization or rewrite the monitoring logic.
I confirm that despite the specs, you can already use PID as the first argument in functions to work with the pool. However, the problem of generating pool_ids remains.
Full support for GenServer.name() was implemented in version 1.0.0-rc.0. I’m testing the version in our applications, and so far everything looks good. If you check it yourself, please share the results.