Skip to content

Commit 1e40f7b

Browse files
committed
fixes
1 parent f02b30e commit 1e40f7b

File tree

13 files changed

+74
-48
lines changed

13 files changed

+74
-48
lines changed

backend/app/api/routes/dlq.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from app.dlq import RetryPolicy
1111
from app.dlq.manager import DLQManager
1212
from app.dlq.models import DLQMessageStatus
13+
from app.domain.enums.events import EventType
1314
from app.schemas_pydantic.dlq import (
1415
DLQBatchRetryResponse,
1516
DLQMessageDetail,
@@ -50,7 +51,7 @@ async def get_dlq_messages(
5051
repository: FromDishka[DLQRepository],
5152
status: DLQMessageStatus | None = Query(None),
5253
topic: str | None = None,
53-
event_type: str | None = None,
54+
event_type: EventType | None = Query(None),
5455
limit: int = Query(50, ge=1, le=1000),
5556
offset: int = Query(0, ge=0),
5657
) -> DLQMessagesResponse:

backend/app/db/repositories/dlq_repository.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
TopicStatistic,
1919
)
2020
from app.dlq.manager import DLQManager
21+
from app.domain.enums.events import EventType
2122
from app.domain.events.event_models import CollectionNames
2223
from app.infrastructure.mappers.dlq_mapper import DLQMapper
2324

@@ -105,16 +106,14 @@ async def get_dlq_stats(self) -> DLQStatistics:
105106

106107
async def get_messages(
107108
self,
108-
status: str | None = None,
109+
status: DLQMessageStatus | None = None,
109110
topic: str | None = None,
110-
event_type: str | None = None,
111+
event_type: EventType | None = None,
111112
limit: int = 50,
112113
offset: int = 0,
113114
) -> DLQMessageListResult:
114115
# Create filter
115-
filter = DLQMessageFilter(
116-
status=DLQMessageStatus(status) if status else None, topic=topic, event_type=event_type
117-
)
116+
filter = DLQMessageFilter(status=status, topic=topic, event_type=event_type)
118117

119118
query = DLQMapper.filter_to_query(filter)
120119
total_count = await self.dlq_collection.count_documents(query)

backend/app/db/repositories/replay_repository.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from app.core.database_context import Collection, Database
66
from app.core.logging import logger
77
from app.domain.admin.replay_updates import ReplaySessionUpdate
8+
from app.domain.enums.replay import ReplayStatus
89
from app.domain.events.event_models import CollectionNames
910
from app.domain.replay import ReplayFilter, ReplaySessionState
1011
from app.infrastructure.mappers import ReplayStateMapper
@@ -42,13 +43,13 @@ async def get_session(self, session_id: str) -> ReplaySessionState | None:
4243
return self._mapper.from_mongo_document(data) if data else None
4344

4445
async def list_sessions(
45-
self, status: str | None = None, user_id: str | None = None, limit: int = 100, skip: int = 0
46+
self, status: ReplayStatus | None = None, user_id: str | None = None, limit: int = 100, skip: int = 0
4647
) -> list[ReplaySessionState]:
4748
collection = self.replay_collection
4849

49-
query = {}
50+
query: dict[str, object] = {}
5051
if status:
51-
query["status"] = status
52+
query["status"] = status.value
5253
if user_id:
5354
query["config.filter.user_id"] = user_id
5455

