Skip to content

Conversation

@mikejgray
Copy link
Contributor

@mikejgray mikejgray commented Oct 5, 2025

Closes #80

Summary by CodeRabbit

  • New Features

    • Added the ability to query and receive a snapshot list of current scheduled events via the message bus.
  • Bug Fixes

    • Improved scheduler shutdown cleanup by removing the event-list listener and reordering listener removals for more reliable shutdown.
  • Tests

    • Added tests validating scheduled-events listing behavior.
    • Standardized test string quoting and formatting for consistency.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 5, 2025

Walkthrough

Adds an EventScheduler message-bus handler list_events_handler exposed on mycroft.scheduler.list_events, registers its listener at init, removes it during shutdown (adjusting listener removal order including system.clock.synced), and adds a unit test verifying the handler; tests also standardize quoting and minor formatting.

Changes

Cohort / File(s) Summary
Scheduler feature: list events handler
ovos_bus_client/util/scheduler.py
Adds list_events_handler(self, message: Message) that replies with {"scheduled_events": self.events}; registers listener on mycroft.scheduler.list_events during init; removes that listener during shutdown and adjusts listener removal order (includes system.clock.synced); minor formatting tweak.
Unit tests: coverage and consistency
test/unittests/test_event_scheduler.py
Adds test_list_events_handler to validate the reply contains all scheduled events; standardizes double-quoted strings and minor formatting/spacing adjustments across tests.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant C as Client
  participant B as MessageBus
  participant ES as EventScheduler

  C->>B: emit "mycroft.scheduler.list_events"
  B->>ES: deliver Message
  ES->>B: reply {"scheduled_events": events}
  B-->>C: deliver reply

  rect rgb(245,245,255)
    note right of ES: Shutdown sequence (listener cleanup)
    ES->>B: remove listener "mycroft.scheduler.list_events"
    ES->>B: remove other listeners (including "system.clock.synced")
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

I twitch my ears and count each tick,
I list the slots both small and quick;
A busbell rings, I send it back,
Carrots queued along the track.
I hop away — listeners unpicked. 🥕

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The PR title "feat(EventScheduler): list_events API" is concise, specific, and directly summarizes the primary change introduced in this pull request. The raw_summary confirms that the PR adds a new list_events_handler method to the EventScheduler class that returns a snapshot of scheduled events, which matches the title's promise. The title avoids vague language and clearly communicates the main feature being added.
Linked Issues Check ✅ Passed The PR implements the list_events functionality explicitly mentioned in issue #80, which specifically states that "EventScheduler does not have capabilities to list existing events" and requests the ability to discover entries without knowing names in advance. The code changes add the list_events_handler method to provide this functionality as requested. However, issue #80 is titled "EventScheduler full CRUD" and mentions that it "should ideally have full CRUD options," which would include create, update, and delete operations in addition to the list functionality being implemented here. This PR appears to address the primary pain point of listing events but may not fully satisfy the broader CRUD scope mentioned in the issue title.
Out of Scope Changes Check ✅ Passed The changes in this PR consist of adding the list_events_handler method, wiring it to the message bus via mycroft.scheduler.list_events, updating the shutdown sequence to properly clean up the listener, adding corresponding test coverage, and minor code quality improvements (consistent string quoting in tests). All of these changes are directly related to implementing the list_events API feature as scoped by issue #80. No extraneous modifications to unrelated functionality or files were introduced.
Docstring Coverage ✅ Passed Docstring coverage is 80.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 769f78c and 5a495bd.

