Skip to content

Event log#95

Merged
michael-pisman merged 23 commits intomainfrom
even_log
Jul 30, 2025
Merged

Event log#95
michael-pisman merged 23 commits intomainfrom
even_log

Conversation

@michael-pisman
Copy link
Member

@michael-pisman michael-pisman commented Jul 30, 2025

This pull request introduces significant new features and enhancements to the unipoll_api project, including WebSocket and event streaming functionality, Redis integration for notifications, and improved workspace and group management. Key updates include the addition of new WebSocket actions, Redis-based push notifications, event logging for resources, and new endpoints for event streams.

New Features and Integrations:

  • WebSocket Actions:

    • Added websocket.py with WebSocket-related actions for managing workspaces and groups, including CRUD operations for resources, members, and policies. (src/unipoll_api/actions/websocket.py)
    • Imported WebsocketActions into __init__.py to expose WebSocket functionality. (src/unipoll_api/actions/__init__.py)
  • Redis Integration:

    • Introduced Redis for push notifications with methods to publish messages and listen to channels. (src/unipoll_api/redis.py)
    • Added Redis configuration fields (redis_host, redis_port) to application settings. (src/unipoll_api/config.py)
  • Event Logging and Streaming:

    • Added an Event document for time-series event logging. (src/unipoll_api/documents.py)
    • Implemented event logging in workspace updates, including notifications for members. (src/unipoll_api/actions/workspace.py)
    • Created new endpoints for subscribing to resource events and pushing notifications. (src/unipoll_api/routes/streams.py)

Enhancements to Existing Components:

  • Workspace and Group Management:

    • Enhanced workspace-related actions to include event logging and notifications. (src/unipoll_api/actions/workspace.py)
    • Updated dependencies to support WebSocket authentication and token validation. (src/unipoll_api/dependencies.py)
  • Error Handling:

    • Added WebSocket-specific exceptions for better error reporting. (src/unipoll_api/exceptions/websocket.py)

Configuration and Dependencies:

  • Dependencies:
    • Added sse-starlette for server-sent events. (pyproject.toml)
  • Startup Improvements:
    • Introduced application start time for tracking resource updates. (src/unipoll_api/app.py)

These changes collectively enhance the API's real-time capabilities and improve resource management while introducing robust event logging and notification systems.

Event document represents time series for storing various events
Added list of linked events to Resource model and created log_event() method to record new events into the database
Created to functions to publish and listen to the messages from redis
Changed get_updates function to use ResourceID instead of Resource object, removed event_generator
operation_id is not set inside router module
There is no point in storing events inside of the Resource
Copilot AI review requested due to automatic review settings July 30, 2025 06:52
@michael-pisman michael-pisman merged commit 376f06d into main Jul 30, 2025
1 check failed
@michael-pisman michael-pisman deleted the even_log branch July 30, 2025 06:55
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

This PR implements an event logging system with real-time notifications for workspace operations. The changes introduce WebSocket connections for real-time communication, MongoDB time-series collections for event storage, and Redis pub/sub for push notifications.

Key changes:

  • Added WebSocket support with action parsing and real-time messaging capabilities
  • Implemented event logging system using MongoDB time-series collections
  • Added Redis integration for real-time push notifications and Server-Sent Events (SSE)

Reviewed Changes

Copilot reviewed 18 out of 19 changed files in this pull request and generated 13 comments.

Show a summary per file
File Description
src/unipoll_api/websocket_manager.py Enhanced WebSocket manager with JSON messaging and action parsing functionality
src/unipoll_api/utils/events.py New event utilities for getting updates, streaming events, and notifying members
src/unipoll_api/schemas/websocket.py New WebSocket message schema for action-based communication
src/unipoll_api/routes/websocket.py Updated WebSocket route with authentication and message parsing
src/unipoll_api/routes/streams.py New streaming endpoints for event logs and Redis notifications
src/unipoll_api/routes/init.py Added streams router to main application
src/unipoll_api/redis.py New Redis client for pub/sub messaging
src/unipoll_api/mongo_db.py Added Event document to database initialization
src/unipoll_api/exceptions/websocket.py New WebSocket-specific exception classes
src/unipoll_api/exceptions/init.py Exported WebSocket exceptions
src/unipoll_api/documents.py Added Event document with time-series configuration
src/unipoll_api/dependencies.py Updated WebSocket authentication dependency
src/unipoll_api/config.py Added Redis configuration settings
src/unipoll_api/app.py Added application start time tracking
src/unipoll_api/actions/workspace.py Added event logging to workspace updates
src/unipoll_api/actions/websocket.py New WebSocket action handlers for various operations
src/unipoll_api/actions/init.py Exported WebSocket actions
pyproject.toml Added sse-starlette dependency
Comments suppressed due to low confidence (1)

