Channels - Where to store state?

It’s a bit hard to recommend the concrete approach, because the description is quite vague, but I’ll give it a try :slight_smile:

To avoid ambiguity with the term channel, I’ll use the term topic instead.

My first take on this would be to use a separate GenServer for each topic. You could hold all the transient data of the topic in that server. The server would also need to keep track of whether it’s in the quite mode. So now, whenever someone wants to send a message to the topic, they need to do it through the corresponding server. Since the server knows about its mode, it can easily decide whether to send the message or not.

Adding expiry logic can now be fairly simple with the help of :timer.send_interval or Process.send_after which would be invoked in the topic server. Either approach will result in some message sent to the server, which you’d need to handle in the corresponding handle_info and remove expired items.

This approach is very consistent, and when done properly, you’ll have no race conditions or strange behaviour. However, the topic server might turn out to be a bottleneck if you have frequent activity on a topic (frequent messages, mode changes, or other state changes). In that case, you could consider using an ETS table. ETS tables can boost your performance significantly, but they are appropriate only for some situations, so you need to think it through. In some cases a hybrid approach is needed, where all the writes are serialized through the server process, while reads are performed directly from the table.

If you go for ETS tables, and want to expire items, you could look into some of the caching libraries, such as CachEx, or my own con_cache. Cachex has more features and higher activity, so as the author of con_cache, I’d myself recommend looking into Cachex first.

If the transient state is really simple, then I’d consider ETS from the start. For example, if we only need to deal with the quiet mode, then I’d just have one ETS table where I’d store that info for each topic.

In more complex cases, I’d start with GenServer and do some testing to see if it can handle the desired load.

Again, the problem is vaguely defined, so it’s hard to precisely say which of the two would be a more suitable choice in this particular case.

8 Likes