Skip to content

Conversation

@rushatgabhane
Copy link
Member

@rushatgabhane rushatgabhane commented Jan 18, 2026

Details

For Jobs plugin, added a new sequentialKey param. If multiple jobs have the same sequentialKey, then they will run one at a time, in the order they were created in.

  1. Added sequentialKey column to jobs table
  2. Jobs created with a sequentialKey check for existing active jobs with the same key
  3. If found, new job is set to WAITING state instead of QUEUED
  4. When a job completes (FinishJob, FailJob, DeleteJob), the next WAITING job with the same key is promoted to QUEUED

Unsupported stuff

I couldn't think of a usecase / requirement at the moment for these

  • Using repeat with sequentialKey - A repeating job never gets deleted, so WAITING jobs won't be promoted.
  • Child jobs used with sequentialKey - Child jobs are marked FINISHED (not deleted) when complete so WAITING jobs won't be promoted.

Fixed Issues

See - https://expensify.slack.com/archives/C086VHWPPUM/p1768336706994209?thread_ts=1768271555.676269&cid=C086VHWPPUM

Part of https://github.com/Expensify/Expensify/issues/568339

Tests

Unit tests added that verify

  1. First job with sequentialKey is QUEUED
  2. Second job with same key becomes WAITING when first is QUEUED
  3. Second job with same key becomes WAITING when first is RUNNING
  4. FinishJob promotes next WAITING job to QUEUED
  5. FailJob promotes next WAITING job to QUEUED
  6. DeleteJob promotes next WAITING job to QUEUED
  7. Three jobs with same key run in order
  8. Jobs with different keys don't block each other

Internal Testing Reminder: when changing bedrock, please compile auth against your new changes

@rushatgabhane rushatgabhane changed the title Sequential jobs Feature: add support for jobs to run sequentially Jan 18, 2026
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 adds support for sequential job execution in the Jobs plugin through a new sequentialKey parameter. Jobs sharing the same sequential key will execute one at a time in creation order, with subsequent jobs waiting until the active job completes.

Changes:

  • Added sequentialKey column to the jobs table
  • Jobs with an active sequential key are created in WAITING state instead of QUEUED
  • When jobs complete via FinishJob, FailJob, or DeleteJob, the next WAITING job with the same key is promoted to QUEUED

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
plugins/Jobs.cpp Added sequentialKey column to schema, logic to set jobs to WAITING when sequential key exists, and promotion logic in FinishJob/FailJob/DeleteJob
plugins/Jobs.md Documented the sequentialKey parameter and its limitations with repeat and parentJobID
test/tests/jobs/CreateJobTest.cpp Added comprehensive tests for sequential job creation and ordering
test/tests/jobs/FailJobTest.cpp Added test verifying FailJob promotes waiting jobs
test/tests/jobs/DeleteJobTest.cpp Added test verifying DeleteJob promotes waiting jobs
test/clustertest/tests/FinishJobTest.cpp Added test verifying FinishJob promotes waiting jobs

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +612 to +626
// If sequentialKey is set, check if there are other pending jobs with the same key.
// If so, this job should wait for them to complete before running by setting the initial state to WAITING.
const string& safeSequentialKey = SContains(job, "sequentialKey") ? SQ(job["sequentialKey"]) : SQ("");
if (safeSequentialKey != SQ("")) {
SQResult result;
if (!db.read("SELECT 1 FROM jobs "
"WHERE sequentialKey=" + safeSequentialKey + " "
"AND state IN ('QUEUED', 'RUNQUEUED', 'RUNNING', 'WAITING') "
"LIMIT 1;", result)) {
STHROW("502 Select failed");
}
if (!result.empty()) {
initialState = "WAITING";
}
}
Copy link

Copilot AI Jan 18, 2026

Choose a reason for hiding this comment

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

Missing validation to prevent unsupported combinations of sequentialKey with repeat or parentJobID. The PR description states these are unsupported because jobs with repeat or parentJobID don't get deleted on completion, preventing WAITING jobs from being promoted. However, there's no validation to prevent users from creating jobs with these combinations, which would lead to unexpected behavior where WAITING jobs never get promoted to QUEUED.

Copilot uses AI. Check for mistakes.
"parentJobID INTEGER NOT NULL DEFAULT 0, "
"retryAfter TEXT NOT NULL DEFAULT \"\")",
"retryAfter TEXT NOT NULL DEFAULT \"\", "
"sequentialKey TEXT NOT NULL DEFAULT \"\")",
Copy link

Copilot AI Jan 18, 2026

Choose a reason for hiding this comment

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

Missing database index for sequentialKey column. The queries at lines 617-620, 1224-1230, 1330-1336, and 1383-1389 filter by sequentialKey without an index, which will cause performance issues as the jobs table grows. An index should be added similar to other indexed columns.

Copilot uses AI. Check for mistakes.
Copy link
Member Author

Choose a reason for hiding this comment

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

Do we need an index? I thinkk let's add it when it becomes a problem

Comment on lines +612 to +626
// If sequentialKey is set, check if there are other pending jobs with the same key.
// If so, this job should wait for them to complete before running by setting the initial state to WAITING.
const string& safeSequentialKey = SContains(job, "sequentialKey") ? SQ(job["sequentialKey"]) : SQ("");
if (safeSequentialKey != SQ("")) {
SQResult result;
if (!db.read("SELECT 1 FROM jobs "
"WHERE sequentialKey=" + safeSequentialKey + " "
"AND state IN ('QUEUED', 'RUNQUEUED', 'RUNNING', 'WAITING') "
"LIMIT 1;", result)) {
STHROW("502 Select failed");
}
if (!result.empty()) {
initialState = "WAITING";
}
}
Copy link

Copilot AI Jan 18, 2026

Choose a reason for hiding this comment

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

The sequentialKey logic can override the parentJobID state logic, which could break parent-child job semantics. When both parentJobID and sequentialKey are set (an unsupported combination per the PR description), a child job that should be PAUSED (lines 605-610) can be set to WAITING (line 624), preventing it from running when the parent finishes. This is another reason why the combination should be explicitly validated and rejected.

Copilot uses AI. Check for mistakes.
@rushatgabhane rushatgabhane marked this pull request as ready for review January 19, 2026 23:28
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2daa99573f

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines 96 to +100
"data TEXT NOT NULL, "
"priority INTEGER NOT NULL DEFAULT " + SToStr(JOBS_DEFAULT_PRIORITY) + ", "
"parentJobID INTEGER NOT NULL DEFAULT 0, "
"retryAfter TEXT NOT NULL DEFAULT \"\")",
"retryAfter TEXT NOT NULL DEFAULT \"\", "
"sequentialKey TEXT NOT NULL DEFAULT \"\")",

Choose a reason for hiding this comment

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

P1 Badge Add migration for sequentialKey column

This change only updates the CREATE TABLE jobs SQL. verifyTable doesn’t alter existing tables, so an upgraded deployment with a pre-existing jobs table will still be missing sequentialKey, and subsequent statements like INSERT INTO jobs (..., sequentialKey) or the new SELECT ... sequentialKey will fail with “no such column,” breaking job creation/finish on upgrade. Please add an explicit schema migration (e.g., addColumn) or a guarded alter step for existing databases.

Useful? React with 👍 / 👎.

Copy link
Member Author

@rushatgabhane rushatgabhane Jan 19, 2026

Choose a reason for hiding this comment

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

we don't do this is code right? have to manually run Alter table before deploying this code

@rushatgabhane rushatgabhane requested a review from Gonals January 20, 2026 04:31
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