You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Filed alongside #1021, which describes how a synchronous throw inside a scheduled job's handler wedges CAP 10's srv.schedule(...).as(jobName) singleton lock. The workaround is a manual DELETE against CDS_OUTBOX_MESSAGES, plus a catch-block in runWithLock that does the same. Neither is what we want long-term — this is CAP-framework behavior.
Ask (to upstream at SAP Support Portal, component BC-XS-CDX-NJS)
Two options, either would fix it:
Guaranteed status-flip on throw. The CAP scheduling internals should wrap the handler invocation in a try/finally and always transition the CDS_OUTBOX_MESSAGES row out of processing — to error (if retries make sense) or delete it. Callers should not have to reach into the internal outbox schema to unstick themselves.
Publish a documented hook. Alternatively, expose a way for the handler (or the enclosing service) to explicitly signal "tick complete" that the framework can call on the exception path. That gives userland the ability to write the belt-and-suspenders catch itself without depending on unwritten schema invariants.
Option 1 is preferred; option 2 is acceptable.
Why this matters
The current behavior fails-open silently: no JobLastRun row, no PipelineLog, just a wedged tick that never fires again until manually cleared.
The failure mode is easy to hit — any resolver/config precondition inside the handler that throws synchronously before the first await will do it.
The pre-CAP-10 chassis (JobLocks) didn't have this problem because we owned lock lifecycle in runWithLock's finally-block. chore: replace node-cron scheduler with CAP 10 Scheduling API #958's migration to .as(name) moved lock lifecycle into the framework, which is fine, but now the framework has to guarantee the finally semantics we used to guarantee ourselves.
Draft SAP Support text
Component: BC-XS-CDX-NJS
Title: CAP 10 scheduling API — .as(jobName) singleton wedges on synchronous throw inside handler
Description: A scheduled job registered via srv.schedule('cron.foo', {}).every('13 2 * * *').as('foo') — where the on('cron.foo') handler throws synchronously (e.g. from a config-resolver precondition) — leaves the corresponding CDS_OUTBOX_MESSAGES row at STATUS='processing' indefinitely. Subsequent scheduled ticks do not fire; the framework treats the slot as occupied. Manual DELETE against CDS_OUTBOX_MESSAGES is the only recovery.
Expected: framework flips the row out of processing on any exit path (success OR throw), analogous to the try/finally pattern userland used before .as() locking existed.
Repro: register any .as(name) scheduled job whose handler throw new Error(...) before the first await. Wait through the next scheduled fire time. Observe: no JobLastRun row for the second tick, no PipelineLog, and SELECT STATUS FROM CDS_OUTBOX_MESSAGES WHERE TASK='<name>' still shows processing from the first tick.
Owner
Once someone with SAP Support access has bandwidth, paste the draft into launchpad.support.sap.com and link the incident number back to this issue.
Priority: medium — we have the workaround. But it's the kind of framework quirk that will bite every other CAP 10 project that has scheduled jobs, so worth surfacing.
Context
Filed alongside #1021, which describes how a synchronous throw inside a scheduled job's handler wedges CAP 10's
srv.schedule(...).as(jobName)singleton lock. The workaround is a manual DELETE againstCDS_OUTBOX_MESSAGES, plus a catch-block inrunWithLockthat does the same. Neither is what we want long-term — this is CAP-framework behavior.Ask (to upstream at SAP Support Portal, component BC-XS-CDX-NJS)
Two options, either would fix it:
CDS_OUTBOX_MESSAGESrow out ofprocessing— toerror(if retries make sense) or delete it. Callers should not have to reach into the internal outbox schema to unstick themselves.Option 1 is preferred; option 2 is acceptable.
Why this matters
JobLastRunrow, noPipelineLog, just a wedged tick that never fires again until manually cleared.awaitwill do it.runWithLock's finally-block. chore: replace node-cron scheduler with CAP 10 Scheduling API #958's migration to.as(name)moved lock lifecycle into the framework, which is fine, but now the framework has to guarantee the finally semantics we used to guarantee ourselves.Draft SAP Support text
Owner
Once someone with SAP Support access has bandwidth, paste the draft into launchpad.support.sap.com and link the incident number back to this issue.
Priority: medium — we have the workaround. But it's the kind of framework quirk that will bite every other CAP 10 project that has scheduled jobs, so worth surfacing.