Skip to content

Commit 5ed3935

Browse files
committed
Remove module-level app instance that uses lazy loading
1 parent 680ffaa commit 5ed3935

File tree

6 files changed

+126
-217
lines changed

6 files changed

+126
-217
lines changed

packages/slackBotFunction/app/config/config.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1+
"""
2+
Configuration module - initializes AWS clients, Slack app, and environment variables
3+
"""
4+
15
import os
26
import json
37
import boto3
8+
from slack_bolt import App
49
from aws_lambda_powertools import Logger
510
from aws_lambda_powertools.utilities.parameters import get_parameter
611

@@ -30,4 +35,11 @@
3035
bot_token = json.loads(bot_token_raw)["token"]
3136
signing_secret = json.loads(signing_secret_raw)["secret"]
3237

38+
# Initialize Slack app
39+
app = App(
40+
process_before_response=True,
41+
token=bot_token,
42+
signing_secret=signing_secret,
43+
)
44+
3345
logger.info(f"Guardrail ID: {GUARD_RAIL_ID}, Version: {GUARD_VERSION}")

packages/slackBotFunction/app/handler.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
1+
"""
2+
Main Lambda handler - processes Slack events and async operations
3+
"""
4+
15
from slack_bolt.adapter.aws_lambda import SlackRequestHandler
26
from aws_lambda_powertools import Logger
37
from aws_lambda_powertools.utilities.typing import LambdaContext
4-
from app.slack.slack_handlers import get_app
8+
from app.config.config import app
59
from app.slack.slack_events import process_async_slack_event
10+
from app.slack.slack_handlers import setup_handlers
11+
12+
# Register event handlers
13+
setup_handlers(app)
614

715
logger = Logger(service="slackBotFunction")
816

@@ -15,5 +23,5 @@ def handler(event: dict, context: LambdaContext) -> dict:
1523
process_async_slack_event(event["slack_event"])
1624
return {"statusCode": 200}
1725

18-
slack_handler = SlackRequestHandler(app=get_app())
26+
slack_handler = SlackRequestHandler(app=app)
1927
return slack_handler.handle(event, context)

packages/slackBotFunction/app/slack/slack_events.py

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
"""
2+
Slack event processing - handles async message processing and Bedrock integration
3+
"""
4+
15
import re
2-
import json
36
import boto3
47
from slack_sdk import WebClient
58
from aws_lambda_powertools import Logger
@@ -9,22 +12,11 @@
912
AWS_REGION,
1013
GUARD_RAIL_ID,
1114
GUARD_VERSION,
12-
AWS_LAMBDA_FUNCTION_NAME,
1315
)
1416

1517
logger = Logger(service="slackBotFunction")
1618

1719

