Skip to content

Conversation

@NiveditJain
Copy link
Member

No description provided.

- Updated README.md to include new "Triggers" feature for automatic scheduling of workflows using cron expressions.
- Added "Triggers" section in mkdocs.yml for navigation.
- Expanded concepts documentation to explain triggers and their lifecycle.
- Introduced examples for implementing triggers in graph templates and Python SDK.
- Created a new triggers.md file detailing trigger usage and common cron expressions.
- Updated StateManager and related models to support triggers for automatic graph execution.
- Revised the description of the `triggers` parameter in the README to indicate its beta status and specify the SDK version (0.0.3b1) associated with this feature. This enhances clarity for users regarding the current state of the triggers functionality.
@safedep
Copy link

safedep bot commented Sep 29, 2025

SafeDep Report Summary

Green Malicious Packages Badge Green Vulnerable Packages Badge Green Risky License Badge

Package Details
Package Malware Vulnerability Risky License Report

This report is generated by SafeDep Github App.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 29, 2025

Warning

Rate limit exceeded

@NiveditJain has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 19 minutes and 29 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 26ed57a and 2d77783.

📒 Files selected for processing (4)
  • state-manager/app/tasks/trigger_cron.py (3 hunks)
  • state-manager/app/tasks/verify_graph.py (4 hunks)
  • state-manager/tests/unit/controller/test_upsert_graph_template.py (1 hunks)
  • state-manager/tests/unit/tasks/test_verify_graph.py (6 hunks)

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Introduced Automatic Triggers (beta) for cron-based scheduling of graph executions.
    • Python SDK now supports defining triggers and scheduling via CronTrigger.
    • Upsert operations return richer metadata (validation status, errors, config, triggers, timestamps).
  • Documentation

    • Added comprehensive Triggers guide with JSON/Python examples, cron patterns, best practices, and limitations.
    • Updated Core Concepts, Graph Components, and Create Graph docs; added an Automatic Scheduling example and navigation entry.
  • Bug Fixes

    • Improved scheduling reliability: better duplicate handling, consistent rescheduling, and cleanup of outdated triggers on graph updates.

Walkthrough

Adds cron-based Triggers (beta) across docs, SDK, and state-manager: documents new Triggers concept and examples; exports CronTrigger and extends StateManager.upsert_graph(triggers=...); updates controller/task logic to create/clean cron triggers and returns expanded upsert metadata.

Changes

