diff --git a/src/modules/schedule/data.py b/src/modules/schedule/data.py index 1e007fe9..b6248aa8 100644 --- a/src/modules/schedule/data.py +++ b/src/modules/schedule/data.py @@ -22,8 +22,8 @@ class ScheduleData(Registry): results = {} to_fetch = set() for slotid in slotids: - row = cls._cache_.get(slotid, None) - if row is None: + row = cls._cache_.get((slotid,), None) + if row is None or row.data is None: to_fetch.add(slotid) else: results[slotid] = row @@ -82,7 +82,7 @@ class ScheduleData(Registry): to_fetch = set() for key in keys: row = cls._cache_.get(key, None) - if row is None: + if row is None or row.data is None: to_fetch.add(key) else: results[key] = row @@ -129,8 +129,8 @@ class ScheduleData(Registry): results = {} to_fetch = set() for guildid in guildids: - row = cls._cache_.get(guildid, None) - if row is None: + row = cls._cache_.get((guildid,), None) + if row is None or row.data is None: to_fetch.add(guildid) else: results[guildid] = row diff --git a/src/tracking/voice/cog.py b/src/tracking/voice/cog.py index 30040648..c075029f 100644 --- a/src/tracking/voice/cog.py +++ b/src/tracking/voice/cog.py @@ -247,6 +247,16 @@ class VoiceTrackerCog(LionCog): )) # Bulk create the ongoing sessions if to_create: + # First ensure the lion members exist + await self.bot.core.lions.fetch_members( + *(item[:2] for item in to_create) + ) + + # Then ensure the TrackedChannels exist + cids = set((item[2], item[0]) for item in to_create) + await self.data.TrackedChannel.fetch_multiple(*cids) + + # Then actually create the ongoing sessions rows = await self.data.VoiceSessionsOngoing.table.insert_many( ('guildid', 'userid', 'channelid', 'start_time', 'last_update', 'live_stream', 'live_video', 'hourly_coins'), @@ -415,6 +425,16 @@ class VoiceTrackerCog(LionCog): )) if to_create: + # Ensure LionMembers exist + await self.bot.core.lions.fetch_members( + *(item[:2] for item in to_create) + ) + + # Ensure TrackedChannels exist + cids = set((item[2], item[0]) for item in to_create) + await self.data.TrackedChannel.fetch_multiple(*cids) + + # Create new sessions rows = await self.data.VoiceSessionsOngoing.table.insert_many( ('guildid', 'userid', 'channelid', 'start_time', 'last_update', 'live_stream', 'live_video', 'hourly_coins'), @@ -567,6 +587,16 @@ class VoiceTrackerCog(LionCog): )) if to_create: + # Ensure LionMembers exist + await self.bot.core.lions.fetch_members( + *(item[:2] for item in to_create) + ) + + # Ensure TrackedChannels exist + cids = set((item[2], item[0]) for item in to_create) + await self.data.TrackedChannel.fetch_multiple(*cids) + + # Create new sessions rows = await self.data.VoiceSessionsOngoing.table.insert_many( ('guildid', 'userid', 'channelid', 'start_time', 'last_update', 'live_stream', 'live_video', 'hourly_coins'), @@ -599,7 +629,8 @@ class VoiceTrackerCog(LionCog): if session.expiry_task is not None: session.expiry_task.cancel() to_close.append(session.guildid, session.userid, now) - await self.data.VoiceSessionsOngoing.close_voice_sessions_at(*to_close) + if to_close: + await self.data.VoiceSessionsOngoing.close_voice_sessions_at(*to_close) logger.info( f"Closed {len(to_close)} voice sessions after leaving guild '{guild.name}' " ) diff --git a/src/tracking/voice/data.py b/src/tracking/voice/data.py index a8576eac..164c7137 100644 --- a/src/tracking/voice/data.py +++ b/src/tracking/voice/data.py @@ -37,6 +37,39 @@ class VoiceTrackerData(Registry): deleted = Bool() _timestamp = Timestamp() + @classmethod + async def fetch_multiple(cls, *keys, create=True): + """ + Fetch and optionally create multiple row, applying cache where possible. + + Provided keys should be in the form (channelid, guildid) + Results will be provided as a map channelid -> Row + """ + cidmap = {cid: gid for cid, gid in keys} + + results = {} + to_fetch = set() + for cid in cidmap: + row = cls._cache_.get((cid,), None) + if row is None or row.data is None: + to_fetch.add(cid) + else: + results[cid] = row + + if to_fetch: + rows = await cls.fetch_where(channelid=list(cidmap.keys())) + for row in rows: + results[row.channelid] = row + to_fetch.remove(row.channelid) + if to_fetch and create: + rows = await cls.table.insert_many( + ('channelid', 'guildid', 'deleted'), + *((cid, cidmap[cid], False) for cid in to_fetch) + ).with_adapter(cls._make_rows) + for row in rows: + results[row.channelid] = row + return results + class VoiceSessionsOngoing(RowModel): """ Model describing currently active voice sessions. diff --git a/src/tracking/voice/session.py b/src/tracking/voice/session.py index 160dafb6..cf662caa 100644 --- a/src/tracking/voice/session.py +++ b/src/tracking/voice/session.py @@ -153,14 +153,16 @@ class VoiceSession: f"Starting voice session for member in guild " f"and channel ." ) + # Create the lion if required + await self.bot.core.lions.fetch_member(self.guildid, self.userid) + + # Create the tracked channel if required + await self.registry.TrackedChannel.fetch_or_create( + self.state.channelid, guildid=self.guildid, deleted=False + ) conn = await self.bot.db.get_connection() async with conn.transaction(): - # Create the tracked channel if required - await self.registry.TrackedChannel.fetch_or_create( - self.state.channelid, guildid=self.guildid, deleted=False - ) - # Insert an ongoing_session with the correct state, set data state = self.state self.data = await self.registry.VoiceSessionsOngoing.create(