@@ -58,15 +59,20 @@ async def list_sessions(
5859
sessions.append(self._mapper.from_mongo_document(doc))
5960
return sessions
6061

61-
async def update_session_status(self, session_id: str, status: str) -> bool:
62+
async def update_session_status(self, session_id: str, status: ReplayStatus) -> bool:
6263
"""Update the status of a replay session"""
63-
result = await self.replay_collection.update_one({"session_id": session_id}, {"$set": {"status": status}})
64+
result = await self.replay_collection.update_one({"session_id": session_id}, {"$set": {"status": status.value}})
6465
return result.modified_count > 0
6566

6667
async def delete_old_sessions(self, cutoff_time: str) -> int:
6768
"""Delete old completed/failed/cancelled sessions"""
69+
terminal_statuses = [
70+
ReplayStatus.COMPLETED.value,
71+
ReplayStatus.FAILED.value,
72+
ReplayStatus.CANCELLED.value,
73+
]
6874
result = await self.replay_collection.delete_many(
69-
{"created_at": {"$lt": cutoff_time}, "status": {"$in": ["completed", "failed", "cancelled"]}}
75+
{"created_at": {"$lt": cutoff_time}, "status": {"$in": terminal_statuses}}
7076
)
7177
return result.deleted_count
7278

backend/app/db/repositories/saga_repository.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,10 @@ async def get_saga(self, saga_id: str) -> Saga | None:
4646
doc = await self.sagas.find_one({"saga_id": saga_id})
4747
return self.mapper.from_mongo(doc) if doc else None
4848

49-
async def get_sagas_by_execution(self, execution_id: str, state: str | None = None) -> list[Saga]:
49+
async def get_sagas_by_execution(self, execution_id: str, state: SagaState | None = None) -> list[Saga]:
5050
query: dict[str, object] = {"execution_id": execution_id}
5151
if state:
52-
query["state"] = state
52+
query["state"] = state.value
5353

5454
cursor = self.sagas.find(query).sort("created_at", DESCENDING)
5555
docs = await cursor.to_list(length=None)
@@ -69,8 +69,8 @@ async def list_sagas(self, filter: SagaFilter, limit: int = 100, skip: int = 0)
6969

7070
return SagaListResult(sagas=sagas, total=total, skip=skip, limit=limit)
7171

72-
async def update_saga_state(self, saga_id: str, state: str, error_message: str | None = None) -> bool:
73-
update_data = {"state": state, "updated_at": datetime.now(timezone.utc)}
72+
async def update_saga_state(self, saga_id: str, state: SagaState, error_message: str | None = None) -> bool:
73+
update_data: dict[str, object] = {"state": state.value, "updated_at": datetime.now(timezone.utc)}
7474

7575
if error_message:
7676
update_data["error_message"] = error_message

backend/app/dlq/models.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ class DLQMessageFilter:
115115

116116
status: DLQMessageStatus | None = None
117117
topic: str | None = None
118-
event_type: str | None = None
118+
event_type: EventType | None = None
119119

120120

121121
@dataclass

backend/tests/unit/db/repositories/test_replay_repository.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ async def test_indexes_and_session_crud(repo: ReplayRepository) -> None:
2626
assert got and got.session_id == "s1"
2727
lst = await repo.list_sessions(limit=5)
2828
assert any(s.session_id == "s1" for s in lst)
29-
assert await repo.update_session_status("s1", "running") is True
29+
assert await repo.update_session_status("s1", ReplayStatus.RUNNING) is True
3030
session_update = ReplaySessionUpdate(status=ReplayStatus.COMPLETED)
3131
assert await repo.update_replay_session("s1", session_update) is True
3232

backend/tests/unit/db/repositories/test_saga_repository.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import pytest
44

55
from app.db.repositories.saga_repository import SagaRepository
6+
from app.domain.enums.saga import SagaState
67
from app.domain.saga.models import Saga, SagaFilter, SagaListResult
78

89
pytestmark = pytest.mark.unit
@@ -30,7 +31,7 @@ async def test_saga_crud_and_queries(repo: SagaRepository, db) -> None: # type:
3031
result = await repo.list_sagas(f, limit=2)
3132
assert isinstance(result, SagaListResult)
3233

33-
assert await repo.update_saga_state("s1", "completed") in (True, False)
34+
assert await repo.update_saga_state("s1", SagaState.COMPLETED) in (True, False)
3435

3536
# user execution ids
3637
await db.get_collection("executions").insert_many([

frontend/src/components/admin/sagas/SagaFilters.svelte

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
<script lang="ts">
22
import { X } from '@lucide/svelte';
3-
import { SAGA_STATES } from '$lib/admin/sagas';
3+
import { SAGA_STATES, type SagaStateFilter } from '$lib/admin/sagas';
44
55
interface Props {
66
searchQuery: string;
7-
stateFilter: string;
7+
stateFilter: SagaStateFilter;
88
executionIdFilter: string;
99
onSearch: () => void;
1010
onClear: () => void;
1111
}
1212
1313
let {
1414
searchQuery = $bindable(''),
15-
stateFilter = $bindable(''),
15+
stateFilter = $bindable<SagaStateFilter>(''),
1616
executionIdFilter = $bindable(''),
1717
onSearch,
1818
onClear

frontend/src/components/admin/users/UserFilters.svelte

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
11
<script lang="ts">
22
import { ChevronDown } from '@lucide/svelte';
3+
import type { UserRole } from '$lib/api';
4+
5+
// Filter types - 'all' means no filter applied
6+
type RoleFilter = 'all' | UserRole;
7+
type StatusFilter = 'all' | 'active' | 'disabled';
8+
type BooleanFilter = 'all' | 'yes' | 'no';
9+
type MultiplierFilter = 'all' | 'custom' | 'default';
310
411
interface AdvancedFilters {
5-
bypassRateLimit: string;
6-
hasCustomLimits: string;
7-
globalMultiplier: string;
12+
bypassRateLimit: BooleanFilter;
13+
hasCustomLimits: BooleanFilter;
14+
globalMultiplier: MultiplierFilter;
815
}
916
1017
interface Props {
1118
searchQuery: string;
12-
roleFilter: string;
13-
statusFilter: string;
19+
roleFilter: RoleFilter;
20+
statusFilter: StatusFilter;
1421
advancedFilters: AdvancedFilters;
1522
showAdvancedFilters: boolean;
1623
hasFiltersActive: boolean;
@@ -19,9 +26,9 @@
1926
2027
let {
2128
searchQuery = $bindable(''),
22-
roleFilter = $bindable('all'),
23-
statusFilter = $bindable('all'),
24-
advancedFilters = $bindable({ bypassRateLimit: 'all', hasCustomLimits: 'all', globalMultiplier: 'all' }),
29+
roleFilter = $bindable<RoleFilter>('all'),
30+
statusFilter = $bindable<StatusFilter>('all'),
31+
advancedFilters = $bindable<AdvancedFilters>({ bypassRateLimit: 'all', hasCustomLimits: 'all', globalMultiplier: 'all' }),
2532
showAdvancedFilters = $bindable(false),
2633
hasFiltersActive,
2734
onReset
@@ -50,6 +57,7 @@
5057
<select id="role-filter" bind:value={roleFilter} class="form-select-standard w-full">
5158
<option value="all">All Roles</option>
5259
<option value="user">User</option>
60+
<option value="moderator">Moderator</option>
5361
<option value="admin">Admin</option>
5462
</select>
5563
</div>

frontend/src/lib/admin/events/eventTypes.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export const EVENT_TYPES: EventType[] = [
2121
];
2222

2323
// Event type color mapping
24-
export function getEventTypeColor(eventType: string): string {
24+
export function getEventTypeColor(eventType: EventType): string {
2525
if (eventType.includes('_completed') || eventType.includes('_succeeded')) {
2626
return 'text-green-600 dark:text-green-400';
2727
}
@@ -44,7 +44,7 @@ export function getEventTypeColor(eventType: string): string {
4444
}
4545

4646
// Get display label for event type
47-
export function getEventTypeLabel(eventType: string): string {
47+
export function getEventTypeLabel(eventType: EventType): string {
4848
// For execution_requested, show icon only (with tooltip)
4949
if (eventType === 'execution_requested') {
5050
return '';

0 commit comments

Comments
 (0)