MemberJunction / MemberJunction/MJ
Queue engine cannot enqueue tasks: QueueTask default 'Pending' violates CK_QueueTask_Status
- Dominant language
- TSQL
- Stars
- 29
- Forks
- 6
- Avg merge
- 2d 1h
- Merged PRs (30d)
- 323
Description
## Summary
The queue subsystem cannot enqueue a task against a real database: `QueueManager.AddTask` creates every `MJ: Queue Tasks` row with `Status = 'Pending'`, but `'Pending'` is **not** an allowed value of the `CK_QueueTask_Status` CHECK constraint. The INSERT is rejected, `BaseEntity.Save()` returns `false`, and no task is ever queued — so the whole queue path is inert end-to-end.
Surfaced during the review of #3542. That PR fixes the *adjacent* defect (`QueueBase.StartTask` discarding the `Save()` return, plus missing Developer/Integration CRUD grants), but those fixes are inert until a task can be created in the first place, which this issue blocks.
## Evidence
- **`packages/MJQueue/src/generic/QueueManager.ts:117`** — `taskRecord.Set('Status', 'Pending')` then `.Save()` at `:120`. Note the untyped `.Set(...)`: the strongly-typed setter would be a compile error, because…
- **Generated ORM (`packages/MJCoreEntities/src/generated/entity_subclasses.ts`, `MJQueueTaskEntity.Status`)**:
- Allowed values: `'Completed' | 'Failed' | 'In Progress'`
- **Default Value: `Pending`**
- i.e. the column's own default value is not a member of its own CHECK constraint.
So `AddTask` writes a value the CHECK forbids; the default is equally unusable. On any real SQL Server, `AddTask(...)` fails at record creation with a CHECK-constraint violation.
## Why it isn't caught today
- The `MJQueue` unit test mocks `Save()`, so the CHECK never runs — the mock returns success for a `'Pending'` status the database would reject.
- `.Set('Status', 'Pending')` bypasses the generated typed setter (`set Status(value: 'Completed' | 'Failed' | 'In Progress')`), which would otherwise flag `'Pending'` as a type error at compile time.
- The new integration bundle **IT78 – Queue Engine Lifecycle** works *around* the defect (it seeds fixture rows with persistable statuses and asserts engine-performed transitions), so it stays green and does not pin the bug.
## Impact
`QueueManager.AddTask` is non-functional against a real schema. Any feature that relies on the queue engine to enqueue and dispatch tasks cannot persist work.
## Proposed fix (pick one, then regenerate + test)
1. **Preferred — reconcile the value list with the lifecycle.** Decide whether `Pending` is a real lifecycle state:
- If yes: drop + re-add `CK_QueueTask_Status` in one migration to include `'Pending'`, then `mj codegen` so the generated `Status` union grows to include it. Keep the column default `'Pending'`.
- If no: change the column default to `'In Progress'` (or remove the default) **and** have `AddTask` insert with `'In Progress'`.
2. **Use the typed setter** — replace `taskRecord.Set('Status', …)` with `taskRecord.Status = …` so the value is validated at compile time against the generated union (this is what hid the bug).
3. **Add a real persistence test** — an integration check that actually persists a `QueueTask` through `AddTask` against the live CHECK, so the path can't silently regress again.
## References
- PR #3542 (review finding M4 / "notable findings for triage" #4)
- `migrations/v6/V202608110515__v6.1.x__Queue_Entity_Developer_Integration_Grants.sql` (the grants half of the queue fix)
Contributor guide
Research direction
Start with packages/MJQueue/src/generic/QueueManager.ts:117-120 and the generated MJQueueTaskEntity.Status in packages/MJCoreEntities/src/generated/entity_subclasses.ts. Inspect the QueueTask CHECK constraint and the referenced migration, then decide whether Pending belongs in the lifecycle. Regenerate with mj codegen and add a real persistence check through AddTask, using IT78 – Queue Engine Lifecycle as related integration coverage.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- sql, typescript
- Domain
- backend, databases, testing-qa
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100