Skip to content

Commit ab7c545

Browse files
✨ Add Redis cache support (#58)
Co-authored-by: openhands <openhands@all-hands.dev>
1 parent 3fb12ae commit ab7c545

File tree

6 files changed

+75
-5
lines changed

6 files changed

+75
-5
lines changed

compose.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Copyright (c) NiceBots
2+
# SPDX-License-Identifier: MIT
3+
4+
services:
5+
redis:
6+
image: redis:alpine
7+
ports:
8+
- "6379:6379"
9+
command: --loglevel debug

config.example.yaml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,16 @@ extensions:
3636
every: 300 # 300 seconds = 5 minutes
3737
bot:
3838
token: "bot token here" # Your bot token
39+
cache:
40+
type: "memory" # Cache type. Possible values: "memory" or "redis"
41+
redis: # Redis configuration (only used if type is "redis")
42+
host: "localhost" # Redis server host
43+
port: 6379 # Redis server port
44+
db: 0 # Redis database number
45+
password: null # Redis password (optional)
46+
ssl: false # Whether to use SSL for Redis connection
3947
logging:
4048
level: "INFO" # The logging level. Possible values: DEBUG, INFO, WARNING, ERROR, CRITICAL
4149
use:
4250
bot: true # Whether to run the bot
4351
backend: false # Whether to run the backend
44-
45-

readme.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,35 @@ BOTKIT__extensions__listings__enabled=false
114114
BOTKIT__extensions__listings__topgg_token=your_top.gg_token
115115
BOTKIT__extensions__ping__enabled=true
116116
BOTKIT__logging__level=INFO
117+
BOTKIT__cache__type=redis
118+
BOTKIT__cache__redis__host=redis.example.com
119+
BOTKIT__cache__redis__port=6379
117120
```
118121

122+
### Cache Configuration
123+
124+
Botkit supports two types of caching:
125+
126+
- **Memory Cache**: Simple in-memory cache (default)
127+
- **Redis Cache**: Distributed cache using Redis
128+
129+
To configure the cache, use the `cache` section under the `bot` in your config:
130+
131+
```yaml
132+
bot:
133+
cache:
134+
type: "redis" # Use "memory" for in-memory cache
135+
redis: # Redis configuration (only needed when type is "redis")
136+
host: "localhost"
137+
port: 6379
138+
db: 0
139+
password: "optional" # Optional Redis password
140+
ssl: false # Whether to use SSL
141+
```
142+
143+
If Redis cache is requested but no configuration is provided, Botkit will fall back to
144+
memory cache with a warning.
145+
119146
## Creating Extensions
120147

121148
Extensions are in truth just python located in the `src/extensions` directory. When

src/custom/__init__.py

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,33 @@ def load_translations(self) -> None:
5151

5252

5353
class Bot(bridge.Bot):
54-
def __init__(self, *args: Any, **options: Any) -> None:
54+
def __init__(
55+
self, *args: Any, cache_type: str = "memory", cache_config: dict[str, Any] | None = None, **options: Any
56+
) -> None:
5557
self.translations: list[ExtensionTranslation] = options.pop("translations", [])
56-
self.cache: aiocache.SimpleMemoryCache | aiocache.RedisCache = aiocache.SimpleMemoryCache()
58+
59+
self.botkit_cache: aiocache.BaseCache
60+
# Initialize cache based on type and config
61+
if cache_type == "redis":
62+
if cache_config:
63+
logger.info("Using Redis cache")
64+
self.botkit_cache = aiocache.RedisCache(
65+
endpoint=cache_config.get("host", "localhost"),
66+
port=cache_config.get("port", 6379),
67+
db=cache_config.get("db", 0),
68+
password=cache_config.get("password"),
69+
ssl=cache_config.get("ssl", False),
70+
namespace="botkit",
71+
)
72+
else:
73+
logger.warning(
74+
"Redis cache type specified but no configuration provided. Falling back to memory cache."
75+
)
76+
self.botkit_cache = aiocache.SimpleMemoryCache(namespace="botkit")
77+
else:
78+
logger.info("Using memory cache")
79+
self.botkit_cache = aiocache.SimpleMemoryCache(namespace="botkit")
80+
5781
super().__init__(*args, **options)
5882

5983
@self.listen(name="on_ready", once=True)

src/start.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,10 +145,14 @@ async def setup_and_start_bot(
145145
intents = discord.Intents.default()
146146
if config.get("prefix"):
147147
intents.message_content = True
148+
# Get cache configuration
149+
cache_config = config.get("cache", {})
148150
bot = custom.Bot(
149151
intents=intents,
150152
help_command=None,
151153
command_prefix=(config.get("prefix", {}).get("prefix") or commands.when_mentioned),
154+
cache_type=cache_config.get("type", "memory"),
155+
cache_config=cache_config.get("redis"),
152156
)
153157
for function, its_config in bot_functions:
154158
setup_func(function, bot=bot, config=its_config)

src/utils/cooldown.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ def cooldown[C: commands.Cog, **P]( # noqa: PLR0913
9292
def inner(func: CogCommandFunction[C, P]) -> CogCommandFunction[C, P]:
9393
@wraps(func)
9494
async def wrapper(self: C, ctx: custom.ApplicationContext, *args: P.args, **kwargs: P.kwargs) -> None:
95-
cache = ctx.bot.cache
95+
cache = ctx.bot.botkit_cache
9696
key_value: str = await parse_reactive_setting(key, ctx.bot, ctx)
9797
limit_value: int = await parse_reactive_setting(limit, ctx.bot, ctx)
9898
per_value: int = await parse_reactive_setting(per, ctx.bot, ctx)

0 commit comments

Comments
 (0)