📒 Files selected for processing (1)
  • ovos_bus_client/util/scheduler.py (4 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
ovos_bus_client/util/scheduler.py (2)
ovos_bus_client/client/client.py (4)
  • on (298-305)
  • emit (164-195)
  • emit (388-412)
  • remove_all_listeners (345-354)
ovos_bus_client/message.py (2)
  • Message (32-238)
  • response (201-214)
🔇 Additional comments (3)
ovos_bus_client/util/scheduler.py (3)

98-98: LGTM! Handler registration follows established patterns.

The registration of list_events_handler is consistent with the other scheduler message handlers and uses the appropriate event naming convention.


311-318: LGTM! Critical syntax error from previous review has been fixed.

The implementation correctly:

  • Uses the event lock to safely snapshot the scheduled events
  • Leverages message.response() to maintain context and auto-append ".response" suffix
  • Follows the same thread-safety pattern as get_event_handler

The closing parenthesis issue flagged in the previous review is now resolved.


365-370: LGTM! Listener cleanup is complete and well-organized.

All message bus listeners registered during initialization (including the new list_events handler) are properly removed during shutdown. The alphabetical ordering improves maintainability.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov-commenter
Copy link

codecov-commenter commented Oct 5, 2025

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 39.83%. Comparing base (9aebc61) to head (391a825).
⚠️ Report is 116 commits behind head on dev.
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@            Coverage Diff             @@
##              dev     #172      +/-   ##
==========================================
- Coverage   42.27%   39.83%   -2.44%     
==========================================
  Files          16       18       +2     
  Lines        2188     2337     +149     
==========================================
+ Hits          925      931       +6     
- Misses       1263     1406     +143     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions github-actions bot added feature and removed feature labels Oct 5, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dd73736 and 0258d56.

📒 Files selected for processing (2)
  • ovos_bus_client/util/scheduler.py (4 hunks)
  • test/unittests/test_event_scheduler.py (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
ovos_bus_client/util/scheduler.py (2)
ovos_bus_client/client/client.py (2)
  • on (298-305)
  • remove_all_listeners (345-354)
ovos_bus_client/message.py (2)
  • Message (32-238)
  • reply (166-199)
test/unittests/test_event_scheduler.py (2)
ovos_bus_client/util/scheduler.py (1)
  • list_events_handler (311-315)
ovos_bus_client/message.py (1)
  • reply (166-199)
🪛 Ruff (0.13.3)
test/unittests/test_event_scheduler.py

24-24: Unused method argument: mock_thread

(ARG002)


39-39: Unused method argument: mock_json_dump

(ARG002)


39-39: Unused method argument: mock_thread

(ARG002)


67-67: Unused method argument: mock_thread

(ARG002)


90-90: Unused method argument: mock_dump

(ARG002)


90-90: Unused method argument: mock_thread

(ARG002)


111-111: Unused method argument: mock_dump

(ARG002)


111-111: Unused method argument: mock_thread

(ARG002)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: license_tests
🔇 Additional comments (5)
ovos_bus_client/util/scheduler.py (3)

72-72: LGTM!

The formatting adjustment improves code readability.


98-98: LGTM!

The new handler is correctly registered with the messagebus.


364-364: LGTM!

The cleanup correctly removes the new listener during shutdown.

test/unittests/test_event_scheduler.py (2)

2-7: LGTM!

String literal standardization improves code consistency.


20-106: LGTM!

The standardization of string literals to double quotes improves consistency across the test suite.

mikejgray and others added 2 commits October 5, 2025 15:31
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@github-actions github-actions bot added feature and removed feature labels Oct 21, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0258d56 and 769f78c.

📒 Files selected for processing (2)
  • ovos_bus_client/util/scheduler.py (4 hunks)
  • test/unittests/test_event_scheduler.py (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
test/unittests/test_event_scheduler.py (2)
ovos_bus_client/util/scheduler.py (1)
  • list_events_handler (311-329)
ovos_bus_client/message.py (1)
  • reply (166-199)
ovos_bus_client/util/scheduler.py (2)
ovos_bus_client/client/client.py (4)
  • on (298-305)
  • emit (164-195)
  • emit (388-412)
  • remove_all_listeners (345-354)
ovos_bus_client/message.py (2)
  • Message (32-238)
  • response (201-214)
🪛 Ruff (0.14.1)
test/unittests/test_event_scheduler.py

24-24: Unused method argument: mock_thread

(ARG002)


39-39: Unused method argument: mock_json_dump

(ARG002)


39-39: Unused method argument: mock_thread

(ARG002)


67-67: Unused method argument: mock_thread

(ARG002)


90-90: Unused method argument: mock_dump

(ARG002)


90-90: Unused method argument: mock_thread

(ARG002)


111-111: Unused method argument: mock_dump

(ARG002)


111-111: Unused method argument: mock_thread

(ARG002)

ovos_bus_client/util/scheduler.py

317-318: Expected ')', found newline

(invalid-syntax)

Comment on lines +111 to +145
def test_list_events_handler(self, mock_open, mock_dump, mock_load, mock_thread):
"""
Test list_events_handler returns all scheduled events.
"""
mock_load.return_value = ""
mock_open.return_value = MagicMock()
emitter = MagicMock()
es = EventScheduler(emitter)

# Schedule a couple of events
es.schedule_event("test-event-1", 900000000000, None, {"data": "test1"})
es.schedule_event("test-event-2", 910000000000, 60, {"data": "test2"})

# Create a mock message
mock_message = MagicMock()
mock_message.context = {"source": "test"}

# Call the handler
es.list_events_handler(mock_message)

# Verify message.reply was called with correct msg_type and data
mock_message.reply.assert_called_once()
call_args = mock_message.reply.call_args
self.assertEqual(call_args[0][0], "mycroft.scheduler.list_events.response")
self.assertIn("scheduled_events", call_args[1]["data"])

# Verify emitter.emit was called with the reply message
emitter.emit.assert_called()

# Verify the scheduled events contain our test events
scheduled_events = call_args[1]["data"]["scheduled_events"]
self.assertIn("test-event-1", scheduled_events)
self.assertIn("test-event-2", scheduled_events)

es.shutdown()
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Test verifies wrong method call.

The production code calls message.response() (line 317 in scheduler.py), but the test verifies mock_message.reply() was called (line 132). These are different methods on the MagicMock object.

When using MagicMock(), calling message.response() in production invokes the mock's response attribute, not reply. The test should verify response was called.

Apply this diff to fix the test:

     # Call the handler
     es.list_events_handler(mock_message)
 
-    # Verify message.reply was called with correct msg_type and data
-    mock_message.reply.assert_called_once()
-    call_args = mock_message.reply.call_args
-    self.assertEqual(call_args[0][0], "mycroft.scheduler.list_events.response")
-    self.assertIn("scheduled_events", call_args[1]["data"])
+    # Verify message.response was called with correct data
+    mock_message.response.assert_called_once()
+    call_args = mock_message.response.call_args
+    self.assertIn("scheduled_events", call_args[1]["data"])
 
     # Verify emitter.emit was called with the reply message
     emitter.emit.assert_called()
     
     # Verify the scheduled events contain our test events
-    scheduled_events = call_args[1]["data"]["scheduled_events"]
+    call_args = mock_message.response.call_args
+    scheduled_events = call_args[1]["data"]["scheduled_events"]
     self.assertIn("test-event-1", scheduled_events)
     self.assertIn("test-event-2", scheduled_events)
🧰 Tools
🪛 Ruff (0.14.1)

111-111: Unused method argument: mock_dump

(ARG002)


111-111: Unused method argument: mock_thread

(ARG002)

🤖 Prompt for AI Agents
In test/unittests/test_event_scheduler.py around lines 111 to 145, the test
asserts on mock_message.reply but production code calls message.response();
update the test to assert and inspect mock_message.response instead of
mock_message.reply (replace mock_message.reply.assert_called_once(),
mock_message.reply.call_args usage, and subsequent call_args checks to use
mock_message.response) so the test verifies the actual method invoked by the
scheduler.

@mikejgray mikejgray force-pushed the FEAT_EventSchedulerList branch from 769f78c to 5a495bd Compare October 21, 2025 03:40
@github-actions github-actions bot added feature and removed feature labels Oct 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

EventScheduler full CRUD

3 participants