Skip to content

Commit 05a699a

Browse files
authored
slackbot: only dedupe root message; allow replies to process\n\n- Gate try_acquire/mark_completed only when event is the root (no thread_ts)\n- Prevent 'SKIPPED_DUPLICATE' on legitimate follow-ups in the same thread (#1225)
1 parent 5499afd commit 05a699a

1 file changed

Lines changed: 33 additions & 29 deletions

File tree

  • examples/slackbot/src/slackbot

examples/slackbot/src/slackbot/api.py

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -149,36 +149,38 @@ async def handle_message(payload: SlackPayload, db: Database):
149149
return Completed(message="Message too long", name="SKIPPED")
150150

151151
if re.search(BOT_MENTION, user_message) and payload.authorizations:
152-
# Use the root thread timestamp as our idempotency key
152+
# Only gate the root message; replies should not be blocked
153+
is_root_message = event.thread_ts is None
153154
root_ts = thread_ts
154155

155-
# Cross-process acquire; only one handler should proceed
156-
acquired = await try_acquire_thread(db, root_ts)
157-
if not acquired:
158-
status = await get_thread_status(db, root_ts)
159-
if status == "in_progress":
160-
assert event.channel is not None, (
161-
"Event channel is None when posting edit-ignored notice"
162-
)
163-
await post_slack_message(
164-
message=(
165-
"✋ I noticed you edited your original message. "
166-
"I'm already working on your first version — please add any "
167-
"clarifications as new messages in this thread so I don't lose track."
168-
),
169-
channel_id=event.channel,
170-
thread_ts=root_ts,
171-
)
156+
if is_root_message:
157+
# Cross-process acquire; only one handler should proceed for the root
158+
acquired = await try_acquire_thread(db, root_ts)
159+
if not acquired:
160+
status = await get_thread_status(db, root_ts)
161+
if status == "in_progress":
162+
assert event.channel is not None, (
163+
"Event channel is None when posting edit-ignored notice"
164+
)
165+
await post_slack_message(
166+
message=(
167+
"✋ I noticed you edited your original message. "
168+
"I'm already working on your first version — please add any "
169+
"clarifications as new messages in this thread so I don't lose track."
170+
),
171+
channel_id=event.channel,
172+
thread_ts=root_ts,
173+
)
174+
return Completed(
175+
message="Ignored edit while in progress",
176+
name="IGNORED_EDIT",
177+
data=dict(thread_ts=root_ts),
178+
)
172179
return Completed(
173-
message="Ignored edit while in progress",
174-
name="IGNORED_EDIT",
180+
message="Duplicate root event after completion",
181+
name="SKIPPED_DUPLICATE",
175182
data=dict(thread_ts=root_ts),
176183
)
177-
return Completed(
178-
message="Duplicate event after completion",
179-
name="SKIPPED_DUPLICATE",
180-
data=dict(thread_ts=root_ts),
181-
)
182184

183185
# Check if this is the designated channel
184186
team_id = payload.team_id or ""
@@ -261,10 +263,12 @@ async def handle_message(payload: SlackPayload, db: Database):
261263
data=dict(error=str(e), user_context=user_context),
262264
)
263265
finally:
264-
try:
265-
await mark_thread_completed(db, root_ts)
266-
except Exception:
267-
logger.warning("Failed to mark thread as completed")
266+
# Only mark completion for the root message; do not block replies
267+
if "is_root_message" in locals() and is_root_message:
268+
try:
269+
await mark_thread_completed(db, root_ts)
270+
except Exception:
271+
logger.warning("Failed to mark thread as completed")
268272

269273
return Completed(
270274
message="Responded to mention",

0 commit comments

Comments
 (0)