Skip to content

Conversation

@llama90
Copy link
Contributor

@llama90 llama90 commented Jan 13, 2026

No description provided.

@llama90 llama90 requested a review from Copilot January 13, 2026 02:50
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

#
# Quadrant-based workers:
# sr - Short-Read unified worker (handles /echo, /status, etc.)
# sr - Short-Read unified worker (handles /echo, /status-check, etc.)
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment incorrectly lists /status-check as an example command. Based on the command registry (src/shared/command-registry.ts) and SR worker implementation (src/workers/sr/index.ts), the actual command is /status, not /status-check.

Copilot uses AI. Check for mistakes.
Comment on lines +11 to +160
/**
* Log worker performance metrics for monitoring and analysis
*/
function logWorkerMetrics(params: {
correlationId?: string;
command?: string;
totalE2eMs?: number;
workerDurationMs: number;
queueWaitMs?: number;
syncResponseMs?: number;
asyncResponseMs?: number;
success: boolean;
errorType?: string;
errorMessage?: string;
}) {
logger.info('Performance metrics', {
...params,
component: 'sw-worker', // Add component identifier for filtering
});
}

/**
* Handler result with performance metrics
*/
interface HandlerResult {
syncResponseMs?: number;
asyncResponseMs?: number;
}

/**
* Command handler registry
* Maps command names to their handler functions
*/
const COMMAND_HANDLERS: Record<
string,
(message: WorkerMessage, messageId: string) => Promise<HandlerResult>
> = {
// Add new short-write commands here (no infrastructure changes needed!)
// '/scale': handleScale,
// '/restart': handleRestart,
};

/**
* Unified SW worker handler
* Routes commands to appropriate handlers based on command type
*/
export async function handler(event: SQSEvent): Promise<SQSBatchResponse> {
logger.info('SW unified worker invoked', {
recordCount: event.Records.length,
quadrant: 'short-write',
});

const batchItemFailures: { itemIdentifier: string }[] = [];

for (const record of event.Records) {
const startTime = Date.now();
let messageLogger = logger;
let correlationId: string | undefined;

try {
const message: WorkerMessage = JSON.parse(record.body);
correlationId = message.correlation_id;

// Create child logger with correlation ID for request tracing
messageLogger = logger.child(correlationId || record.messageId, {
component: 'sw-worker',
command: message.command,
userId: message.user_id,
quadrant: 'short-write',
});

messageLogger.info('Routing command to handler', {
command: message.command,
text: message.text,
user: message.user_name,
messageId: record.messageId,
});

// Find handler for command
const handler = COMMAND_HANDLERS[message.command];

if (!handler) {
const availableCommands = Object.keys(COMMAND_HANDLERS).join(', ');
const errorMsg = `Unknown command: ${message.command}. Available short-write commands: ${availableCommands || 'none'}`;

messageLogger.error(errorMsg, new Error('Unknown command'), {
command: message.command,
availableCommands,
});

throw new Error(errorMsg);
}

// Execute handler and get performance metrics
const handlerResult = await handler(message, record.messageId);

const totalDuration = Date.now() - startTime;
const e2eDuration = message.api_gateway_start_time
? Date.now() - message.api_gateway_start_time
: undefined;

// Log structured performance metrics for CloudWatch Insights analysis
logWorkerMetrics({
correlationId,
command: message.command,
totalE2eMs: e2eDuration,
workerDurationMs: totalDuration,
queueWaitMs: e2eDuration ? Math.max(0, e2eDuration - totalDuration) : undefined,
syncResponseMs: handlerResult.syncResponseMs,
asyncResponseMs: handlerResult.asyncResponseMs,
success: true,
});

messageLogger.info('Command processed successfully', {
command: message.command,
duration: totalDuration,
e2eDuration,
});

} catch (error) {
const duration = Date.now() - startTime;
const err = error as Error;

messageLogger.error('Failed to process command', err, {
messageId: record.messageId,
duration,
});

// Log performance metrics even for failures
logWorkerMetrics({
correlationId,
workerDurationMs: duration,
success: false,
errorType: err.name,
errorMessage: err.message,
});

// Add to failed items for retry
batchItemFailures.push({ itemIdentifier: record.messageId });
}
}

logger.info('SW worker batch complete', {
total: event.Records.length,
failed: batchItemFailures.length,
succeeded: event.Records.length - batchItemFailures.length,
});

return { batchItemFailures };
}
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The worker implementation contains significant code duplication with the SR worker implementation (lines 11-160 are nearly identical between SW, LR, and SR workers, with only component names differing). Consider extracting the common worker logic into a shared utility function that accepts configuration (component name, quadrant name) to improve maintainability. This would ensure that future changes to error handling, metrics logging, or batch processing logic only need to be made in one place.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot open a new pull request to apply changes based on this feedback

