fix: asyncio.Lock on channel create + PROJECT_NAME in .env.example

This commit is contained in:
2026-03-07 13:37:22 +09:00
parent efaf29a6d2
commit 51cfd57930
2 changed files with 31 additions and 22 deletions

View File

@@ -10,5 +10,8 @@ BRAIN_PATH=C:\Users\Certes\.gemini\antigravity\brain
# 세션 활성 판단: 마지막 파일 변경으로부터 이 시간(초) 이내면 활성 # 세션 활성 판단: 마지막 파일 변경으로부터 이 시간(초) 이내면 활성
ACTIVE_TIMEOUT_SECONDS=300 ACTIVE_TIMEOUT_SECONDS=300
# Project name (used for Discord channel: AG-{PROJECT_NAME})
PROJECT_NAME=gravity_control
# Watcher Settings # Watcher Settings
DEBOUNCE_SECONDS=2 DEBOUNCE_SECONDS=2

50
bot.py
View File

@@ -97,6 +97,7 @@ class GravityBot(commands.Bot):
self.session_status_messages: dict[str, int] = {} # conv_id → msg_id self.session_status_messages: dict[str, int] = {} # conv_id → msg_id
self._sent_approval_ids: set[str] = set() self._sent_approval_ids: set[str] = set()
self._ready_event = asyncio.Event() self._ready_event = asyncio.Event()
self._channel_lock = asyncio.Lock() # Prevents double-create race
self.bridge = BridgeProtocol() self.bridge = BridgeProtocol()
self.session_category: discord.CategoryChannel | None = None self.session_category: discord.CategoryChannel | None = None
self.guild: discord.Guild | None = None self.guild: discord.Guild | None = None
@@ -187,33 +188,38 @@ class GravityBot(commands.Bot):
async def _get_project_channel(self) -> discord.TextChannel: async def _get_project_channel(self) -> discord.TextChannel:
"""Get the project channel. Create if it doesn't exist yet. """Get the project channel. Create if it doesn't exist yet.
Thread-safe: only ONE channel will ever be created because Uses asyncio.Lock to prevent race between event processor
self.project_channel acts as a singleton guard. and approval scanner both creating channels simultaneously.
""" """
if self.project_channel: if self.project_channel:
return self.project_channel return self.project_channel
# Create the channel async with self._channel_lock:
try: # Double-check after acquiring lock
self.project_channel = await self.guild.create_text_channel( if self.project_channel:
name=self._channel_name, return self.project_channel
category=self.session_category,
topic=f"Gravity Control — Antigravity Bridge",
)
logger.info(f"Created project channel: #{self._channel_name}")
embed = discord.Embed( # Create the channel
title=f"🚀 {Config.PROJECT_NAME}", try:
description=( self.project_channel = await self.guild.create_text_channel(
f"Antigravity Bridge 연결됨\n" name=self._channel_name,
f"모든 세션 이벤트가 이 채널로 전달됩니다." category=self.session_category,
), topic=f"Gravity Control — Antigravity Bridge",
color=discord.Color.blue(), )
timestamp=datetime.now(timezone.utc), logger.info(f"Created project channel: #{self._channel_name}")
)
await self.project_channel.send(embed=embed) embed = discord.Embed(
except discord.errors.Forbidden: title=f"🚀 {Config.PROJECT_NAME}",
logger.error(f"No permission to create channel: {self._channel_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 return self.project_channel