Pottion / job loss with concurrent persistent jobs (job:eval + service:true)ential race condi
Friday, 14 August 2026 · 8 messages · last reply 26 Aug 2026
VC
Vincenzo Cestone14 Aug 2026 17:11 #
Hi BaseX Team,
We encountered a non-deterministic issue where persistent jobs (scheduled with `service: true()`) are lost after restarting BaseX HTTP server.
It appears to be a concurrency / thread-safety race condition when multiple requests (or rapid evaluations) create persistent jobs simultaneously.
### Steps to Reproduce
1. Deploy the following RESTXQ function:
module namespace _ = 'test:job';
declare
%rest:path("test/job")
%rest:GET
%output:method("text")
function _:jobtest() {
let $uuid := random:uuid()
return for $i in (1 to 3)
let $jobref := `Test/{$uuid}/{$i}`
let $datetime := current-dateTime() + xs:dayTimeDuration('PT2M') + $i *
xs:dayTimeDuration('PT5S')
let $jobopts := map { "id" : $jobref, "service" : true(), "start" :
$datetime }
let $jev := job:eval(`admin:write-log("Started job {$jobref}")`, (),
$jobopts)
return (`Scheduled {$jobref} @ {$datetime}`, admin:write-log(`Scheduled
job {$jev} at {$datetime}`))
};
2. Trigger concurrent calls to the endpoint (e.g. running 3 parallel curl
requests):
curl http://localhost:8080/test/job &
curl http://localhost:8080/test/job &
curl http://localhost:8080/test/job &3. Restart the BaseX server before the execution time arrives.
### Observed Result
All 9 jobs are reported as "Scheduled" in the logs before restart:
- Test/d8015eba-de2b-47d8-9140-99b45f18558a/1, /2, /3
- Test/e7a9b690-ccac-492f-a367-74dfbe122ed7/1, /2, /3
- Test/94f452aa-bc90-4d30-bf42-1201e3aa8e9f/1, /2, /3
However, after restarting the server, one job (e.g.,
`Test/94f452aa-bc90-4d30-bf42-1201e3aa8e9f/2`) disappears and is never executed.
It seems that concurrent writes to the persistent job registry (.jobs file / job manager state) lack proper synchronization, causing in-flight persistent schedules to overwrite each other.
Is this a known issue, or could internal synchronization be improved for job persistence?
Best regards,
Vincenzo
CG
Christian Grün17 Aug 2026 11:51 #
Hi Vincenzo,
Thanks for the excellent test case, which made it simple to reproduce the issue. As you already indicated, it was a race condition. It is resolved in the latest stable snapshot [1].
Spero che aiuti,
Christian
[1] https://files.basex.org/releases/latest/
Quoted text · Vincenzo Cestone · 38 lines
Von: Vincenzo Cestone via BaseX-Talk <basex-talk at mailman.uni-konstanz.de> Gesendet: Freitag, 14. August 2026 17:11 An: BaseX Betreff: [basex-talk] Pottion / job loss with concurrent persistent jobs (job:eval + service:true)ential race condi Hi BaseX Team, We encountered a non-deterministic issue where persistent jobs (scheduled with `service: true()`) are lost after restarting BaseX HTTP server. It appears to be a concurrency / thread-safety race condition when multiple requests (or rapid evaluations) create persistent jobs simultaneously. ### Steps to Reproduce 1. Deploy the following RESTXQ function: module namespace _ = 'test:job'; declare %rest:path("test/job") %rest:GET %output:method("text") function _:jobtest() { let $uuid := random:uuid() return for $i in (1 to 3) let $jobref := `Test/{$uuid}/{$i}` let $datetime := current-dateTime() + xs:dayTimeDuration('PT2M') + $i * xs:dayTimeDuration('PT5S') let $jobopts := map { "id" : $jobref, "service" : true(), "start" : $datetime } let $jev := job:eval(`admin:write-log("Started job {$jobref}")`, (), $jobopts) return (`Scheduled {$jobref} @ {$datetime}`, admin:write-log(`Scheduled job {$jev} at {$datetime}`)) }; 2. Trigger concurrent calls to the endpoint (e.g. running 3 parallel curl requests): curl http://localhost:8080/test/job & curl http://localhost:8080/test/job & curl http://localhost:8080/test/job & 3. Restart the BaseX server before the execution time arrives. ### Observed Result All 9 jobs are reported as "Scheduled" in the logs before restart: - Test/d8015eba-de2b-47d8-9140-99b45f18558a/1, /2, /3 - Test/e7a9b690-ccac-492f-a367-74dfbe122ed7/1, /2, /3 - Test/94f452aa-bc90-4d30-bf42-1201e3aa8e9f/1, /2, /3 However, after restarting the server, one job (e.g., `Test/94f452aa-bc90-4d30-bf42-1201e3aa8e9f/2`) disappears and is never executed. It seems that concurrent writes to the persistent job registry (.jobs file / job manager state) lack proper synchronization, causing in-flight persistent schedules to overwrite each other. Is this a known issue, or could internal synchronization be improved for job persistence? Best regards, Vincenzo
V
v.cestone17 Aug 2026 14:51 #
Hi Christian and BaseX Team,
Thank you very much for the quick fix. I tested the patch using the latest build.
Unfortunately, it seems that a regression occurred: using the exact same test setup as before, after restarting the server, none of the scheduled persistent jobs are triggered at all.
Additional observation: when running `
job:list()` right after the server restart, it shows the correct list of jobs but does not execute them.
VincenzoQuoted text · Christian Grün · 64 lines
Christian Grün wrote: > Hi Vincenzo, > > Thanks for the excellent test case, which made it simple to reproduce the issue. As you already indicated, it was a race condition. It is resolved in the latest stable snapshot [1]. > > Spero che aiuti, > Christian > > [1] https://files.basex.org/releases/latest/ > ________________________________________ > > Von: Vincenzo Cestone via BaseX-Talk <basex-talk at mailman.uni-konstanz.de> > Gesendet: Freitag, 14. August 2026 17:11 > An: BaseX > Betreff: [basex-talk] Pottion / job loss with concurrent persistent jobs (job:eval + service:true)ential race condi > > Hi BaseX Team, > > We encountered a non-deterministic issue where persistent jobs (scheduled with `service: true()`) are lost after restarting BaseX HTTP server. > > It appears to be a concurrency / thread-safety race condition when multiple requests (or rapid evaluations) create persistent jobs simultaneously. > > ### Steps to Reproduce > > 1. Deploy the following RESTXQ function: > > module namespace _ = 'test:job'; > > declare > %rest:path("test/job") > %rest:GET > %output:method("text") > function _:jobtest() { > let $uuid := random:uuid() > return for $i in (1 to 3) > let $jobref := `Test/{$uuid}/{$i}` > let $datetime := current-dateTime() + xs:dayTimeDuration('PT2M') + $i * xs:dayTimeDuration('PT5S') > let $jobopts := map { "id" : $jobref, "service" : true(), "start" : $datetime } > let $jev := job:eval(`admin:write-log("Started job {$jobref}")`, (), $jobopts) > return (`Scheduled {$jobref} @ {$datetime}`, admin:write-log(`Scheduled job {$jev} at {$datetime}`)) > }; > > 2. Trigger concurrent calls to the endpoint (e.g. running 3 parallel curl requests): > curl http://localhost:8080/test/job & > curl http://localhost:8080/test/job & > curl http://localhost:8080/test/job & > > 3. Restart the BaseX server before the execution time arrives. > > ### Observed Result > > All 9 jobs are reported as "Scheduled" in the logs before restart: > - Test/d8015eba-de2b-47d8-9140-99b45f18558a/1, /2, /3 > - Test/e7a9b690-ccac-492f-a367-74dfbe122ed7/1, /2, /3 > - Test/94f452aa-bc90-4d30-bf42-1201e3aa8e9f/1, /2, /3 > > However, after restarting the server, one job (e.g., `Test/94f452aa-bc90-4d30-bf42-1201e3aa8e9f/2`) disappears and is never executed. > > It seems that concurrent writes to the persistent job registry (.jobs file / job manager state) lack proper synchronization, causing in-flight persistent schedules to overwrite each other. > > Is this a known issue, or could internal synchronization be improved for job persistence? > > Best regards, > Vincenzo
CG
Christian Grün17 Aug 2026 15:10 #
Quoted text · v.cestone · 1 line
> Unfortunately, it seems that a regression occurred: using the exact same test setup as before, after restarting the server, none of the scheduled persistent jobs are triggered at all.
I didn’t manage to reproduce this out of the box. Could you try again, or provide me with a minimal use case?
ML
Marco Lettere17 Aug 2026 17:24 #
Hi all,
I can confirm Vincenzo's remarks. We tried on Ubuntu, Windows and MAc and it's always the same. After restarting the server jobs are never executed even if all remaining behaviour is correct (jobs appear in jobs:list until thei scheduled time and then are removed).
After some investigations we've found out by rewriting the jobopts as:
let $jobopts := map { "id" : $jobref, "service" : true(), "start" :
$datetime*, "log" : `Job {$i} started` *}that an attempt is made to run the jobs but it fails with the following class cast exception:
17:15:36.003 JOB:Test/4c5d89a9-a0f9-44ee-9f55-f5d97926ee1a/2 admin REQUEST *Job 1 started*
17:15:36.005 JOB:Test/4c5d89a9-a0f9-44ee-9f55-f5d97926ee1a/2 admin ERROR [xquery:error] Unexpected error: java.lang.ClassCastException: class org.basex.query.value.item.Bln cannot be cast to class org.basex.query.value.item.ANum (org.basex.query.value.item.Bln and org.basex.query.value.item.ANum are in un... 0.61 ms
Thus our suspicion is that something is messed up during parsing of the jobs.xml file after restarting.
In addition could you please change the documentation of the log option in the
job:eval to not show a false() as default but rather an empty sequence?
Regards,
Marco.Quoted text · Christian Grün · 3 lines
On 8/17/26 15:10, Christian Grün via BaseX-Talk wrote: >> Unfortunately, it seems that a regression occurred: using the exact same test setup as before, after restarting the server, none of the scheduled persistent jobs are triggered at all. > I didn’t manage to reproduce this out of the box. Could you try again, or provide me with a minimal use case?
CG
Christian Grün17 Aug 2026 20:05 #
Agreed; I am sorry. I assume that some attributes like `timeout` should not have ended up in your jobs.xml file. I’ll provide a bug fix soon.
Quoted text · Marco Lettere · 18 lines
Von: Marco Lettere via BaseX-Talk <basex-talk at mailman.uni-konstanz.de> Gesendet: Montag, 17. August 2026 17:24 An: basex-talk at mailman.uni-konstanz.de Betreff: [basex-talk] Re: Pottion / job loss with concurrent persistent jobs (job:eval + service:true)ential race condi Hi all, I can confirm Vincenzo's remarks. We tried on Ubuntu, Windows and MAc and it's always the same. After restarting the server jobs are never executed even if all remaining behaviour is correct (jobs appear in jobs:list until thei scheduled time and then are removed). After some investigations we've found out by rewriting the jobopts as: let $jobopts := map { "id" : $jobref, "service" : true(), "start" : $datetime, "log" : `Job {$i} started` } that an attempt is made to run the jobs but it fails with the following class cast exception: 17:15:36.003 JOB:Test/4c5d89a9-a0f9-44ee-9f55-f5d97926ee1a/2 admin REQUEST Job 1 started 17:15:36.005 JOB:Test/4c5d89a9-a0f9-44ee-9f55-f5d97926ee1a/2 admin ERROR [xquery:error] Unexpected error: java.lang.ClassCastException: class org.basex.query.value.item.Bln cannot be cast to class org.basex.query.value.item.ANum (org.basex.query.value.item.Bln and org.basex.query.value.item.ANum are in un... 0.61 ms Thus our suspicion is that something is messed up during parsing of the jobs.xml file after restarting. In addition could you please change the documentation of the log option in the job:eval to not show a false() as default but rather an empty sequence? Regards, Marco. On 8/17/26 15:10, Christian Grün via BaseX-Talk wrote: Unfortunately, it seems that a regression occurred: using the exact same test setup as before, after restarting the server, none of the scheduled persistent jobs are triggered at all. I didn’t manage to reproduce this out of the box. Could you try again, or provide me with a minimal use case?
CG
Hi Vincenzo, hi Marco,
A new snapshot is online [1]. If the jobs are not registered, try to remove the `timeout` attribute from jobs.xml. If it’s still playing mad, remove the jobs.xml file and try again.
Ciao,
Christian
PS: The newest version allows you to register new services in the DBA.
[1] https://files.basex.org/releases/latest/
Quoted text · Marco Lettere · 18 lines
Von: Marco Lettere via BaseX-Talk <basex-talk at mailman.uni-konstanz.de> Gesendet: Montag, 17. August 2026 17:24 An: basex-talk at mailman.uni-konstanz.de Betreff: [basex-talk] Re: Pottion / job loss with concurrent persistent jobs (job:eval + service:true)ential race condi Hi all, I can confirm Vincenzo's remarks. We tried on Ubuntu, Windows and MAc and it's always the same. After restarting the server jobs are never executed even if all remaining behaviour is correct (jobs appear in jobs:list until thei scheduled time and then are removed). After some investigations we've found out by rewriting the jobopts as: let $jobopts := map { "id" : $jobref, "service" : true(), "start" : $datetime, "log" : `Job {$i} started` } that an attempt is made to run the jobs but it fails with the following class cast exception: 17:15:36.003 JOB:Test/4c5d89a9-a0f9-44ee-9f55-f5d97926ee1a/2 admin REQUEST Job 1 started 17:15:36.005 JOB:Test/4c5d89a9-a0f9-44ee-9f55-f5d97926ee1a/2 admin ERROR [xquery:error] Unexpected error: java.lang.ClassCastException: class org.basex.query.value.item.Bln cannot be cast to class org.basex.query.value.item.ANum (org.basex.query.value.item.Bln and org.basex.query.value.item.ANum are in un... 0.61 ms Thus our suspicion is that something is messed up during parsing of the jobs.xml file after restarting. In addition could you please change the documentation of the log option in the job:eval to not show a false() as default but rather an empty sequence? Regards, Marco. On 8/17/26 15:10, Christian Grün via BaseX-Talk wrote: Unfortunately, it seems that a regression occurred: using the exact same test setup as before, after restarting the server, none of the scheduled persistent jobs are triggered at all. I didn’t manage to reproduce this out of the box. Could you try again, or provide me with a minimal use case?
V
v.cestone26 Aug 2026 12:08 #
Hi Christian,
I re-tested the latest build (08-25-2026) using the exact same test setup as before (running the 3 parallel curl requests to schedule multiple persistent jobs simultaneously).
I can confirm that the issue is completely resolved! All 9 persistent jobs were correctly written to the registry and executed as scheduled after restarting the server, with no jobs lost.
Thank you very much for the quick fix and great support!
Best regards,
Vincenzo
Written for BaseX 12.4. BaseX may have changed since: please check the current documentation.
⚡Generated with XQuery