Comment on lines +11 to +160
/**
* Log worker performance metrics for monitoring and analysis
*/
function logWorkerMetrics(params: {
correlationId?: string;
command?: string;
totalE2eMs?: number;
workerDurationMs: number;
queueWaitMs?: number;
syncResponseMs?: number;
asyncResponseMs?: number;
success: boolean;
errorType?: string;
errorMessage?: string;
}) {
logger.info('Performance metrics', {
...params,
component: 'lr-worker', // Add component identifier for filtering
});
}

/**
* Handler result with performance metrics
*/
interface HandlerResult {
syncResponseMs?: number;
asyncResponseMs?: number;
}

/**
* Command handler registry
* Maps command names to their handler functions
*/
const COMMAND_HANDLERS: Record<
string,
(message: WorkerMessage, messageId: string) => Promise<HandlerResult>
> = {
// Add new long-read commands here (no infrastructure changes needed!)
// '/analyze': handleAnalyze,
// '/report': handleReport,
};

/**
* Unified LR worker handler
* Routes commands to appropriate handlers based on command type
*/
export async function handler(event: SQSEvent): Promise<SQSBatchResponse> {
logger.info('LR unified worker invoked', {
recordCount: event.Records.length,
quadrant: 'long-read',
});

const batchItemFailures: { itemIdentifier: string }[] = [];

for (const record of event.Records) {
const startTime = Date.now();
let messageLogger = logger;
let correlationId: string | undefined;

try {
const message: WorkerMessage = JSON.parse(record.body);
correlationId = message.correlation_id;

// Create child logger with correlation ID for request tracing
messageLogger = logger.child(correlationId || record.messageId, {
component: 'lr-worker',
command: message.command,
userId: message.user_id,
quadrant: 'long-read',
});

messageLogger.info('Routing command to handler', {
command: message.command,
text: message.text,
user: message.user_name,
messageId: record.messageId,
});

// Find handler for command
const handler = COMMAND_HANDLERS[message.command];

if (!handler) {
const availableCommands = Object.keys(COMMAND_HANDLERS).join(', ');
const errorMsg = `Unknown command: ${message.command}. Available long-read commands: ${availableCommands || 'none'}`;

messageLogger.error(errorMsg, new Error('Unknown command'), {
command: message.command,
availableCommands,
});

throw new Error(errorMsg);
}

// Execute handler and get performance metrics
const handlerResult = await handler(message, record.messageId);

const totalDuration = Date.now() - startTime;
const e2eDuration = message.api_gateway_start_time
? Date.now() - message.api_gateway_start_time
: undefined;

// Log structured performance metrics for CloudWatch Insights analysis
logWorkerMetrics({
correlationId,
command: message.command,
totalE2eMs: e2eDuration,
workerDurationMs: totalDuration,
queueWaitMs: e2eDuration ? Math.max(0, e2eDuration - totalDuration) : undefined,
syncResponseMs: handlerResult.syncResponseMs,
asyncResponseMs: handlerResult.asyncResponseMs,
success: true,
});

messageLogger.info('Command processed successfully', {
command: message.command,
duration: totalDuration,
e2eDuration,
});

} catch (error) {
const duration = Date.now() - startTime;
const err = error as Error;

messageLogger.error('Failed to process command', err, {
messageId: record.messageId,
duration,
});

// Log performance metrics even for failures
logWorkerMetrics({
correlationId,
workerDurationMs: duration,
success: false,
errorType: err.name,
errorMessage: err.message,
});

// Add to failed items for retry
batchItemFailures.push({ itemIdentifier: record.messageId });
}
}

logger.info('LR worker batch complete', {
total: event.Records.length,
failed: batchItemFailures.length,
succeeded: event.Records.length - batchItemFailures.length,
});

return { batchItemFailures };
}
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The worker implementation contains significant code duplication with the SR worker implementation (lines 11-160 are nearly identical between LR, SW, and SR workers, with only component names differing). Consider extracting the common worker logic into a shared utility function that accepts configuration (component name, quadrant name) to improve maintainability. This would ensure that future changes to error handling, metrics logging, or batch processing logic only need to be made in one place.

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Copilot AI commented Jan 13, 2026

@llama90 I've opened a new pull request, #23, to work on those changes. Once the pull request is ready, I'll request review from you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants