Skip to content

Commit 749c486

Browse files
committed
add room & contact cache
1 parent 3fc7d8c commit 749c486

File tree

3 files changed

+77
-8
lines changed

3 files changed

+77
-8
lines changed

src/wechaty/user/contact.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from __future__ import annotations
2222

2323
import types
24+
import os
2425
import asyncio
2526
import dataclasses
2627
import json
@@ -47,8 +48,9 @@
4748

4849
# from wechaty.utils import type_check
4950
from wechaty.exceptions import WechatyPayloadError, WechatyOperationError
50-
from wechaty.config import PARALLEL_TASK_NUM
51+
from wechaty.config import PARALLEL_TASK_NUM, config
5152
from wechaty.utils.async_helper import gather_with_concurrency
53+
from wechaty.utils.data_util import save_pickle_data, load_pickle_data
5254

5355
from ..accessory import Accessory
5456

@@ -64,7 +66,6 @@
6466

6567
log = get_logger('Contact')
6668

67-
6869
# pylint:disable=R0904
6970
class Contact(Accessory[ContactPayload], AsyncIOEventEmitter):
7071
"""
@@ -250,18 +251,39 @@ async def find_all(cls: Type[Contact],
250251
"""
251252
log.info('find_all() <%s, %s>', cls, query)
252253

254+
# 0. load from local cache file
255+
if config.cache_contacts and os.path.exists(config.cache_contact_path):
256+
contact_payloads = load_pickle_data(config.cache_contact_path)
257+
assert isinstance(contact_payloads, list)
258+
assert isinstance(contact_payloads[0], ContactPayload)
259+
260+
contact_payloads: List[ContactPayload] = contact_payloads
261+
contacts = []
262+
for contact_payload in contact_payloads:
263+
contact = cls.load(contact_payload.id)
264+
265+
# type: ignore
266+
contact._payload = contact_payload
267+
contacts.append(contact)
268+
return contacts
269+
253270
# 1. load contacts with concurrent tasks
254271
contact_ids: List[str] = await cls.get_puppet().contact_list()
255272

256273
contacts: List[Contact] = [cls.load(contact_id) for contact_id in contact_ids]
257274
tasks: List[Task] = [asyncio.create_task(contact.ready()) for contact in contacts]
258275
await gather_with_concurrency(PARALLEL_TASK_NUM, tasks)
259276

277+
if config.cache_contacts:
278+
contact_payloads = [contact.payload for contact in contacts if contact.payload is not None]
279+
save_pickle_data(contact_payloads, config.cache_contact_path)
280+
260281
# 2. filter contacts
261282
if not query:
262283
return contacts
263284

264285
contacts = cls._filter_contacts(contacts, query)
286+
265287
return contacts
266288

267289
async def ready(self, force_sync: bool = False) -> None:

src/wechaty/user/room.py

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
limitations under the License.
2020
"""
2121
from __future__ import annotations
22+
import os
2223
import types
2324
import asyncio
2425
import dataclasses
@@ -38,6 +39,7 @@
3839
import json
3940
from pyee import AsyncIOEventEmitter
4041
from wechaty.exceptions import WechatyOperationError, WechatyPayloadError
42+
from wechaty.config import config
4143
from wechaty_puppet import (
4244
FileBox,
4345
RoomQueryFilter,
@@ -50,6 +52,7 @@
5052
# from wechaty.utils import type_check
5153
from ..accessory import Accessory
5254
from ..config import AT_SEPARATOR, PARALLEL_TASK_NUM
55+
from wechaty.utils.data_util import save_pickle_data, load_pickle_data
5356
from wechaty.utils.async_helper import gather_with_concurrency
5457

5558
if TYPE_CHECKING:
@@ -222,11 +225,31 @@ async def find_all(cls,
222225
"""
223226
log.info('Room find_all <%s>', query)
224227

225-
# 1. load rooms with concurrent tasks
226-
room_ids = await cls.get_puppet().room_search()
227-
rooms: List[Room] = [cls.load(room_id) for room_id in room_ids]
228-
tasks: List[Task] = [asyncio.create_task(room.ready()) for room in rooms]
229-
await gather_with_concurrency(PARALLEL_TASK_NUM, tasks)
228+
# 0. load from local cache file
229+
if config.cache_rooms and os.path.exists(config.cache_room_path):
230+
room_payloads = load_pickle_data(config.cache_room_path)
231+
assert isinstance(room_payloads, list)
232+
assert isinstance(room_payloads[0], RoomPayload)
233+
234+
room_payloads: List[RoomPayload] = room_payloads
235+
rooms = []
236+
for room_payload in room_payloads:
237+
room = cls.load(room_payload.id)
238+
239+
# type: ignore
240+
room._payload = room_payload
241+
rooms.append(room)
242+
else:
243+
244+
# 1. load rooms with concurrent tasks
245+
room_ids = await cls.get_puppet().room_search()
246+
rooms: List[Room] = [cls.load(room_id) for room_id in room_ids]
247+
tasks: List[Task] = [asyncio.create_task(room.ready()) for room in rooms]
248+
await gather_with_concurrency(PARALLEL_TASK_NUM, tasks)
249+
250+
if config.cache_rooms:
251+
room_payloads = [room.payload for room in rooms if room.payload is not None]
252+
save_pickle_data(room_payloads, config.cache_contact_path)
230253

231254
# 2. filter the rooms
232255
if not query:

src/wechaty/utils/data_util.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,31 @@
2626
Any,
2727
)
2828
from collections import UserDict
29-
from wechaty.config import config
29+
import pickle
30+
31+
32+
def save_pickle_data(obj: object, path: str):
33+
"""save pickle data
34+
35+
Args:
36+
obj (object): the pickled data
37+
path (str): the path of pickle data
38+
"""
39+
with open(path, 'wb') as f:
40+
pickle.dump(obj, f)
41+
42+
def load_pickle_data(path: str) -> object:
43+
"""load pickle data from path
44+
45+
Args:
46+
path (str): the path of pickle data
47+
48+
Returns:
49+
object: the final data
50+
"""
51+
with open(path, 'rb') as f:
52+
data = pickle.load(f)
53+
return data
3054

3155

3256
class WechatySetting(UserDict):

0 commit comments

Comments
 (0)