Skip to content

Commit 0142614

Browse files
authored
Use redis to manage Slack integration state (#204)
1 parent 9c59a4e commit 0142614

File tree

1 file changed

+28
-11
lines changed
  • apps/roomote/src/app/api/webhooks/slack

1 file changed

+28
-11
lines changed

apps/roomote/src/app/api/webhooks/slack/route.ts

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,16 @@ import { eq } from 'drizzle-orm';
44
import { db, cloudJobs } from '@roo-code-cloud/db/server';
55

66
import { SlackNotifier } from '@/lib/slack';
7+
import { redis } from '@/lib/redis';
78

89
import { createAndEnqueueJob } from '../github/handlers/utils';
910

10-
const mentionedThreads = new Set<string>();
11-
const pendingWorkspaceSelections = new Map<string, SlackEvent>();
1211
const slack = new SlackNotifier();
1312

13+
// Redis keys for storing thread data
14+
const MENTIONED_THREADS_KEY = 'slack:mentioned_threads';
15+
const PENDING_WORKSPACE_SELECTIONS_KEY = 'slack:pending_workspace_selections';
16+
1417
interface SlackEvent {
1518
type: string;
1619
channel: string;
@@ -126,13 +129,17 @@ async function handleInteractivePayload(payload: SlackInteractivePayload) {
126129
const threadId = payload.message.thread_ts || payload.message.ts;
127130

128131
try {
129-
const originalEvent = pendingWorkspaceSelections.get(threadId);
132+
const originalEventJson = await redis.hget(
133+
PENDING_WORKSPACE_SELECTIONS_KEY,
134+
threadId,
135+
);
130136

131-
if (!originalEvent) {
137+
if (!originalEventJson) {
132138
throw new Error('Original mention event not found');
133139
}
134140

135-
pendingWorkspaceSelections.delete(threadId);
141+
const originalEvent: SlackEvent = JSON.parse(originalEventJson);
142+
await redis.hdel(PENDING_WORKSPACE_SELECTIONS_KEY, threadId);
136143

137144
const { jobId, enqueuedJobId } = await createAndEnqueueJob(
138145
'slack.app.mention',
@@ -161,10 +168,8 @@ async function handleInteractivePayload(payload: SlackInteractivePayload) {
161168
.set({ slackThreadTs: threadId })
162169
.where(eq(cloudJobs.id, jobId));
163170
} catch (error) {
164-
console.error('❌ Failed to process workspace selection:', error);
165-
166171
await slack.postMessage({
167-
text: `❌ Sorry, something went wrong processing your request. Please try again.`,
172+
text: `❌ ${error instanceof Error ? error.message : 'Unknown error'}`,
168173
channel: payload.channel.id,
169174
thread_ts: threadId,
170175
});
@@ -175,11 +180,15 @@ async function handleInteractivePayload(payload: SlackInteractivePayload) {
175180
async function handleAppMention(event: SlackEvent) {
176181
console.log('🤖 Bot mentioned in channel:', event.channel);
177182
const threadId = event.thread_ts || event.ts;
178-
mentionedThreads.add(threadId);
183+
await redis.sadd(MENTIONED_THREADS_KEY, threadId);
179184
console.log(`📌 Tracking thread: ${threadId}`);
180185

181186
try {
182-
pendingWorkspaceSelections.set(threadId, event);
187+
await redis.hset(
188+
PENDING_WORKSPACE_SELECTIONS_KEY,
189+
threadId,
190+
JSON.stringify(event),
191+
);
183192

184193
const workspaceRoot = process.env.WORKSPACE_ROOT || '/roo/repos';
185194

@@ -222,7 +231,15 @@ async function handleAppMention(event: SlackEvent) {
222231
}
223232

224233
async function handleMessage(event: SlackEvent) {
225-
if (!event.thread_ts || !mentionedThreads.has(event.thread_ts)) {
234+
if (!event.thread_ts) {
235+
return;
236+
}
237+
238+
const isTrackedThread = await redis.sismember(
239+
MENTIONED_THREADS_KEY,
240+
event.thread_ts,
241+
);
242+
if (!isTrackedThread) {
226243
return;
227244
}
228245

0 commit comments

Comments
 (0)