-
-
Notifications
You must be signed in to change notification settings - Fork 180
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Concept: Cache module #805
Comments
From discord/discord-api-docs#2184 (comment):
This makes this issue even more important. We should expect, that one day, Discord will remove or at least severely limit the options to request all members of a server. When this happens, we should provide a way for users to have a (semi-)persistent cache for users. |
I think an immutable cache is still possible. If I am not wrong with this cache design it should be possible to have a mutable or immutable cache without the need to have a more complex code base: private void refreshData(long id) {
if(api.isImmutableCache){
return;
}
List<DataEntity> entities = dataStore.get(
ServerTextChannelData.class, "ID", String.valueOf(id)
);
if (!entities.isEmpty()) {
data = (ServerTextChannelData) entities.get(0);
}
} With a simple flag that can be set we can decide whether we want to actually refresh the data from the cache or not. This results in either a mutable or immutable enity. |
This will not work for collections (e.g., |
Then this will result in a sort of semi immutable. But once you get the channels from the cache they are immutable entities which you can store in a variable to process them in your task. I think that's a good trade off though. |
I've already suggested a design for an external cache module in #454 (comment).
However, since this suggestion was not well received because of the immutability, this issue proposes a mutable external cache that also allows sharing data between multiple shards and allows for different data stores like Redis.
Similar to the immutable cache, the mutable cache holds simple immutable and serializable POJOs that do not contain references to other entities except by their ids.
Since the module is independent of Javacord, we can use another JVM language like Kotlin to reduce the necessary boilerplate.
Storing data objects
The implementation of the data store is extremely simple and can look like this for a classic in-memory store:
Since all entities can be serialized (e.g. to JSON), it's easy to create other data stores like Redis. A mixture of different data stores for different data classes (e.g. only users/members in Redis) is also possible and easy to implement.
Using the data objects
We don't want to expose the data objects themselves but keep our current API. The current entities can be constructed as needed:
The two important differences to the previously suggested immutable cache are, that
#getServer()
are called. The other direction is no problem. For example, the deletion of a server would only result in an empty list when#getChannels()
is called.#getName()
, we refresh the cache. This makes sure that we always return the latest data. For data that cannot change (e.g. the id), a refresh is not necessary.Updating the cache
Updating the cache is very straightforward:
Since entities do not store references to other objects, it should be possible to simply map Discord's gateway entities to the data objects and replace them in our cache with very little effort. E.g. for a channel creation or deletion, we can simply add/remove the channel from the cache without having to update any references in the server object (like we currently have to).
Considerations
#refresh()
method that can be called. Another option that would not require any actions from the user is by introducing a caching layer in the store implementation that keeps frequently used entities in local memory.-
in-between. This is probably secure (since we control both the entity name and the key name) but it might be worth giving it a second thought.CompletableFuture
. I believe that this is an acceptable compromise. Especially, if you consider that in practice, you don't want every entity to be in a non-memory cache but probably only users and maybe messages. Users that require an external cache should be able to deal with these trade-offs.Server
andServerTextChannel
) in the examples do not use interfaces. This would not be the case in the final implementation, but I wanted to keep the examples simple for demonstration purposesThe text was updated successfully, but these errors were encountered: