Skip to content

Commit 4973dfe

Browse files
committed
fixes
1 parent 48c8d5c commit 4973dfe

File tree

4 files changed

+102
-83
lines changed

4 files changed

+102
-83
lines changed

backend/app/services/sse/redis_bus.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import redis.asyncio as redis
66
from pydantic import BaseModel
77

8+
from app.core.logging import logger
89
from app.infrastructure.kafka.events.base import BaseEvent
910
from app.schemas_pydantic.sse import RedisNotificationMessage, RedisSSEMessage
1011

@@ -25,7 +26,11 @@ async def get(self, model: Type[T]) -> T | None:
2526
return None
2627
try:
2728
return model.model_validate_json(msg["data"])
28-
except Exception:
29+
except Exception as e:
30+
logger.warning(
31+
f"Failed to parse Redis message on channel {self._channel}: {e}",
32+
extra={"channel": self._channel, "model": model.__name__},
33+
)
2934
return None
3035

3136
async def close(self) -> None:

backend/app/services/sse/sse_service.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,11 @@ async def _stream_events_redis(
151151
if msg.event_type in self.TERMINAL_EVENT_TYPES:
152152
logger.info(f"Terminal event for execution {execution_id}: {msg.event_type}")
153153
break
154-
except Exception:
155-
# Ignore malformed messages
154+
except Exception as e:
155+
logger.warning(
156+
f"Failed to process SSE message for execution {execution_id}: {e}",
157+
extra={"execution_id": execution_id, "event_type": str(msg.event_type)},
158+
)
156159
continue
157160

158161
async def _build_sse_event_from_redis(self, execution_id: str, msg: RedisSSEMessage) -> SSEExecutionEventData:

frontend/src/routes/admin/__tests__/AdminEvents.test.ts

Lines changed: 9 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -2,86 +2,15 @@ import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest';
22
import { render, screen, waitFor, cleanup } from '@testing-library/svelte';
33
import userEvent from '@testing-library/user-event';
44
import { tick } from 'svelte';
5-
import { mockElementAnimate, mockWindowGlobals } from '$routes/admin/__tests__/test-utils';
6-
7-
interface MockEventOverrides {
8-
event_id?: string;
9-
event_type?: string;
10-
timestamp?: string;
11-
correlation_id?: string;
12-
aggregate_id?: string;
13-
metadata?: Record<string, unknown>;
14-
payload?: Record<string, unknown>;
15-
}
16-
17-
const DEFAULT_EVENT = {
18-
event_id: 'evt-1',
19-
event_type: 'execution_completed',
20-
timestamp: '2024-01-15T10:30:00Z',
21-
correlation_id: 'corr-123',
22-
aggregate_id: 'exec-456',
23-
metadata: { user_id: 'user-1', service_name: 'test-service' },
24-
payload: { output: 'hello', exit_code: 0 },
25-
};
26-
27-
const EVENT_TYPES = [
28-
'execution_requested', 'execution_started', 'execution_completed',
29-
'execution_failed', 'pod_created', 'pod_running'
30-
];
31-
32-
const createMockEvent = (overrides: MockEventOverrides = {}) => ({ ...DEFAULT_EVENT, ...overrides });
33-
34-
const createMockEvents = (count: number) =>
35-
Array.from({ length: count }, (_, i) => createMockEvent({
36-
event_id: `evt-${i + 1}`,
37-
event_type: EVENT_TYPES[i % EVENT_TYPES.length],
38-
timestamp: new Date(Date.now() - i * 60000).toISOString(),
39-
correlation_id: `corr-${i + 1}`,
40-
aggregate_id: `exec-${i + 1}`,
41-
metadata: { user_id: `user-${(i % 3) + 1}`, service_name: 'execution-service' },
42-
}));
43-
44-
function createMockStats(overrides: Partial<{
45-
total_events: number;
46-
error_rate: number;
47-
avg_processing_time: number;
48-
top_users: Array<{ user_id: string; count: number }>;
49-
}> = {}) {
50-
return {
51-
total_events: 150,
52-
error_rate: 2.5,
53-
avg_processing_time: 1.23,
54-
top_users: [{ user_id: 'user-1', count: 50 }],
55-
...overrides,
56-
};
57-
}
58-
59-
function createMockEventDetail(event = createMockEvent()) {
60-
return {
61-
event,
62-
related_events: [
63-
{ event_id: 'rel-1', event_type: 'execution_started', timestamp: '2024-01-15T10:29:00Z' },
64-
{ event_id: 'rel-2', event_type: 'pod_created', timestamp: '2024-01-15T10:29:30Z' },
65-
],
66-
};
67-
}
68-
69-
function createMockUserOverview() {
70-
return {
71-
user: {
72-
user_id: 'user-1',
73-
username: 'testuser',
74-
75-
role: 'user',
76-
is_active: true,
77-
is_superuser: false,
78-
},
79-
stats: { total_events: 100 },
80-
derived_counts: { succeeded: 80, failed: 10, timeout: 5, cancelled: 5, terminal_total: 100 },
81-
rate_limit_summary: { bypass_rate_limit: false, global_multiplier: 1.0, has_custom_limits: false },
82-
recent_events: [createMockEvent()],
83-
};
84-
}
5+
import {
6+
mockElementAnimate,
7+
mockWindowGlobals,
8+
createMockEvent,
9+
createMockEvents,
10+
createMockStats,
11+
createMockEventDetail,
12+
createMockUserOverview,
13+
} from '$routes/admin/__tests__/test-utils';
8514

8615
// Hoisted mocks
8716
const mocks = vi.hoisted(() => ({

frontend/src/routes/admin/__tests__/test-utils.ts

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { vi, type Mock } from 'vitest';
2+
import { EVENT_TYPES } from '$lib/admin/events/eventTypes';
23

34
const animateMock = {
45
onfinish: null,
@@ -42,3 +43,84 @@ export function mockWindowGlobals(openMock: Mock, confirmMock: Mock): void {
4243
vi.stubGlobal('open', openMock);
4344
vi.stubGlobal('confirm', confirmMock);
4445
}
46+
47+
// ============================================================================
48+
// Event Mock Helpers
49+
// ============================================================================
50+
51+
export interface MockEventOverrides {
52+
event_id?: string;
53+
event_type?: string;
54+
timestamp?: string;
55+
correlation_id?: string;
56+
aggregate_id?: string;
57+
metadata?: Record<string, unknown>;
58+
payload?: Record<string, unknown>;
59+
}
60+
61+
export const DEFAULT_EVENT = {
62+
event_id: 'evt-1',
63+
event_type: 'execution_completed',
64+
timestamp: '2024-01-15T10:30:00Z',
65+
correlation_id: 'corr-123',
66+
aggregate_id: 'exec-456',
67+
metadata: { user_id: 'user-1', service_name: 'test-service' },
68+
payload: { output: 'hello', exit_code: 0 },
69+
};
70+
71+
/** Re-export EVENT_TYPES from the source for test consistency */
72+
export { EVENT_TYPES } from '$lib/admin/events/eventTypes';
73+
74+
export const createMockEvent = (overrides: MockEventOverrides = {}) => ({ ...DEFAULT_EVENT, ...overrides });
75+
76+
export const createMockEvents = (count: number) =>
77+
Array.from({ length: count }, (_, i) => createMockEvent({
78+
event_id: `evt-${i + 1}`,
79+
event_type: EVENT_TYPES[i % EVENT_TYPES.length],
80+
timestamp: new Date(Date.now() - i * 60000).toISOString(),
81+
correlation_id: `corr-${i + 1}`,
82+
aggregate_id: `exec-${i + 1}`,
83+
metadata: { user_id: `user-${(i % 3) + 1}`, service_name: 'execution-service' },
84+
}));
85+
86+
export function createMockStats(overrides: Partial<{
87+
total_events: number;
88+
error_rate: number;
89+
avg_processing_time: number;
90+
top_users: Array<{ user_id: string; count: number }>;
91+
}> = {}) {
92+
return {
93+
total_events: 150,
94+
error_rate: 2.5,
95+
avg_processing_time: 1.23,
96+
top_users: [{ user_id: 'user-1', count: 50 }],
97+
...overrides,
98+
};
99+
}
100+
101+
export function createMockEventDetail(event = createMockEvent()) {
102+
return {
103+
event,
104+
related_events: [
105+
{ event_id: 'rel-1', event_type: 'execution_started', timestamp: '2024-01-15T10:29:00Z' },
106+
{ event_id: 'rel-2', event_type: 'pod_created', timestamp: '2024-01-15T10:29:30Z' },
107+
],
108+
};
109+
}
110+
111+
export function createMockUserOverview() {
112+
return {
113+
user: {
114+
user_id: 'user-1',
115+
username: 'testuser',
116+
117+
role: 'user',
118+
is_active: true,
119+
is_superuser: false,
120+
},
121+
stats: { total_events: 100 },
122+
derived_counts: { succeeded: 80, failed: 10, timeout: 5, cancelled: 5, terminal_total: 100 },
123+
rate_limit_summary: { bypass_rate_limit: false, global_multiplier: 1, has_custom_limits: false },
124+
recent_events: [createMockEvent()],
125+
};
126+
}

0 commit comments

Comments
 (0)