18-
def trigger_async_processing(event_data):
19-
"""Trigger async processing of the Slack event to avoid timeout issues."""
20-
lambda_client = boto3.client("lambda")
21-
lambda_client.invoke(
22-
FunctionName=AWS_LAMBDA_FUNCTION_NAME,
23-
InvocationType="Event",
24-
Payload=json.dumps({"async_processing": True, "slack_event": event_data}),
25-
)
26-
27-
2820
def get_bedrock_knowledgebase_response(user_query):
2921
"""Get and return the Bedrock Knowledge Base RetrieveAndGenerate response."""
3022
client = boto3.client(
Lines changed: 50 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,97 +1,93 @@
1+
"""
2+
Slack event handlers - handles @mentions and direct messages to the bot
3+
"""
4+
15
import time
2-
from slack_bolt import App
3-
from aws_lambda_powertools import Logger
6+
import json
7+
import os
8+
import boto3
49
from botocore.exceptions import ClientError
5-
from app.slack.slack_events import trigger_async_processing
10+
from aws_lambda_powertools import Logger
611

712
logger = Logger(service="slackBotFunction")
813

9-
# Lazy initialization of Slack app
10-
_app = None
11-
12-
13-
def get_app():
14-
"""Get or create the Slack app instance"""
15-
global _app
16-
if _app is None:
17-
from app.config.config import bot_token, signing_secret
18-
19-
_app = App(
20-
process_before_response=True,
21-
token=bot_token,
22-
signing_secret=signing_secret,
23-
)
24-
_setup_handlers(_app)
25-
return _app
26-
2714

28-
def _setup_handlers(app_instance):
29-
"""Setup event handlers for the app"""
15+
def setup_handlers(app):
16+
"""
17+
Register all event handlers with the Slack app
18+
"""
3019
from app.config.config import bot_token
3120

32-
@app_instance.middleware
21+
@app.middleware
3322
def log_request(slack_logger, body, next):
34-
"""Middleware to log incoming Slack requests using AWS Lambda Powertools logger."""
3523
logger.debug("Slack request received", extra={"body": body})
3624
return next()
3725

38-
@app_instance.event("app_mention")
26+
@app.event("app_mention")
3927
def handle_app_mention(event, ack, body):
40-
"""Handle when the bot is @mentioned"""
28+
"""
29+
Handle @mentions in channels
30+
"""
4131
ack()
4232

4333
event_id = body.get("event_id")
44-
if not event_id:
45-
logger.warning("Missing event_id in Slack event body.")
46-
elif is_duplicate_event(event_id):
47-
logger.info(f"Duplicate event detected, skipping: {event_id}")
34+
if not event_id or is_duplicate_event(event_id):
35+
logger.info(f"Skipping duplicate or missing event: {event_id}")
4836
return
4937

5038
user_id = event.get("user", "unknown")
5139
logger.info(f"Processing @mention from user {user_id}", extra={"event_id": event_id})
5240

5341
trigger_async_processing({"event": event, "event_id": event_id, "bot_token": bot_token})
5442

55-
@app_instance.event("message")
43+
@app.event("message")
5644
def handle_direct_message(event, ack, body):
57-
"""Handle direct messages to the bot"""
45+
"""
46+
Handle direct messages to the bot
47+
"""
5848
ack()
5949

60-
if event.get("channel_type") == "im":
61-
event_id = body.get("event_id")
62-
if not event_id:
63-
logger.warning("Missing event_id in Slack event body.")
64-
elif is_duplicate_event(event_id):
65-
logger.info(f"Duplicate event detected, skipping: {event_id}")
66-
return
50+
# Only handle DMs, ignore channel messages
51+
if event.get("channel_type") != "im":
52+
return
6753

68-
user_id = event.get("user", "unknown")
69-
logger.info(f"Processing DM from user {user_id}", extra={"event_id": event_id})
54+
event_id = body.get("event_id")
55+
if not event_id or is_duplicate_event(event_id):
56+
logger.info(f"Skipping duplicate or missing event: {event_id}")
57+
return
7058

71-
trigger_async_processing({"event": event, "event_id": event_id, "bot_token": bot_token})
59+
user_id = event.get("user", "unknown")
60+
logger.info(f"Processing DM from user {user_id}", extra={"event_id": event_id})
61+
62+
trigger_async_processing({"event": event, "event_id": event_id, "bot_token": bot_token})
7263

7364

7465
def is_duplicate_event(event_id):
75-
"""Check if event has already been processed using conditional put"""
66+
"""
67+
Check if we've already processed this event
68+
"""
7669
from app.config.config import table
7770

7871
try:
7972
ttl = int(time.time()) + 3600 # 1 hour TTL
8073
table.put_item(
81-
Item={"eventId": event_id, "ttl": ttl, "timestamp": int(time.time())},
82-
ConditionExpression="attribute_not_exists(eventId)",
74+
Item={"pk": f"event#{event_id}", "sk": "dedup", "ttl": ttl, "timestamp": int(time.time())},
75+
ConditionExpression="attribute_not_exists(pk)",
8376
)
84-
return False # Item didn't exist, so not a duplicate
77+
return False # Not a duplicate
8578
except ClientError as e:
8679
if e.response["Error"]["Code"] == "ConditionalCheckFailedException":
87-
return True # Item already exists, so it's a duplicate
80+
return True # Duplicate
81+
logger.error(f"Error checking event duplication: {e}")
8882
return False
8983

9084

91-
# Create a module-level app instance that uses lazy loading
92-
class AppProxy:
93-
def __getattr__(self, name):
94-
return getattr(get_app(), name)
95-
85+
def trigger_async_processing(event_data):
86+
"""Fire off async processing to avoid timeout."""
87+
lambda_client = boto3.client("lambda")
9688

97-
app = AppProxy()
89+
lambda_client.invoke(
90+
FunctionName=os.environ["AWS_LAMBDA_FUNCTION_NAME"],
91+
InvocationType="Event",
92+
Payload=json.dumps({"async_processing": True, "slack_event": event_data}),
93+
)

0 commit comments

Comments
 (0)