fix (voice): Fix data preconditions.

Fixes issue where voice session would start without member data.
Fixes issue where voice session would start without channel data.
Fixes issue on init where sessions would start without keys.
Fixes issue on guild join where sessions would start without keys.
Fixes issue in schedule where data cache key was built incorrectly.
This commit is contained in:
2023-07-07 18:26:43 +03:00
parent ce68813788
commit 497419a441
4 changed files with 77 additions and 11 deletions

View File

@@ -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

View File

@@ -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}' <gid:{guild.id}>"
)

View File

@@ -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.

View File

@@ -153,14 +153,16 @@ class VoiceSession:
f"Starting voice session for member <uid:{self.userid}> in guild <gid:{self.guildid}> "
f"and channel <cid:{self.state.channelid}>."
)
# 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(