Skip to content

Commit 3fb0f1b

Browse files
committed
Add memory-cache wrapper for InstallationStore/AsyncInstallationStore
1 parent 930fcea commit 3fb0f1b

File tree

6 files changed

+151
-0
lines changed

6 files changed

+151
-0
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
from logging import Logger
2+
from typing import Optional, Dict
3+
4+
from slack_sdk.oauth.installation_store import Bot, Installation
5+
from slack_sdk.oauth.installation_store.async_installation_store import AsyncInstallationStore
6+
7+
8+
class AsyncCacheableInstallationStore(AsyncInstallationStore):
9+
underlying: AsyncInstallationStore
10+
cached_bots: Dict[str, Bot]
11+
12+
def __init__(self, installation_store: AsyncInstallationStore):
13+
"""A simple memory cache wrapper for any installation stores.
14+
15+
:param installation_store: the installation store to wrap
16+
"""
17+
self.underlying = installation_store
18+
self.cached_bots = {}
19+
20+
@property
21+
def logger(self) -> Logger:
22+
return self.underlying.logger
23+
24+
async def async_save(self, installation: Installation):
25+
return await self.underlying.async_save(installation)
26+
27+
async def async_find_bot(self, *, enterprise_id: Optional[str], team_id: Optional[str]) -> Optional[Bot]:
28+
pass
29+
key = f"{enterprise_id}-{team_id}"
30+
if key in self.cached_bots:
31+
return self.cached_bots[key]
32+
bot = await self.underlying.async_find_bot(enterprise_id=enterprise_id, team_id=team_id)
33+
if bot:
34+
self.cached_bots[key] = bot
35+
return bot
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
from logging import Logger
2+
from typing import Optional, Dict
3+
4+
from slack_sdk.oauth import InstallationStore
5+
from slack_sdk.oauth.installation_store import Bot, Installation
6+
7+
8+
class CacheableInstallationStore(InstallationStore):
9+
underlying: InstallationStore
10+
cached_bots: Dict[str, Bot]
11+
12+
def __init__(self, installation_store: InstallationStore):
13+
"""A simple memory cache wrapper for any installation stores.
14+
15+
:param installation_store: the installation store to wrap
16+
"""
17+
self.underlying = installation_store
18+
self.cached_bots = {}
19+
20+
@property
21+
def logger(self) -> Logger:
22+
return self.underlying.logger
23+
24+
def save(self, installation: Installation):
25+
return self.underlying.save(installation)
26+
27+
def find_bot(
28+
self, *, enterprise_id: Optional[str], team_id: Optional[str]
29+
) -> Optional[Bot]:
30+
key = f"{enterprise_id}-{team_id}"
31+
if key in self.cached_bots:
32+
return self.cached_bots[key]
33+
bot = self.underlying.find_bot(enterprise_id=enterprise_id, team_id=team_id)
34+
if bot:
35+
self.cached_bots[key] = bot
36+
return bot
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import os
2+
import unittest
3+
4+
from slack_sdk.oauth.installation_store import Installation
5+
from slack_sdk.oauth.installation_store.cacheable_installation_store import CacheableInstallationStore
6+
from slack_sdk.oauth.installation_store.sqlite3 import SQLite3InstallationStore
7+
8+
9+
class TestCacheable(unittest.TestCase):
10+
11+
def test_save_and_find(self):
12+
sqlite3_store = SQLite3InstallationStore(
13+
database="logs/cacheable.db",
14+
client_id="111.222"
15+
)
16+
sqlite3_store.init()
17+
store = CacheableInstallationStore(sqlite3_store)
18+
19+
installation = Installation(
20+
app_id="A111",
21+
enterprise_id="E111",
22+
team_id="T111",
23+
user_id="U111",
24+
bot_id="B111",
25+
bot_token="xoxb-111",
26+
bot_scopes=["chat:write"],
27+
bot_user_id="U222"
28+
)
29+
store.save(installation)
30+
31+
bot = store.find_bot(enterprise_id="E111", team_id="T111")
32+
self.assertIsNotNone(bot)
33+
34+
os.remove("logs/cacheable.db")
35+
36+
bot = sqlite3_store.find_bot(enterprise_id="E111", team_id="T111")
37+
self.assertIsNone(bot)
38+
bot = store.find_bot(enterprise_id="E111", team_id="T111")
39+
self.assertIsNotNone(bot)

tests/slack_sdk_async/oauth/__init__.py

Whitespace-only changes.

tests/slack_sdk_async/oauth/installation_store/__init__.py

Whitespace-only changes.
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import os
2+
import unittest
3+
4+
from slack_sdk.oauth.installation_store import Installation
5+
from slack_sdk.oauth.installation_store.async_cacheable_installation_store import AsyncCacheableInstallationStore
6+
from slack_sdk.oauth.installation_store.sqlite3 import SQLite3InstallationStore
7+
from tests.helpers import async_test
8+
9+
10+
class TestCacheable(unittest.TestCase):
11+
12+
@async_test
13+
async def test_save_and_find(self):
14+
sqlite3_store = SQLite3InstallationStore(
15+
database="logs/cacheable.db",
16+
client_id="111.222"
17+
)
18+
sqlite3_store.init()
19+
store = AsyncCacheableInstallationStore(sqlite3_store)
20+
21+
installation = Installation(
22+
app_id="A111",
23+
enterprise_id="E111",
24+
team_id="T111",
25+
user_id="U111",
26+
bot_id="B111",
27+
bot_token="xoxb-111",
28+
bot_scopes=["chat:write"],
29+
bot_user_id="U222"
30+
)
31+
await store.async_save(installation)
32+
33+
bot = await store.async_find_bot(enterprise_id="E111", team_id="T111")
34+
self.assertIsNotNone(bot)
35+
36+
os.remove("logs/cacheable.db")
37+
38+
bot = await sqlite3_store.async_find_bot(enterprise_id="E111", team_id="T111")
39+
self.assertIsNone(bot)
40+
bot = await store.async_find_bot(enterprise_id="E111", team_id="T111")
41+
self.assertIsNotNone(bot)

0 commit comments

Comments
 (0)