Scheduler update#896
Closed
v1r3n wants to merge 25 commits into
Closed
Conversation
Covers SQLite module, Redis module (via JedisProxy), and replacement of all mock-based service tests with Testcontainers-backed integration tests. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fix @ConditionalOnExpression default: scheduler.enabled:false (not true) - Add JedisProxy extension requirements (zscore, zrevrangeByScore) - Document truncateStore() hook for Redis test teardown (no DataSource) - Replace batch hmget/mget with individual hget/get loop (JedisProxy gap) - Fix removeExecutionRecord to ZREM exec_by_sched via read-first pattern - Add Redis build.gradle dependencies and settings.gradle registration - Add META-INF/spring/AutoConfiguration.imports to both new modules - Add smoke test subclasses to all four modules in the concrete class table - Clarify @ClassRule Redis container lifecycle for JUnit 4 - Note secondary index omission is intentional for SQLite dev/test scope Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Change SQLite db.type from 'memory' to 'sqlite' (established codebase value) - Clarify truncateStore() refactoring as explicit prerequisite task, not already done — prevents implementer confusion with current base classes - Mark DST/catchup scenarios as future work (not yet in testFixtures) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Covers 21 tasks across 4 chunks: prerequisite test-base refactoring, SQLite module, Redis module (JedisProxy extensions + DAO), and mock test deletion. All review findings applied: - @TestConfiguration instead of @configuration in SQLite tests - FlywayAutoConfiguration added to @ContextConfiguration - SqliteSchedulerAutoConfigurationSmokeTest unconditionally overrides baseRunner() to add hikari.maximum-pool-size=1 - zrevrangeByScore wraps Set<String> in new ArrayList<>() for List return - deleteWorkflowSchedule does HDEL schedules first to bound inconsistency - setNextRunTimeInEpoch guards with hexists for non-existent schedules - JedisProxy construction uses new JedisStandalone(jedisPool) correctly - Task 20 pre-deletion gate covers all 4 backends (not just 2) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…-JDBC test backends Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…chema and tests Implements a SQLite-backed SchedulerDAO using INSERT OR REPLACE for upserts, manual IN-placeholder expansion, and a single HikariCP connection (maximumPoolSize=1) to ensure in-memory database isolation. Includes Flyway migration, Spring Boot auto-configuration, DAO test, service integration test, and smoke test. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… Redis DAO Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…y-backed DAO and tests Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… backend integration tests Also add V2 Flyway migrations for MySQL and Postgres (execution_time column + index), fixing MySQL-incompatible IF NOT EXISTS syntax in ADD COLUMN / CREATE INDEX. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add scheduler/examples/ with 8 verified workflow+schedule JSON pairs (basic, catchup, bounded, multistep fork/join, failure, concurrent, input-param, do-while) plus seed.sh and a full quickstart README - Add scheduler/scripts/ with 4 concurrency/load test scripts (concurrent write, concurrent resume, thundering herd, load blast) - Set workflow event field to "scheduler:<name>" on every scheduler- triggered workflow via StartWorkflowRequest.event, wired through StartWorkflowInput and WorkflowExecutorOps; test added to AbstractSchedulerServiceIntegrationTest - Wire conductor-scheduler-sqlite-persistence into server-lite and enable conductor.scheduler.enabled=true so the lite server supports the scheduler out of the box Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add getAllExecutionRecords(limit) to SchedulerDAO interface and all 4
backends (Postgres, MySQL, SQLite, Redis)
- Add searchExecutions() to SchedulerService with in-memory filtering
by scheduleName, status, workflowType, startTime range, executionId,
and free-text; supports sort and pagination
- Add GET /api/scheduler/search/executions endpoint to SchedulerResource
returning {results, totalHits} shape expected by the UI
- Add Scheduler nav entries (Definitions, Executions) to UI sidebar
- Point ui-next dev server at port 7001
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…endpoint Spring requires explicit parameter names when -parameters compiler flag is absent. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add GET /schedules/search with pagination, freeText, paused, workflowName
and sort filters — needed by /scheduleDef UI page
- Change pause/resume from PUT to GET (matches Orkes contract and UI fetch)
- Add GET /nextFewSchedules with cronExpression/startTime/endTime/limit params
- Change POST /schedules to return 200 (void) to match Orkes
- Change DELETE /schedules/{name} to return 200 to match Orkes
- searchExecutions now returns SearchResult<WorkflowScheduleExecution>
instead of raw Map
- Add searchSchedules() and getListOfNextSchedules() to SchedulerService
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…tests across all backends
- Add 73 integration tests to AbstractSchedulerServiceIntegrationTest covering:
- searchSchedules: filter by workflowName, freeText, scheduleName, paused; sort by
name/createTime/updatedTime ASC/DESC; pagination; combined filters
- searchExecutions: all 6 query clause types (scheduleName IN, status IN, workflowType IN,
startTime>/startTime<, executionId); freeText on scheduleName/workflowId/executionId;
all sort fields (startTime, scheduledTime) with direction defaulting; pagination
- getListOfNextSchedules: basic, startTime, endTime, and zero-limit cases
- Fix RedisSchedulerDAO.getAllExecutionRecords to use a dedicated KEY_EXEC_SCHED_NAMES set
instead of relying on getAllSchedules(), so executions saved without a schedule entry are
correctly enumerated
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
| } | ||
|
|
||
| private boolean matchesQuery(WorkflowScheduleExecution r, String query) { | ||
| for (String clause : query.split("(?i)\\s+AND\\s+")) { |
Check failure
Code scanning / CodeQL
Polynomial regular expression used on uncontrolled data High
| } | ||
| Matcher m; | ||
|
|
||
| m = Pattern.compile("(?i)scheduleName\\s+IN\\s+\\(([^)]+)\\)").matcher(clause); |
Check failure
Code scanning / CodeQL
Polynomial regular expression used on uncontrolled data High
| continue; | ||
| } | ||
|
|
||
| m = Pattern.compile("(?i)status\\s+IN\\s+\\(([^)]+)\\)").matcher(clause); |
Check failure
Code scanning / CodeQL
Polynomial regular expression used on uncontrolled data High
| continue; | ||
| } | ||
|
|
||
| m = Pattern.compile("(?i)workflowType\\s+IN\\s+\\(([^)]+)\\)").matcher(clause); |
Check failure
Code scanning / CodeQL
Polynomial regular expression used on uncontrolled data High
manan164
reviewed
Apr 14, 2026
|
|
||
| @PutMapping("/schedules/{name}/pause") | ||
| @ResponseStatus(HttpStatus.NO_CONTENT) | ||
| @GetMapping("/schedules/{name}/pause") |
manan164
reviewed
Apr 14, 2026
|
|
||
| @PutMapping("/schedules/{name}/resume") | ||
| @ResponseStatus(HttpStatus.NO_CONTENT) | ||
| @GetMapping("/schedules/{name}/resume") |
manan164
reviewed
Apr 14, 2026
| schedulerService.pauseSchedule(name); | ||
| } | ||
| public void pauseSchedule(@PathVariable("name") String name) { | ||
| schedulerService.pauseSchedule(name); |
Contributor
There was a problem hiding this comment.
Lets add reason parameter back
manan164
reviewed
Apr 14, 2026
| import org.springframework.ai.openai.api.OpenAiAudioApi; | ||
| import org.springframework.ai.openaisdk.OpenAiSdkChatModel; | ||
| import org.springframework.ai.openaisdk.OpenAiSdkChatOptions; | ||
| import org.springframework.ai.openaisdk.OpenAiSdkEmbeddingModel; |
manan164
approved these changes
Apr 14, 2026
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Pull Request type
NOTE: Please remember to run
./gradlew spotlessApplyto fix any format violations.Changes in this PR
Changes in this PR
Scheduler event field injection
When a workflow is triggered by the scheduler, the workflow's event field is now set to scheduler:. This makes it easy to identify which schedule fired a given workflow execution — visible in
workflow history, the UI, and any downstream observability tooling that reads the event field.
Implementation: added event to StartWorkflowRequest, wired it through the StartWorkflowInput constructor (which already had the field but never populated it from a request), and set it in
SchedulerService.dispatchWorkflow before calling startWorkflow. Test added to AbstractSchedulerServiceIntegrationTest so all persistence backends (Postgres, MySQL, SQLite, Redis) inherit the assertion.
Scheduler examples and scripts
Added scheduler/examples/ with 8 verified workflow + schedule JSON pairs covering common patterns: basic every-minute, catchup mode, bounded schedule, multi-step FORK/JOIN, failure scenario, concurrent
execution, input parameterization, and DO_WHILE internal loop. Includes seed.sh for the Docker demo stack and a README quickstart covering the full API lifecycle, cron format, configuration reference, and
per-scenario run instructions.
Added scheduler/scripts/ with 4 concurrency/load test scripts used during live validation (concurrent UPSERT, concurrent resume, thundering-herd N-schedule fanout, multi-client load blast).
server-lite scheduler wiring
Added conductor-scheduler-sqlite-persistence to server-lite/build.gradle and enabled conductor.scheduler.enabled=true in its application.properties so the standalone lite server supports the scheduler out of
the box.
Issue #