Discord4J / Stores

A set of Discord entity cache implementations for Discord4J
https://discord4j.com
GNU Lesser General Public License v3.0
11 stars 7 forks source link

[WIP] Prototype for an action-based Store API #9

Closed Alex1304 closed 3 years ago

Alex1304 commented 3 years ago

As another attempt to design a Store API that would allow implementors to make proper optimizations on store access operations, I tried to make one that is based on actions rather than generic CRUD operations. Now I fully understand the need to have something action-specific rather than trying to be too generic, I hope we can come to a viable solution this time.

For that there were basically two options, either have a huge interface with dozens of methods for every possible action on the store, or have a common interface for individual actions, reducing the Store interface to just one method that accepts an action as parameter. I went for the second option, because it would allow more things like making user-defined actions, have Stores that only handle a subset of actions, and most importantly not break backward-compatibility when adding a new action to the API.

Here are a few things to understand about the content of this PR:

Some example usage of the new API:

GatewayDiscordClient gateway = client.gateway()
        .setStore(SwitchingStore.builder()
                .useIfActionOfType(new JdkStore(), ReadAction.class, GatewayWriteAction.class)
                .useIfActionOfType(new NoOpStore(), ExternalWriteAction.class)
                .build())
        .login()
        .block();

How to use a store:

ChannelData data = store.execute(new GetChannelByIdAction(channelId)).block();

How to implement a store using the helper class:

public class MyCustomStore implements Store {

    @Override
    public <R> Mono<R> execute(StoreAction<R> action) {
        return StoreActionHandlingHelper.create()
                .addHandler(GuildCreateAction.class, this::handleGuildCreate)
                .addHandler(GuildDeleteAction.class, this::handleGuildDelete)
                .handle(action);
    }

    private Mono<Void> handleGuildCreate(GuildCreateAction action) {
        //...
    }

    private Mono<GuildData> handleGuildDelete(GuildDeleteAction action) {
        //... 
    }
}
Alex1304 commented 3 years ago

Given the direction it's taking, it looks like the new stores api is going to reside either in d4j-common or in a brand new module, leaving this one for the old stores only. I'm going to close this PR and work exclusively on https://github.com/Discord4J/Discord4J/pull/788 going forward, I'll add any new classes in d4j-common and will let you decide later what should belong to a new module.