Skip to content

Commit

Permalink
add shard manager interface
Browse files Browse the repository at this point in the history
applies to #26
  • Loading branch information
switchupcb committed Dec 5, 2022
1 parent f0f9efc commit cbb525d
Show file tree
Hide file tree
Showing 25 changed files with 432 additions and 217 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ bot := &disgo.Client{
Authorization: &disgo.Authorization{ ... },
Config: disgo.DefaultConfig(),
Handlers: new(disgo.Handlers),
Sessions: []*disgo.Session{disgo.NewSession()},
}
```

Expand Down Expand Up @@ -138,7 +137,8 @@ Open a WebSocket **Session** to receive events.

```go
// Connect the session to the Discord Gateway (WebSocket Connection).
if err := bot.Sessions[0].Connect(bot); err != nil {
s := disgo.NewSession()
if err := s.Connect(bot); err != nil {
log.Printf("can't open websocket session to Discord Gateway: %v", err)

return
Expand Down
9 changes: 5 additions & 4 deletions _contribution/concepts/SHARD.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# What is Discord Sharding?

Disgo provides an **optional** shard manager for your Discord Bot. Read [The Disgo Shard Manager](/shard/README.md) for information about its implementation.
Disgo makes implementing Sharding easy by providing a customizable shard manager. Use the [**Disgo Shard Manager (module)**](/shard/README.md) or provide your own implementation by implementing the [`ShardManager interface`](/wrapper/shard.go).

## What is a Session?

Expand All @@ -16,15 +16,16 @@ When the **new bot** handles more data _(without sharding)_, all that data is se

### Advanced

A shard only refers to which session(s) a guild's data will be sent to. In other words, a shard represents a _traffic route_ for guild data. This presents the following hierarchy:
A shard only refers to which session(s) a guild's data will be sent to. In other words, a shard represents a _traffic route_ for guild data. This presents the following hierarchy:

- **One Session manages multiple shards**.
- **One Shard manages multiple guilds' data**.
- **One Shard manages multiple guilds' data**.

Multiple sessions can use the same shard _(routes for a guild's data)_; each session can contain a different number of shards. This allows you to create sessions that handle a different amount traffic _(which is done for a multitude of reasons)_.

## What is Sharding?

Sharding refers to managing data through multiple Shards _(WebSocket Sessions, Gateways, Whatever)_. Discord shards bots by guild: **One Shard manages the data for multiple guilds.**
Sharding refers to managing data through multiple shards _(routes of Guild data)_.

### How Does It Work?

Expand Down
7 changes: 5 additions & 2 deletions _examples/bot/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ func main() {
},

Gateway: disgo.Gateway{
// ShardManager is an interface defined in ./wrapper/shard.go
ShardManager: nil,

// RateLimiter is an interface defined in ./wrapper/ratelimiter.go
RateLimiter: new(disgo.RateLimit),
Expand All @@ -68,8 +70,9 @@ func main() {
// described in ./_contribution/REQUESTS.md
Handlers: new(disgo.Handlers),

// Sessions controls the bot's WebSocket Sessions (Gateway, Voice).
Sessions: []*disgo.Session{},
// Sessions controls the bot's WebSocket Sessions (Gateway, Voice)
// when a shard manager is used.
Sessions: disgo.NewSessionManager(),
}

// set a configuration option during runtime.
Expand Down
2 changes: 1 addition & 1 deletion _examples/command/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ Use `ctrl + C` or `cmd + C` in the terminal.

```
Exiting program due to signal...
Disconnected from the Discord Gateway.
Deleting the application command...
Disconnecting from the Discord Gateway...
Program executed successfully.
```

Expand Down
2 changes: 2 additions & 0 deletions _examples/command/autocomplete/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ When application command data is received, the bot will respond with a message.
Use `ctrl + C` or `cmd + C` in the terminal.

```
Exiting program due to signal...
Disconnected from the Discord Gateway.
Deleting the application command...
Program executed successfully.
```
13 changes: 9 additions & 4 deletions _examples/command/autocomplete/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ func main() {
Authentication: disgo.BotToken(token), // or BearerToken("TOKEN")
Config: disgo.DefaultConfig(),
Handlers: new(disgo.Handlers),
Sessions: []*disgo.Session{disgo.NewSession()},
}

log.Println("Creating an application command...")
Expand Down Expand Up @@ -108,7 +107,8 @@ func main() {
log.Println("Connecting to the Discord Gateway...")

// Connect the session to the Discord Gateway (WebSocket Connection).
if err := bot.Sessions[0].Connect(bot); err != nil {
s := disgo.NewSession()
if err := s.Connect(bot); err != nil {
log.Printf("can't open websocket session to Discord Gateway: %v", err)

return
Expand All @@ -117,15 +117,20 @@ func main() {
log.Println("Successfully connected to the Discord Gateway. Waiting for an interaction...")

// end the program using a SIGINT call via `Ctrl + C` from the terminal.
if err := tools.InterceptSignal(tools.Signals, bot.Sessions...); err != nil {
if err := tools.InterceptSignal(tools.Signals, s); err != nil {
log.Printf("error exiting program: %v", err)
}

log.Println("Deleting the application command...")
log.Println("Exiting program due to signal...")

// tools.InterceptSignal() calls s.Disconnect() which disconnects the Session from the Discord Gateway.
log.Println("Disconnected from the Discord Gateway.")

// The following code is not necessarily required, but useful for the cleanup of this program.
//
// delete the Global Application Command.
log.Println("Deleting the application command...")

requestDeleteGlobalApplicationCommand := &disgo.DeleteGlobalApplicationCommand{CommandID: newCommand.ID}
if err := requestDeleteGlobalApplicationCommand.Send(bot); err != nil {
log.Printf("error deleting Global Application Command: %v", err)
Expand Down
2 changes: 2 additions & 0 deletions _examples/command/followup/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ Upon receiving an interaction from the user, the bot will respond with a regular
Use `ctrl + C` or `cmd + C` in the terminal.

```
Exiting program due to signal...
Disconnected from the Discord Gateway.
Deleting the application command...
Program executed successfully.
```
13 changes: 9 additions & 4 deletions _examples/command/followup/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ func main() {
Authentication: disgo.BotToken(token), // or BearerToken("TOKEN")
Config: disgo.DefaultConfig(),
Handlers: new(disgo.Handlers),
Sessions: []*disgo.Session{disgo.NewSession()},
}

log.Println("Creating an application command...")
Expand Down Expand Up @@ -77,7 +76,8 @@ func main() {
log.Println("Connecting to the Discord Gateway...")

// Connect the session to the Discord Gateway (WebSocket Connection).
if err := bot.Sessions[0].Connect(bot); err != nil {
s := disgo.NewSession()
if err := s.Connect(bot); err != nil {
log.Printf("can't open websocket session to Discord Gateway: %v", err)

return
Expand All @@ -86,15 +86,20 @@ func main() {
log.Println("Successfully connected to the Discord Gateway. Waiting for an interaction...")

// end the program using a SIGINT call via `Ctrl + C` from the terminal.
if err := tools.InterceptSignal(tools.Signals, bot.Sessions...); err != nil {
if err := tools.InterceptSignal(tools.Signals, s); err != nil {
log.Printf("error exiting program: %v", err)
}

log.Println("Deleting the application command...")
log.Println("Exiting program due to signal...")

// tools.InterceptSignal() calls s.Disconnect() which disconnects the Session from the Discord Gateway.
log.Println("Disconnected from the Discord Gateway.")

// The following code is not necessarily required, but useful for the cleanup of this program.
//
// delete the Global Application Command.
log.Println("Deleting the application command...")

requestDeleteGlobalApplicationCommand := &disgo.DeleteGlobalApplicationCommand{CommandID: newCommand.ID}
if err := requestDeleteGlobalApplicationCommand.Send(bot); err != nil {
log.Printf("error deleting Global Application Command: %v", err)
Expand Down
2 changes: 2 additions & 0 deletions _examples/command/localization/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ Upon receiving an interaction from the user, the bot will respond with a message
Use `ctrl + C` or `cmd + C` in the terminal.

```
Exiting program due to signal...
Disconnected from the Discord Gateway.
Deleting the application command...
Program executed successfully.
```
13 changes: 9 additions & 4 deletions _examples/command/localization/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ func main() {
Authentication: disgo.BotToken(token), // or BearerToken("TOKEN")
Config: disgo.DefaultConfig(),
Handlers: new(disgo.Handlers),
Sessions: []*disgo.Session{disgo.NewSession()},
}

log.Println("Creating an application command...")
Expand Down Expand Up @@ -121,7 +120,8 @@ func main() {
log.Println("Connecting to the Discord Gateway...")

// Connect the session to the Discord Gateway (WebSocket Connection).
if err := bot.Sessions[0].Connect(bot); err != nil {
s := disgo.NewSession()
if err := s.Connect(bot); err != nil {
log.Printf("can't open websocket session to Discord Gateway: %v", err)

return
Expand All @@ -130,15 +130,20 @@ func main() {
log.Println("Successfully connected to the Discord Gateway. Waiting for an interaction...")

// end the program using a SIGINT call via `Ctrl + C` from the terminal.
if err := tools.InterceptSignal(tools.Signals, bot.Sessions...); err != nil {
if err := tools.InterceptSignal(tools.Signals, s); err != nil {
log.Printf("error exiting program: %v", err)
}

log.Println("Deleting the application command...")
log.Println("Exiting program due to signal...")

// tools.InterceptSignal() calls s.Disconnect() which disconnects the Session from the Discord Gateway.
log.Println("Disconnected from the Discord Gateway.")

// The following code is not necessarily required, but useful for the cleanup of this program.
//
// delete the Global Application Command.
log.Println("Deleting the application command...")

requestDeleteGlobalApplicationCommand := &disgo.DeleteGlobalApplicationCommand{CommandID: newCommand.ID}
if err := requestDeleteGlobalApplicationCommand.Send(bot); err != nil {
log.Printf("error deleting Global Application Command: %v", err)
Expand Down
66 changes: 20 additions & 46 deletions _examples/command/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@ import (
"fmt"
"log"
"os"
"os/signal"
"syscall"

"github.com/switchupcb/disgo"
"github.com/switchupcb/disgo/tools"
)

// Environment Variables
Expand All @@ -34,7 +33,6 @@ func main() {
Authentication: disgo.BotToken(token), // or BearerToken("TOKEN")
Config: disgo.DefaultConfig(),
Handlers: new(disgo.Handlers),
Sessions: []*disgo.Session{disgo.NewSession()},
}

log.Println("Creating an application command...")
Expand Down Expand Up @@ -81,18 +79,32 @@ func main() {
log.Println("Connecting to the Discord Gateway...")

// Connect the session to the Discord Gateway (WebSocket Connection).
if err := bot.Sessions[0].Connect(bot); err != nil {
s := disgo.NewSession()
if err := s.Connect(bot); err != nil {
log.Printf("can't open websocket session to Discord Gateway: %v", err)

return
}

log.Println("Successfully connected to the Discord Gateway. Waiting for an interaction...")

// End the program using a SIGINT call via `Ctrl + C` from the terminal.
//
// The following code is equivalent to tools.InterceptSignal(tools.Signals, bot.Sessions...)
interceptSIGINT(bot, newCommand)
// end the program using a SIGINT call via `Ctrl + C` from the terminal.
tools.InterceptSignal(tools.Signals, s)

log.Println("Exiting program due to signal...")

// tools.InterceptSignal() calls s.Disconnect() which disconnects the Session from the Discord Gateway.
log.Println("Disconnected from the Discord Gateway.")

// Deleting the Global Application Command is not required, but useful for the cleanup of this program.
log.Println("Deleting the application command...")

requestDeleteGlobalApplicationCommand := &disgo.DeleteGlobalApplicationCommand{CommandID: newCommand.ID}
if err := requestDeleteGlobalApplicationCommand.Send(bot); err != nil {
log.Printf("error deleting Global Application Command: %v", err)

return
}

log.Printf("Program executed successfully.")
}
Expand Down Expand Up @@ -140,41 +152,3 @@ func onInteraction(bot *disgo.Client, interaction *disgo.Interaction, command *d

return nil
}

// interceptSIGINT intercepts the SIGINT signal for a graceful end of the program.
func interceptSIGINT(bot *disgo.Client, command *disgo.ApplicationCommand) {
// create an buffered channel (reason in goroutine below).
signalChannel := make(chan os.Signal, 1)

// set the syscalls that signalChannel is sent.
// https://www.gnu.org/software/libc/manual/html_node/Termination-Signals.html
signal.Notify(signalChannel,
syscall.SIGTERM,
syscall.SIGINT,
syscall.SIGQUIT,
syscall.SIGHUP,
)

// block this goroutine until a signal is received.
// https://go.dev/tour/concurrency/3
<-signalChannel

log.Println("Exiting program due to signal...")

// Deleting the Global Application Command is not required, but useful for the cleanup of this program.
log.Println("Deleting the application command...")

requestDeleteGlobalApplicationCommand := &disgo.DeleteGlobalApplicationCommand{CommandID: command.ID}
if err := requestDeleteGlobalApplicationCommand.Send(bot); err != nil {
log.Printf("error deleting Global Application Command: %v", err)
}

log.Println("Disconnecting from the Discord Gateway...")

// Disconnect the session from the Discord Gateway (WebSocket Connection).
if err := bot.Sessions[0].Disconnect(); err != nil {
log.Printf("error closing connection to Discord Gateway: %v", err)

os.Exit(1)
}
}
2 changes: 1 addition & 1 deletion _examples/command/subcommand/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,6 @@ Use `ctrl + C` or `cmd + C` in the terminal.

```
Exiting program due to signal...
Disconnecting from the Discord Gateway...
Disconnected from the Discord Gateway.
Program executed successfully.
```
Loading

0 comments on commit cbb525d

Please sign in to comment.