feat: Add Playbook Manager, Saved Searches, and Timeline View components

- Implemented PlaybookManager for creating and managing investigation playbooks with templates.
- Added SavedSearches component for managing bookmarked queries and recurring scans.
- Introduced TimelineView for visualizing forensic event timelines with zoomable charts.
- Enhanced backend processing with auto-queued jobs for dataset uploads and improved database concurrency.
- Updated frontend components for better user experience and performance optimizations.
- Documented changes in update log for future reference.
This commit is contained in:
2026-02-23 14:23:07 -05:00
parent 37a9584d0c
commit 5a2ad8ec1c
110 changed files with 10537 additions and 1185 deletions

View File

@@ -21,9 +21,14 @@ _engine_kwargs: dict = dict(
)
if _is_sqlite:
_engine_kwargs["connect_args"] = {"timeout": 30}
_engine_kwargs["pool_size"] = 1
_engine_kwargs["max_overflow"] = 0
_engine_kwargs["connect_args"] = {"timeout": 60, "check_same_thread": False}
# NullPool: each session gets its own connection.
# Combined with WAL mode, this allows concurrent reads while a write is in progress.
from sqlalchemy.pool import NullPool
_engine_kwargs["poolclass"] = NullPool
else:
_engine_kwargs["pool_size"] = 5
_engine_kwargs["max_overflow"] = 10
engine = create_async_engine(settings.DATABASE_URL, **_engine_kwargs)
@@ -34,7 +39,7 @@ def _set_sqlite_pragmas(dbapi_conn, connection_record):
if _is_sqlite:
cursor = dbapi_conn.cursor()
cursor.execute("PRAGMA journal_mode=WAL")
cursor.execute("PRAGMA busy_timeout=5000")
cursor.execute("PRAGMA busy_timeout=30000")
cursor.execute("PRAGMA synchronous=NORMAL")
cursor.close()
@@ -46,6 +51,10 @@ async_session_factory = async_sessionmaker(
)
# Alias expected by other modules
async_session = async_session_factory
class Base(DeclarativeBase):
"""Base class for all ORM models."""
pass
@@ -71,5 +80,5 @@ async def init_db() -> None:
async def dispose_db() -> None:
"""Dispose of the engine connection pool."""
await engine.dispose()
"""Dispose of the engine on shutdown."""
await engine.dispose()