Cohort / File(s) Summary
SDK: StateManager & models
python-sdk/exospherehost/statemanager.py, python-sdk/exospherehost/models.py, python-sdk/README.md
Add CronTrigger model export; add `triggers: list[ CronTrigger ]
Docs: Concept, components, and usage
docs/docs/exosphere/concepts.md, docs/docs/exosphere/create-graph.md, docs/docs/exosphere/graph-components.md, docs/docs/exosphere/python-sdk-graph.md, docs/docs/exosphere/triggers.md, README.md
Add “Triggers” concept, Automatic Scheduling example (JSON & Python), cron patterns, retry policy, beta notes; update core lists, next-steps, and README snippets.
Docs navigation
docs/mkdocs.yml
Add Triggers page to navigation; minor whitespace fix.
State manager: controller & response models
state-manager/app/controller/upsert_graph_template.py, state-manager/app/models/... (response types)
On upsert, delete pending CRON triggers matching old expressions before verification; call verification without passing old_triggers; extend UpsertGraphTemplateResponse with validation metadata, secrets, retry_policy, store_config, triggers, created_at, updated_at.
State manager: task workers
state-manager/app/tasks/verify_graph.py, state-manager/app/tasks/trigger_cron.py
Simplify verify_graph to use only graph_template and create crons from graph_template.triggers; remove old diff/cancel helpers; in trigger_cron, loop insertions for next triggers, handle DuplicateKeyError, and ensure reschedule generation runs in finally block.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Dev as Developer
  participant SDK as Python SDK (StateManager)
  participant API as Exosphere Host API
  participant DB as Scheduler DB
  participant Exec as Execution Engine

  Dev->>SDK: upsert_graph(name,nodes,..., triggers=[CronTrigger(expr)...])
  SDK->>API: POST /graphs { ..., triggers:[{type:"CRON", expression:"..."}] }
  API->>DB: register cron trigger records
  DB-->>API: ack triggers created
  API-->>SDK: 200 OK { graph_id, triggers_registered:true }

  rect rgba(220,245,230,0.35)
    Note over DB,API: At scheduled times
    DB->>API: fire trigger (graph_id, trigger_id)
    API->>Exec: start graph execution
    Exec-->>API: execution status
  end

  alt Error registering triggers
    API-->>SDK: 4xx/5xx
    SDK-->>Dev: propagate error
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

I nibble logs at break of dawn, 🐇
Cron-lines hum and schedules yawn. ⏰
I hop, I plant a trigger seed,
Graphs wake up to do the deed.
Beta carrots — hop and run with me!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Description Check ⚠️ Warning The pull request description is completely missing, so there is no information to relate the description to the actual code and documentation changes introduced in this branch. Without any summary or context, reviewers lack guidance on the intent and scope of the modifications. Please add a descriptive summary of the changes that explains the new trigger functionality, documentation updates, API modifications, and any migration steps or version details, to provide reviewers with necessary context.
Title Check ❓ Inconclusive The title references the trigger beta release version but uses a generic phrase “Final changes” that does not clearly convey what functionality or documentation updates were made, making it hard for readers to understand the scope of the changes at a glance. Though it mentions the main feature (trigger beta), it emphasizes a release milestone rather than summarizing the substantive updates such as CronTrigger integration and documentation additions. This vagueness could hinder comprehension for team members reviewing pull request history. Consider revising the title to more specifically describe the key change, for example “Add CronTrigger-based automatic scheduling support (beta-0.0.3b1)”, so that it clearly communicates the main feature and purpose of the pull request.
✅ Passed checks (1 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.

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.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @NiveditJain, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request finalizes the beta release of the 'Triggers' feature, enabling users to schedule the automatic execution of their Exosphere graphs using cron expressions. The changes primarily focus on updating documentation across the project, including the main README, concept guides, and Python SDK examples, to clearly explain how to define, configure, and utilize these new scheduling capabilities.

Highlights

  • Introduction of Automatic Triggers: The pull request introduces and documents the 'Triggers' feature, allowing for the automatic scheduling of Exosphere graph executions using standard cron expressions. This feature is currently in beta.
  • Comprehensive Documentation Updates: Extensive documentation has been added and updated across the project, including the main README, core concepts, graph components, and a new dedicated 'Triggers' page, to guide users on how to define and utilize scheduled workflows.
  • Python SDK Integration: The Python SDK has been updated to support the new CronTrigger model, with examples demonstrating how to include triggers when creating or updating graphs via the upsert_graph method.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@codecov
Copy link

codecov bot commented Sep 29, 2025

Codecov Report

❌ Patch coverage is 42.30769% with 15 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
state-manager/app/tasks/trigger_cron.py 7.14% 13 Missing ⚠️
...te-manager/app/controller/upsert_graph_template.py 83.33% 1 Missing ⚠️
state-manager/app/tasks/verify_graph.py 80.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces the 'Triggers' feature for automatic graph execution via cron scheduling. The changes primarily involve adding extensive documentation for this new beta feature, including a new triggers.md page, and updating existing documentation and Python SDK examples. The backend implementation for handling cron triggers is also included. My review focuses on the clarity and correctness of the new documentation. I've pointed out a few areas in the documentation examples that could be improved for better user understanding, such as incomplete code snippets and a minor syntax error in a JSON example.

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: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
python-sdk/exospherehost/statemanager.py (1)

128-181: Avoid positional-argument breakage in upsert_graph.

Dropping triggers in ahead of validation_timeout shifts every downstream positional argument, so existing calls such as upsert_graph(..., retry_policy, store_config, 120, 2) now inject 120 into triggers and explode at runtime. Please keep the original positional contract by appending the new parameter instead. For example:

-    async def upsert_graph(self, graph_name: str, graph_nodes: list[GraphNodeModel], secrets: dict[str, str], retry_policy: RetryPolicyModel | None = None, store_config: StoreConfigModel | None = None, triggers: list[CronTrigger] | None = None, validation_timeout: int = 60, polling_interval: int = 1):
+    async def upsert_graph(self, graph_name: str, graph_nodes: list[GraphNodeModel], secrets: dict[str, str], retry_policy: RetryPolicyModel | None = None, store_config: StoreConfigModel | None = None, validation_timeout: int = 60, polling_interval: int = 1, triggers: list[CronTrigger] | None = None):
@@
-            triggers (list[CronTrigger] | None): Optional list of cron triggers for automatic
-                graph execution. Each trigger contains a cron expression that schedules when
-                the graph should be executed automatically.
+            triggers (list[CronTrigger] | None): Optional list of cron triggers for automatic
+                graph execution. Each trigger contains a cron expression that schedules when
+                the graph should be executed automatically.
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a6547b7 and 4f31163.

📒 Files selected for processing (10)
  • README.md (2 hunks)
  • docs/docs/exosphere/concepts.md (3 hunks)
  • docs/docs/exosphere/create-graph.md (1 hunks)
  • docs/docs/exosphere/graph-components.md (1 hunks)
  • docs/docs/exosphere/python-sdk-graph.md (2 hunks)
  • docs/docs/exosphere/triggers.md (1 hunks)
  • docs/mkdocs.yml (1 hunks)
  • python-sdk/README.md (4 hunks)
  • python-sdk/exospherehost/models.py (1 hunks)
  • python-sdk/exospherehost/statemanager.py (1 hunks)
🧰 Additional context used
🪛 markdownlint-cli2 (0.18.1)
docs/docs/exosphere/concepts.md

56-56: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


91-91: Trailing spaces
Expected: 0 or 2; Actual: 1

(MD009, no-trailing-spaces)

README.md

31-31: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


91-91: Trailing spaces
Expected: 0 or 2; Actual: 1

(MD009, no-trailing-spaces)

docs/docs/exosphere/triggers.md

42-42: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


210-210: Files should end with a single newline character

(MD047, single-trailing-newline)

NiveditJain and others added 3 commits September 29, 2025 09:53
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
…ate processing

- Updated the `upsert_graph_template` function to delete pending cron triggers when old triggers are present, enhancing trigger management.
- Modified the `create_next_triggers` function in `trigger_cron.py` to handle duplicate key errors gracefully, ensuring robust trigger creation.
- Streamlined the `verify_graph` function by removing the old triggers parameter and directly creating new cron triggers, improving clarity and performance.
- Enhanced error handling in the trigger processing logic to log errors and prevent failures from interrupting the workflow.
@coderabbitai coderabbitai bot added documentation Improvements or additions to documentation enhancement New feature or request labels Sep 29, 2025
@NiveditJain
Copy link
Member Author

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a new 'Triggers' feature for automatic cron-based scheduling of graphs. The changes are comprehensive, covering documentation, the Python SDK, and backend logic in the state-manager. The implementation is generally solid, particularly the reliability improvements in trigger execution. However, I've identified a couple of areas for improvement. There's a potential race condition in the trigger update logic that could affect correctness, and a performance concern with the catch-up mechanism for missed triggers. I've also suggested a minor clarification in the new documentation.

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: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
state-manager/app/tasks/verify_graph.py (1)

104-155: Restore cron cancellation contract and verify_graph signature

Dropping cancel_crons and narrowing verify_graph to a single parameter removed the only path that clears existing pending cron triggers when verification runs. Callers (including the unit tests) still import/patch cancel_crons and invoke verify_graph with the previous (graph_template, old_triggers) signature, which is why the pipeline now fails with AttributeError and TypeError. It also leaves any direct invocations of verify_graph unable to cancel stale cron triggers, so duplicates accumulate.

Please reinstate cancel_crons and keep the old signature (e.g. old_triggers: list[Trigger] | None = None) so we cancel when old triggers are supplied before creating new ones. The helper can reuse the existing deletion logic introduced in the upsert flow. Doing so also resolves the Ruff F401 warnings because Trigger and In become used again.

+async def cancel_crons(graph_template: GraphTemplate, old_triggers: list[Trigger]):
+    expressions_to_cancel = [
+        trigger.value["expression"]
+        for trigger in old_triggers
+        if trigger.type == TriggerTypeEnum.CRON
+    ]
+    if not expressions_to_cancel:
+        return
+
+    await DatabaseTriggers.find(
+        DatabaseTriggers.graph_name == graph_template.name,
+        DatabaseTriggers.namespace == graph_template.namespace,
+        DatabaseTriggers.trigger_status == TriggerStatusEnum.PENDING,
+        DatabaseTriggers.type == TriggerTypeEnum.CRON,
+        In(DatabaseTriggers.expression, expressions_to_cancel)
+    ).delete_many()
+
-async def verify_graph(graph_template: GraphTemplate):
+async def verify_graph(
+    graph_template: GraphTemplate,
+    old_triggers: list[Trigger] | None = None,
+):
@@
-        await graph_template.save()
-        await create_crons(graph_template)
+        await graph_template.save()
+        if old_triggers:
+            await cancel_crons(graph_template, old_triggers)
+        await create_crons(graph_template)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4f31163 and edbbfcf.

📒 Files selected for processing (4)
  • docs/docs/exosphere/graph-components.md (1 hunks)
  • state-manager/app/controller/upsert_graph_template.py (2 hunks)
  • state-manager/app/tasks/trigger_cron.py (3 hunks)
  • state-manager/app/tasks/verify_graph.py (3 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: NiveditJain
PR: exospherehost/exospherehost#428
File: state-manager/app/tasks/verify_graph.py:4-5
Timestamp: 2025-09-28T13:35:42.851Z
Learning: In the cron trigger scheduling logic for state-manager/app/tasks/verify_graph.py, the system intentionally schedules at least one trigger beyond the trigger_ahead_time window to ensure continuity of scheduled executions. The current logic of appending an event then breaking is by design to guarantee "at least one next" trigger.
📚 Learning: 2025-09-28T13:35:42.851Z
Learnt from: NiveditJain
PR: exospherehost/exospherehost#428
File: state-manager/app/tasks/verify_graph.py:4-5
Timestamp: 2025-09-28T13:35:42.851Z
Learning: In the cron trigger scheduling logic for state-manager/app/tasks/verify_graph.py, the system intentionally schedules at least one trigger beyond the trigger_ahead_time window to ensure continuity of scheduled executions. The current logic of appending an event then breaking is by design to guarantee "at least one next" trigger.

Applied to files:

  • state-manager/app/tasks/trigger_cron.py
  • state-manager/app/tasks/verify_graph.py
🧬 Code graph analysis (3)
state-manager/app/tasks/trigger_cron.py (2)
state-manager/app/models/db/trigger.py (1)
  • DatabaseTriggers (9-36)
state-manager/app/models/trigger_models.py (2)
  • TriggerTypeEnum (6-7)
  • TriggerStatusEnum (9-14)
state-manager/app/tasks/verify_graph.py (2)
state-manager/app/models/db/graph_template_model.py (1)
  • GraphTemplate (18-347)
state-manager/app/models/trigger_models.py (1)
  • TriggerTypeEnum (6-7)
state-manager/app/controller/upsert_graph_template.py (3)
state-manager/app/models/db/trigger.py (1)
  • DatabaseTriggers (9-36)
state-manager/app/models/trigger_models.py (2)
  • TriggerStatusEnum (9-14)
  • TriggerTypeEnum (6-7)
state-manager/app/tasks/verify_graph.py (1)
  • verify_graph (129-161)
🪛 GitHub Actions: Ruff check on changed files only
state-manager/app/tasks/verify_graph.py

[error] 5-5: Ruff: F401 'In' from beanie.operators is imported but unused. Remove unused import (lint error).


[error] 12-12: Ruff: F401 'Trigger' from app.models.trigger_models is imported but unused. Remove unused import (lint error).

🪛 GitHub Actions: State Manager Unit Tests
state-manager/app/tasks/verify_graph.py

[error] 1-1: AttributeError: module 'app.tasks.verify_graph' does not have the attribute 'cancel_crons'. Tests patch this symbol but it is missing in the module.


[error] 1-1: TypeError: verify_graph() takes 1 positional argument but 2 were given.

🔇 Additional comments (1)
docs/docs/exosphere/graph-components.md (1)

107-123: Triggers JSON example looks correct.

Thanks for tightening the snippet—this JSON is now standards-compliant and matches the documented cron trigger schema.

NiveditJain and others added 3 commits September 29, 2025 11:02
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
- Updated the `create_next_triggers` function in `trigger_cron.py` to raise exceptions on errors, enhancing error visibility.
- Modified test cases in `test_upsert_graph_template.py` and `test_verify_graph.py` to remove unnecessary parameters from `verify_graph`, streamlining the function calls and improving clarity.
- Adjusted mock setups in tests to reflect the changes in function signatures, ensuring accurate testing of trigger functionality.
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: 5

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between edbbfcf and 26ed57a.

📒 Files selected for processing (1)
  • docs/docs/exosphere/triggers.md (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: NiveditJain
PR: exospherehost/exospherehost#428
File: state-manager/app/tasks/verify_graph.py:4-5
Timestamp: 2025-09-28T13:35:42.851Z
Learning: In the cron trigger scheduling logic for state-manager/app/tasks/verify_graph.py, the system intentionally schedules at least one trigger beyond the trigger_ahead_time window to ensure continuity of scheduled executions. The current logic of appending an event then breaking is by design to guarantee "at least one next" trigger.
🪛 markdownlint-cli2 (0.18.1)
docs/docs/exosphere/triggers.md

42-42: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


211-211: Files should end with a single newline character

(MD047, single-trailing-newline)

🔇 Additional comments (3)
docs/docs/exosphere/triggers.md (3)

172-192: Good fix: the retry example now clarifies assumed variables.

The added comment removes ambiguity and makes the snippet self‑contained enough in context.


83-90: No revisions needed: imports and upsert_graph signature are accurate. All items are correctly exported at the package root, and the triggers and retry_policy parameters match the implementation.


161-163: Confirm cron timezone and DOW support: No timezone config found in code—verify APScheduler’s default evaluation timezone (it may not be UTC) and croniter’s support for both 0 and 7 as Sunday. Update docs if actual behavior differs.

- Removed unused import of `In` from beanie.operators to clean up the code.
- Streamlined the import section by retaining only necessary components, enhancing readability.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant