-
Notifications
You must be signed in to change notification settings - Fork 48
Cl 1935 scheduling workflows which run on a specific time #217
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
danyalxahid-askui
merged 17 commits into
main
from
CL-1935-scheduling-workflows-which-run-on-a-specific-time
Jan 7, 2026
Merged
Changes from all commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
9df1002
feat(messages): add support for injecting cancelled tool results in m…
danyalxahid-askui f7fc4c3
fix(messages): update tool result content type in MessageService
danyalxahid-askui 6e74dc9
feat(scheduled_jobs): implement scheduled job management with APSched…
danyalxahid-askui 58a42a8
Merge branch 'main' into CL-1935-scheduling-workflows-which-run-on-a-…
danyalxahid-askui 3bc7230
refactor(scheduled_jobs): remove unused query parameter from list_sch…
danyalxahid-askui 3c2a95e
chore: update .gitignore and enhance SQLite configuration
danyalxahid-askui bd513ca
refactor(scheduled_jobs): update ScheduledJob creation to use params
danyalxahid-askui 8d01503
feat(scheduled_jobs): add name field to MessageRerunnerData and updat…
danyalxahid-askui 83e743f
feat(scheduled_jobs): enhance job execution with ASKUI token management
danyalxahid-askui 2c3a940
feat(scheduled_jobs): add scheduler database support and improve SQLi…
danyalxahid-askui 7137268
refactor(scheduled_jobs): update job execution logic and improve erro…
danyalxahid-askui b5b5872
refactor: remove functools.cache decorator from create_api_client fun…
danyalxahid-askui 6560bbe
Merge branch 'CL-2013-delivery-chat-unauthorized-chat-api' into CL-19…
danyalxahid-askui 93b1f5f
refactor(scheduled_jobs): enhance job execution and token management
danyalxahid-askui 927e641
refactor(scheduled_jobs): update execute_job to return ScheduledJobEx…
danyalxahid-askui e015c8b
refactor(settings, engine): optimize SQLite configuration and update …
danyalxahid-askui 61eed2e
refactor(scheduled_jobs): sort scheduled jobs by next fire time
danyalxahid-askui File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -166,6 +166,8 @@ reports/ | |
| .DS_Store | ||
| /chat | ||
| /askui_chat.db | ||
| /askui_chat.db-shm | ||
| /askui_chat.db-wal | ||
| .cache/ | ||
|
|
||
| bom.json | ||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| """FastAPI dependencies for scheduled jobs.""" | ||
|
|
||
| from fastapi import Depends | ||
|
|
||
| from askui.chat.api.scheduled_jobs.scheduler import scheduler | ||
| from askui.chat.api.scheduled_jobs.service import ScheduledJobService | ||
|
|
||
|
|
||
| def get_scheduled_job_service() -> ScheduledJobService: | ||
| """Get ScheduledJobService instance with the singleton scheduler.""" | ||
| return ScheduledJobService(scheduler=scheduler) | ||
|
|
||
|
|
||
| ScheduledJobServiceDep = Depends(get_scheduled_job_service) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,122 @@ | ||
| """Executor for scheduled job callbacks.""" | ||
|
|
||
| import base64 | ||
| import logging | ||
| import os | ||
| from typing import Any | ||
|
|
||
| from sqlalchemy.orm import Session | ||
|
|
||
| from askui.chat.api.db.engine import engine | ||
| from askui.chat.api.messages.dependencies import get_message_service | ||
| from askui.chat.api.runs.dependencies import create_run_service | ||
| from askui.chat.api.runs.models import RunCreate | ||
| from askui.chat.api.scheduled_jobs.models import ( | ||
| MessageRerunnerData, | ||
| ScheduledJobExecutionResult, | ||
| scheduled_job_data_adapter, | ||
| ) | ||
|
|
||
| _logger = logging.getLogger(__name__) | ||
|
|
||
|
|
||
| async def execute_job( | ||
| **_kwargs: Any, | ||
| ) -> ScheduledJobExecutionResult: | ||
| """ | ||
| APScheduler callback that creates fresh services and executes the job. | ||
|
|
||
| This function is called by APScheduler when a job fires. It creates fresh | ||
| database sessions and service instances to avoid stale connections. | ||
|
|
||
| Args: | ||
| **_kwargs (Any): Keyword arguments containing job data. | ||
|
|
||
| Returns: | ||
| ScheduledJobExecutionResult: The result containing job data and optional error. | ||
| """ | ||
| # Validates and returns the correct concrete type based on the `type` discriminator | ||
| job_data = scheduled_job_data_adapter.validate_python(_kwargs) | ||
|
|
||
| _logger.info( | ||
| "Executing scheduled job: workspace=%s, thread=%s", | ||
| job_data.workspace_id, | ||
| job_data.thread_id, | ||
| ) | ||
|
|
||
| error: str | None = None | ||
|
|
||
| try: | ||
| # future proofing of new job types | ||
| if isinstance(job_data, MessageRerunnerData): # pyright: ignore[reportUnnecessaryIsInstance] | ||
| # Save previous ASKUI_TOKEN and AUTHORIZATION_HEADER env vars | ||
| _previous_authorization = os.environ.get("ASKUI__AUTHORIZATION") | ||
|
|
||
| # remove authorization header since it takes precedence over the token and is set when forwarding bearer token | ||
| os.environ["ASKUI__AUTHORIZATION"] = ( | ||
| f"Basic {base64.b64encode(job_data.askui_token.get_secret_value().encode()).decode()}" | ||
| ) | ||
|
|
||
| try: | ||
| await _execute_message_rerunner_job(job_data) | ||
| finally: | ||
| # Restore previous AUTHORIZATION_HEADER env var | ||
| if _previous_authorization is not None: | ||
| os.environ["ASKUI__AUTHORIZATION"] = _previous_authorization | ||
| except Exception as e: | ||
| error = f"{type(e).__name__}: {e}" | ||
| _logger.exception("Scheduled job failed: %s", error) | ||
|
|
||
| # Always return job data with optional error | ||
| return ScheduledJobExecutionResult(data=job_data, error=error) | ||
|
|
||
|
|
||
| async def _execute_message_rerunner_job( | ||
| job_data: MessageRerunnerData, | ||
| ) -> None: | ||
| """ | ||
| Execute a message rerunner job. | ||
|
|
||
| Args: | ||
| job_data: The job data. | ||
| """ | ||
| with Session(engine) as session: | ||
| message_service = get_message_service(session) | ||
| run_service = create_run_service(session, job_data.workspace_id) | ||
|
|
||
| # Create message | ||
| message_service.create( | ||
| workspace_id=job_data.workspace_id, | ||
| thread_id=job_data.thread_id, | ||
| params=job_data.message, | ||
| ) | ||
|
|
||
| # Create and execute run | ||
| _logger.debug("Creating run with assistant %s", job_data.assistant_id) | ||
| run, generator = await run_service.create( | ||
| workspace_id=job_data.workspace_id, | ||
| thread_id=job_data.thread_id, | ||
| params=RunCreate(assistant_id=job_data.assistant_id, model=job_data.model), | ||
| ) | ||
|
|
||
| # Consume generator to completion of run | ||
| _logger.debug("Waiting for run %s to complete", run.id) | ||
| async for _event in generator: | ||
| pass | ||
|
|
||
| # Check if run completed with error | ||
| completed_run = run_service.retrieve( | ||
| workspace_id=job_data.workspace_id, | ||
| thread_id=job_data.thread_id, | ||
| run_id=run.id, | ||
| ) | ||
|
|
||
| if completed_run.status == "failed": | ||
| error_message = ( | ||
| completed_run.last_error.message | ||
| if completed_run.last_error | ||
| else "Run failed with unknown error" | ||
| ) | ||
| raise RuntimeError(error_message) | ||
|
|
||
| _logger.info("Scheduled job completed: run_id=%s", run.id) |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.