Skip to content
This repository was archived by the owner on Jun 23, 2025. It is now read-only.

Commit 7043905

Browse files
Merge pull request #1714 from DiceDB/arpitbbhayani
Reactivity Example - Leaderboard
2 parents 7d4f6f6 + 18ec465 commit 7043905

File tree

17 files changed

+242
-32
lines changed

17 files changed

+242
-32
lines changed

docs/astro.config.mjs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ export default defineConfig({
4040
{
4141
label: "Examples and Tutorials",
4242
items: [
43+
{
44+
label: "Leaderboard",
45+
link: "https://github.com/DiceDB/dice/tree/master/examples/leaderboard-go",
46+
},
4347
{
4448
label: "CLI Chatroom",
4549
link: "https://github.com/DiceDB/dice/tree/master/examples/chatroom-go",

docs/src/components/Footer.astro

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,12 @@ const { stars } = await fetchRepoDetails();
6060
Examples
6161
</div>
6262
<p>
63+
<a
64+
href="https://github.com/DiceDB/dice/tree/master/examples/leaderboard-go"
65+
target="_blank"
66+
>
67+
Leaderboard</a
68+
>
6369
<a
6470
href="https://github.com/DiceDB/dice/tree/master/examples/chatroom-go"
6571
target="_blank"

docs/src/content/docs/get-started/hello-world-reactive.mdx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,10 @@ whenever the value of `k1` changes, but it is not just a change event, but the a
5757
This makes it really powerful and flexible to build real-time applications.
5858

5959
> Note: In CLI, you can watch one command at a time, but programmatically you can watch multiple commands at the same time
60-
> and handle them in parallel. You can take a look at our [Chatroom](https://github.com/DiceDB/dice/tree/master/examples/chatroom-go) to see how to do that.
60+
> and handle them in parallel. You can take a look at the following examples to see how to do that
61+
>
62+
> - [Chatroom](https://github.com/DiceDB/dice/tree/master/examples/chatroom-go)
63+
> - [Leaderboard](https://github.com/DiceDB/dice/tree/master/examples/leaderboard-go)
6164
6265
## What else can I watch?
6366

docs/src/content/docs/get-started/hello-world.mdx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ You can follow the steps mentioned in the [installation](/get-started/installati
1717
Once the DiceDB server starts, you will see output similar to this
1818

1919
```
20-
██████╗ ██╗ ██████╗███████╗██████╗ ██████╗
20+
██████╗ ██╗ ██████╗███████╗██████╗ ██████╗
2121
██╔══██╗██║██╔════╝██╔════╝██╔══██╗██╔══██╗
2222
██║ ██║██║██║ █████╗ ██║ ██║██████╔╝
2323
██║ ██║██║██║ ██╔══╝ ██║ ██║██╔══██╗
@@ -54,7 +54,7 @@ then retrieve it using the [`GET`](/commands/get) command.
5454

5555
```bash
5656
localhost:7379> SET k1 v1
57-
OK
57+
OK
5858
localhost:7379> GET k1
5959
OK "v1"
6060
```
@@ -73,5 +73,7 @@ Note: The first `OK` is the status of the command, while the second `OK` is the
7373
This is just the tip of the iceberg when it comes to DiceDB.
7474
We've covered the basics of connecting to a DiceDB instance, storing a simple string, and retrieving it.
7575
The true power of DiceDB lies in its ability to intuitively build reactive applications
76-
like [chatrooms](https://github.com/DiceDB/dice/tree/master/examples/chatroom-go), handle complex data structures and perform operations efficiently.
76+
like [chatrooms](https://github.com/DiceDB/dice/tree/master/examples/chatroom-go) and
77+
[leaderboards](https://github.com/DiceDB/dice/tree/master/examples/leaderboard-go),
78+
handle complex data structures and perform operations efficiently.
7779
But all of that after we do our first tutorial for reactivity and query subscriptions.

examples/leaderboard-go/README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
Leaderboard
2+
===
3+
4+
1. start the DiceDB server
5+
2. run the following command from one terminal session
6+
7+
```sh
8+
$ go run main.go mock
9+
```
10+
11+
3. run the following command from 3 other terminal sessions
12+
13+
```sh
14+
$ go run main.go
15+
```

examples/leaderboard-go/go.mod

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
module leaderboard-go
2+
3+
go 1.24.0
4+
5+
require (
6+
github.com/charmbracelet/bubbles v0.20.0
7+
github.com/charmbracelet/lipgloss v1.0.0
8+
github.com/dicedb/dicedb-go v1.0.9
9+
)
10+
11+
require (
12+
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
13+
github.com/charmbracelet/bubbletea v1.2.4 // indirect
14+
github.com/charmbracelet/x/ansi v0.4.5 // indirect
15+
github.com/charmbracelet/x/term v0.2.1 // indirect
16+
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
17+
github.com/google/uuid v1.6.0 // indirect
18+
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
19+
github.com/mattn/go-isatty v0.0.20 // indirect
20+
github.com/mattn/go-localereader v0.0.1 // indirect
21+
github.com/mattn/go-runewidth v0.0.16 // indirect
22+
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
23+
github.com/muesli/cancelreader v0.2.2 // indirect
24+
github.com/muesli/termenv v0.15.2 // indirect
25+
github.com/rivo/uniseg v0.4.7 // indirect
26+
golang.org/x/sync v0.9.0 // indirect
27+
golang.org/x/sys v0.27.0 // indirect
28+
golang.org/x/text v0.3.8 // indirect
29+
google.golang.org/protobuf v1.36.5 // indirect
30+
)

examples/leaderboard-go/go.sum

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
2+
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
3+
github.com/charmbracelet/bubbles v0.20.0 h1:jSZu6qD8cRQ6k9OMfR1WlM+ruM8fkPWkHvQWD9LIutE=
4+
github.com/charmbracelet/bubbles v0.20.0/go.mod h1:39slydyswPy+uVOHZ5x/GjwVAFkCsV8IIVy+4MhzwwU=
5+
github.com/charmbracelet/bubbletea v1.2.4 h1:KN8aCViA0eps9SCOThb2/XPIlea3ANJLUkv3KnQRNCE=
6+
github.com/charmbracelet/bubbletea v1.2.4/go.mod h1:Qr6fVQw+wX7JkWWkVyXYk/ZUQ92a6XNekLXa3rR18MM=
7+
github.com/charmbracelet/lipgloss v1.0.0 h1:O7VkGDvqEdGi93X+DeqsQ7PKHDgtQfF8j8/O2qFMQNg=
8+
github.com/charmbracelet/lipgloss v1.0.0/go.mod h1:U5fy9Z+C38obMs+T+tJqst9VGzlOYGj4ri9reL3qUlo=
9+
github.com/charmbracelet/x/ansi v0.4.5 h1:LqK4vwBNaXw2AyGIICa5/29Sbdq58GbGdFngSexTdRM=
10+
github.com/charmbracelet/x/ansi v0.4.5/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw=
11+
github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
12+
github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
13+
github.com/dicedb/dicedb-go v1.0.9 h1:WtXtX6Bu/KFjhnOIlnoo9Z1hbmOtL2tMrUmS6793/Pw=
14+
github.com/dicedb/dicedb-go v1.0.9/go.mod h1:V1fiCJnPfSObKWrOJ/zrhHEGlLwT9k3pKCto3sz1oW8=
15+
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
16+
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
17+
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
18+
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
19+
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
20+
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
21+
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
22+
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
23+
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
24+
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
25+
github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=
26+
github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
27+
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
28+
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
29+
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI=
30+
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
31+
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
32+
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
33+
github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo=
34+
github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8=
35+
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
36+
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
37+
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
38+
go.uber.org/mock v0.5.1 h1:ASgazW/qBmR+A32MYFDB6E2POoTgOwT509VP0CT/fjs=
39+
go.uber.org/mock v0.5.1/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
40+
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
41+
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
42+
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
43+
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
44+
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
45+
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
46+
golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY=
47+
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
48+
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
49+
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
50+
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
51+
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=

examples/leaderboard-go/main.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright (c) 2022-present, DiceDB contributors
2+
// All rights reserved. Licensed under the BSD 3-Clause License. See LICENSE file in the project root for full license information.
3+
4+
package main
5+
6+
import (
7+
"fmt"
8+
"leaderboard-go/svc"
9+
"math/rand"
10+
"os"
11+
"os/signal"
12+
"syscall"
13+
"time"
14+
15+
"github.com/dicedb/dicedb-go/wire"
16+
)
17+
18+
var players = []string{"Alice", "Bob", "Charlie", "Dora", "Evan", "Fay", "Gina"}
19+
20+
func main() {
21+
if len(os.Args) > 1 && os.Args[1] == "mock" {
22+
for {
23+
player := players[rand.Intn(len(players))]
24+
score := rand.Intn(100)
25+
svc.UpdateScore(player, score)
26+
fmt.Println("updated game:scores for", player, "with score", score)
27+
time.Sleep(time.Millisecond * 500)
28+
}
29+
}
30+
31+
// Set up signal handling for graceful shutdown
32+
sigChan := make(chan os.Signal, 1)
33+
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
34+
35+
// Subscribe to leaderboard updates
36+
svc.Subscribe()
37+
38+
// Start listening for messages
39+
go svc.ListenForMessages(func(result *wire.Result) {
40+
displayLeaderboard(result.GetZRANGERes().Elements)
41+
})
42+
43+
// Wait for interrupt signal
44+
<-sigChan
45+
fmt.Println("\nShutting down...")
46+
}
47+
48+
func displayLeaderboard(leaderboard []*wire.ZElement) {
49+
// Clear the screen
50+
fmt.Print("\033[H\033[2J")
51+
52+
fmt.Println("Rank Score Player")
53+
fmt.Println("------------------")
54+
55+
for _, element := range leaderboard {
56+
fmt.Printf("%2d. %4d %s\n", element.Rank, element.Score, element.Member)
57+
}
58+
59+
fmt.Println("------------------")
60+
fmt.Println("Press Ctrl+C to exit")
61+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Copyright (c) 2022-present, DiceDB contributors
2+
// All rights reserved. Licensed under the BSD 3-Clause License. See LICENSE file in the project root for full license information.
3+
4+
package svc
5+
6+
import (
7+
"fmt"
8+
"strconv"
9+
10+
"github.com/dicedb/dicedb-go"
11+
"github.com/dicedb/dicedb-go/wire"
12+
)
13+
14+
var (
15+
client *dicedb.Client
16+
)
17+
18+
func init() {
19+
var err error
20+
client, err = dicedb.NewClient("localhost", 7379)
21+
if err != nil {
22+
panic(err)
23+
}
24+
}
25+
26+
func UpdateScore(player string, score int) {
27+
resp := client.Fire(&wire.Command{
28+
Cmd: "ZADD",
29+
Args: []string{"game:scores", strconv.Itoa(score), player},
30+
})
31+
if resp.Status == wire.Status_ERR {
32+
fmt.Println("error updating score:", resp.Message)
33+
}
34+
}
35+
36+
func Subscribe() {
37+
resp := client.Fire(&wire.Command{
38+
Cmd: "ZRANGE.WATCH",
39+
Args: []string{"game:scores", "1", "5", "BYRANK"},
40+
})
41+
if resp.Status == wire.Status_ERR {
42+
fmt.Println("error subscribing:", resp.Message)
43+
}
44+
}
45+
46+
func ListenForMessages(onMessage func(result *wire.Result)) {
47+
ch, err := client.WatchCh()
48+
if err != nil {
49+
panic(err)
50+
}
51+
for resp := range ch {
52+
if resp.Status == wire.Status_ERR {
53+
fmt.Println("error listening for messages:", resp.Message)
54+
} else {
55+
onMessage(resp)
56+
}
57+
}
58+
}

internal/cmd/cmd_get_watch.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ func evalGETWATCH(c *Cmd, s *dstore.Store) (*CmdRes, error) {
7171
}
7272

7373
func executeGETWATCH(c *Cmd, sm *shardmanager.ShardManager) (*CmdRes, error) {
74-
if len(c.C.Args) != 1 {
74+
if len(c.C.Args) == 0 {
7575
return GETWATCHResNilRes, errors.ErrWrongArgumentCount("GET.WATCH")
7676
}
7777
shard := sm.GetShardForKey(c.C.Args[0])

0 commit comments

Comments
 (0)