filtered_args = {}
for key, required in args.items():
value = data.get(key)
if required and not value:
Copy link

Copilot AI Jul 30, 2025

Choose a reason for hiding this comment

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

This condition will incorrectly reject valid falsy values like 0, False, or empty strings that might be legitimate arguments. Consider using value is None instead.

Suggested change
if required and not value:
if required and value is None:

Copilot uses AI. Check for mistakes.
response: BaseModel = await action(**args)
if not response:
response = {"status": "success"}
return response.model_dump(exclude_none=True)
Copy link

Copilot AI Jul 30, 2025

Choose a reason for hiding this comment

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

When response is a dictionary (line 55), calling .model_dump() will fail since dictionaries don't have this method. The function should handle both BaseModel instances and dictionaries consistently.

Suggested change
return response.model_dump(exclude_none=True)
if isinstance(response, BaseModel):
return response.model_dump(exclude_none=True)
return response

Copilot uses AI. Check for mistakes.
try:
timestamp = datetime.now()
for member in resource.members:
# print(member)
Copy link

Copilot AI Jul 30, 2025

Choose a reason for hiding this comment

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

Commented-out debug print statement should be removed from production code.

Suggested change
# print(member)

Copilot uses AI. Check for mistakes.
time = datetime.fromisoformat(since)
return await get_updates(resource_id, time)
except Exception as e:
print(e)
Copy link

Copilot AI Jul 30, 2025

Choose a reason for hiding this comment

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

Using print() for error handling is not appropriate for production code. Consider using proper logging or raising appropriate exceptions.

Copilot uses AI. Check for mistakes.
Comment on lines +44 to +46
print(e)


Copy link

Copilot AI Jul 30, 2025

Choose a reason for hiding this comment

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

Using print() for error handling is not appropriate for production code. Consider using proper logging or raising appropriate exceptions.

Suggested change
print(e)
logger.error(f"Error in generate_event: {e}")
raise HTTPException(status_code=500, detail="Internal Server Error")

Copilot uses AI. Check for mistakes.
Comment on lines +26 to +28
print("Connection error:", e)
except Exception as e:
print("An unexpected error occurred:", e)
Copy link

Copilot AI Jul 30, 2025

Choose a reason for hiding this comment

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

Using print() for error handling is not appropriate for production code. Consider using proper logging.

Suggested change
print("Connection error:", e)
except Exception as e:
print("An unexpected error occurred:", e)
logger.error("Connection error: %s", e)
except Exception as e:
logger.error("An unexpected error occurred: %s", e)

Copilot uses AI. Check for mistakes.
Comment on lines +26 to +28
print("Connection error:", e)
except Exception as e:
print("An unexpected error occurred:", e)
Copy link

Copilot AI Jul 30, 2025

Choose a reason for hiding this comment

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

Using print() for error handling is not appropriate for production code. Consider using proper logging.

Suggested change
print("Connection error:", e)
except Exception as e:
print("An unexpected error occurred:", e)
logger.error("Connection error: %s", e)
except Exception as e:
logger.error("An unexpected error occurred: %s", e)

Copilot uses AI. Check for mistakes.
if user_id == message.get("recipient_id"):
yield {"data": json.dumps(message)}
except redis.exceptions.ConnectionError as e:
print("Connection error:", e)
Copy link

Copilot AI Jul 30, 2025

Choose a reason for hiding this comment

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

Using print() for error handling is not appropriate for production code. Consider using proper logging.

Suggested change
print("Connection error:", e)
logger.error("Connection error: %s", e)

Copilot uses AI. Check for mistakes.
Comment on lines +235 to +236
# @after_event(Insert)
# def
Copy link

Copilot AI Jul 30, 2025

Choose a reason for hiding this comment

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

Incomplete commented code should be removed or properly implemented.

Suggested change
# @after_event(Insert)
# def
@after_event(Insert)
async def after_insert(self):
Debug(f"Event inserted with ID: {self.id}")

Copilot uses AI. Check for mistakes.
"message": message}
await publish_message(data)
except Exception as e:
print(e)
Copy link

Copilot AI Jul 30, 2025

Choose a reason for hiding this comment

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

Using print() for error handling is not appropriate for production code. Consider using proper logging or raising appropriate exceptions.

Suggested change
print(e)
Debug.error(f"An error occurred in notify_members: {e}")
raise

Copilot uses AI. Check for mistakes.
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.

1 participant