Open curz46 opened 5 years ago
ETS doesn't actually implement locking, however mnesia does, so this actually seems like a case for mnesia instead. In addition, if it's needed (not for my bot), the mnesia database can be replicated onto multiple nodes. mnesia
just wraps ETS (and DETS too if you set it to write anything to disk, though not in this case) so you get all of ETS features, in addition to a few others like locking, transactions, etc...
We should aim to normalize things, to avoid storing redundant structs in the cache, and to make accessing individual structs easy. That is to say, we should strip complex objects like Guilds from the objects they contain, and instead just leave their snowflake / id. Each object can have its own ets / mnesia table.
As far as locking / transactions goes, we need to be able to make sure that when handling an event which requires inserting multiple things, we do so in an atomic way, to avoid running into interleaving issues like we had previously.
As far as locking / transactions goes, we need to be able to make sure that when handling an event which requires inserting multiple things, we do so in an atomic way, to avoid running into interleaving issues like we had previously.
Definitely mnesia over ETS.
Actually at this point I'm leaning to using Cachex, it has transaction support, distributed caches, etc...
I've created a Milestone / Project to track issues related to this effort: https://github.com/cronokirby/alchemy/projects
I don't expect this to come as one PR, so I've created the new-cache branch. As we slowly work on this branch to replace the cache, let's create issues tagged with the new-cache label, and keep track of them under the project board.
I think Cachex should be used, as it provides a very solid implementation of a Cache, and lets us focus on the discord specific logic. It also has great support for transactions and grouping queries, which will be very useful for us.
The first things to do at this point would be to split up the Cache work into small issues. A good place to start would be replacing one of the smaller ets tables or processes using Cachex, and adding a good test suite. This would serve as an example for how to do the rest of the cache. Replacing the guild cache is probably the last thing to do, as it relies on the rest of the cache working well.
Oh, and I've labelled this issue as discussion. Let's keep this issue as a centralized place to track work on this project :)
Motivation
READY
's handler has finished execution, but a more favored approach would be making operations to the cache atomic (i.e. impossible for interleaving described in #79 to occur)PrivChannels
cache and a separation of how guild channels and private channels are handled. Operating generically on the channel of a message (e.g. inCogs
), for this reason, is difficult.Goals
Current Structure
Guilds
(guild cache) GenServer contains guild data, guild channels, roles and members.PrivChannels
(private channel cache) ETS stores private channels.User
(user cache) GenServer stores users.The data stored by the cache is the parsed JSON, rather than the structs the user deals with.
Proposed Structure
(partially through discussion with @cronokirby and others, partially my own thoughts)
GuildCache
in ETS, with all redundant data stripped away. For example,roles
contains a list of snowflakes, not a list of role objects.UserCache
in ETS.RoleCache
in ETS. Struct hasguild_id
added.ChannelCache
in ETS. Struct hasguild_id
added, if the channel belongs to a guild.MemberCache
in ETS. Need to be careful here since a member's unique key is the composition ofguild_id
anduser_id
.Notes
MemberCache
separate fromUserCache
. I think it makes things easier to reason about.