From 51cfd57930d62f0e275aa4d96e52838d961a8edd Mon Sep 17 00:00:00 2001 From: CD Date: Sat, 7 Mar 2026 13:37:22 +0900 Subject: [PATCH] fix: asyncio.Lock on channel create + PROJECT_NAME in .env.example --- .env.example | 3 +++ bot.py | 50 ++++++++++++++++++++++++++++---------------------- 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/.env.example b/.env.example index f33729f..d6490f2 100644 --- a/.env.example +++ b/.env.example @@ -10,5 +10,8 @@ BRAIN_PATH=C:\Users\Certes\.gemini\antigravity\brain # 세션 활성 판단: 마지막 파일 변경으로부터 이 시간(초) 이내면 활성 ACTIVE_TIMEOUT_SECONDS=300 +# Project name (used for Discord channel: AG-{PROJECT_NAME}) +PROJECT_NAME=gravity_control + # Watcher Settings DEBOUNCE_SECONDS=2 diff --git a/bot.py b/bot.py index 572ab0d..9988fec 100644 --- a/bot.py +++ b/bot.py @@ -97,6 +97,7 @@ class GravityBot(commands.Bot): self.session_status_messages: dict[str, int] = {} # conv_id → msg_id self._sent_approval_ids: set[str] = set() self._ready_event = asyncio.Event() + self._channel_lock = asyncio.Lock() # Prevents double-create race self.bridge = BridgeProtocol() self.session_category: discord.CategoryChannel | None = None self.guild: discord.Guild | None = None @@ -187,33 +188,38 @@ class GravityBot(commands.Bot): async def _get_project_channel(self) -> discord.TextChannel: """Get the project channel. Create if it doesn't exist yet. - Thread-safe: only ONE channel will ever be created because - self.project_channel acts as a singleton guard. + Uses asyncio.Lock to prevent race between event processor + and approval scanner both creating channels simultaneously. """ if self.project_channel: return self.project_channel - # Create the channel - try: - self.project_channel = await self.guild.create_text_channel( - name=self._channel_name, - category=self.session_category, - topic=f"Gravity Control — Antigravity Bridge", - ) - logger.info(f"Created project channel: #{self._channel_name}") + async with self._channel_lock: + # Double-check after acquiring lock + if self.project_channel: + return self.project_channel - embed = discord.Embed( - title=f"🚀 {Config.PROJECT_NAME}", - description=( - f"Antigravity Bridge 연결됨\n" - f"모든 세션 이벤트가 이 채널로 전달됩니다." - ), - color=discord.Color.blue(), - timestamp=datetime.now(timezone.utc), - ) - await self.project_channel.send(embed=embed) - except discord.errors.Forbidden: - logger.error(f"No permission to create channel: {self._channel_name}") + # Create the channel + try: + self.project_channel = await self.guild.create_text_channel( + name=self._channel_name, + category=self.session_category, + topic=f"Gravity Control — Antigravity Bridge", + ) + logger.info(f"Created project channel: #{self._channel_name}") + + embed = discord.Embed( + title=f"🚀 {Config.PROJECT_NAME}", + description=( + f"Antigravity Bridge 연결됨\n" + f"모든 세션 이벤트가 이 채널로 전달됩니다." + ), + color=discord.Color.blue(), + timestamp=datetime.now(timezone.utc), + ) + await self.project_channel.send(embed=embed) + except discord.errors.Forbidden: + logger.error(f"No permission to create channel: {self._channel_name}") return self.project_channel