Virginity-Bot / virginity-bot

Discord bot for tracking members virginity (Online time)
GNU Affero General Public License v3.0
6 stars 1 forks source link

Enable high availalability #117

Open dudeofawesome opened 1 year ago

dudeofawesome commented 1 year ago

This is different from Discord's "sharding" which enables multiple instances of your bot to listen to different guilds.

Rather, we want multiple instances of the bot to be able to listen to the same guilds, while avoiding handling the same event twice.

Prior art:

EdgarSaldivar commented 1 year ago

Additional Resources (they are designed to work together it seems):

dudeofawesome commented 1 year ago

Crappy diagram of a possible architecture:

stateDiagram-v2
    direction LR

    state "Discord WS API" as DiscordWSAPI

    state "DiscordJS LB 1" as DiscordJSLB1
    state "DiscordJS LB 2" as DiscordJSLB2

    state "Leaderboard Cmd Handler" as CmdLeaderboardHandler
    state "Check Cmd Handler" as CmdCheckHandler
    state "Settings Cmd Handler" as CmdSettingsHandler

    DiscordWSAPI --> DiscordJSLB1
    DiscordWSAPI --> DiscordJSLB2

    DiscordJSLB1 --> DiscordJSLB2
    DiscordJSLB2 --> DiscordJSLB1

    DiscordJSLB1 --> CmdLeaderboardHandler
    DiscordJSLB2 --> CmdLeaderboardHandler
    DiscordJSLB1 --> CmdCheckHandler
    DiscordJSLB2 --> CmdCheckHandler
    DiscordJSLB1 --> CmdSettingsHandler
    DiscordJSLB2 --> CmdSettingsHandler

The loadbalancers would communicate with each other on a per-request basis to decide if one has failed and the request should be retried on the other.

uPaymeiFixit commented 1 year ago

Happy Path Diagram

sequenceDiagram
    participant DI as Discord
    participant IN1 as Instance 1
    participant IN2 as Instance 2
    participant ETCD

    par
        IN1->>DI: Subscribe to Websocket
        IN2->>DI: Subscribe to Websocket
    end

    par
        DI->>IN1: Message 0xDEADBEEF
        DI->>IN2: Message 0xDEADBEEF
    end

    rect rgb(240, 255, 255)
        IN1->>+ETCD: Check status of 0xDEADBEEF
        ETCD->>-IN1: Record not found
        IN1->>ETCD: Create 0xDEADBEEF with <br>status=PROCESSING and {timestamp}
    end

    rect rgb(255, 240, 240)
        IN2->>ETCD: Check status of 0xDEADBEEF
        ETCD->>IN2: 0xDEADBEEF has <br>status=PROCESSING, and {timestamp}
        IN2->>IN2: Wait {TIMEOUT} seconds
    end

    rect rgb(240, 255, 255)
        IN1->>IN1: Process 0xDEADBEEF
        IN1->>DI: Response
        IN1->>ETCD: Update 0xDEADBEEF with <br>status=COMPLETE
    end

    rect rgb(255, 240, 240)
        IN2->>ETCD: Check status of 0xDEADBEEF
        ETCD->>IN2: COMPLETE
    end

    %% rect rgb(255, 240, 240)
    %%     IN2->>ETCD: Check status of 0xDEADBEEF
    %%     ETCD->>IN2: PROCESSING
    %% end