@@ -13,6 +13,38 @@ import (
1313 "gorm.io/gorm"
1414)
1515
16+ // A job whose preparation was deleted has attachment_id NULL (SET NULL cascade)
17+ // and stays Ready until the healthcheck reaper sweeps it. findJob must skip these
18+ // rather than claim them and nil-deref *job.Attachment downstream.
19+ func TestFindWorkSkipsOrphanedJob (t * testing.T ) {
20+ testutil .All (t , func (ctx context.Context , t * testing.T , db * gorm.DB ) {
21+ thread := & Thread {
22+ dbNoContext : db ,
23+ config : Config {EnableScan : true , EnablePack : true , EnableDag : true },
24+ logger : logger .With ("test" , true ),
25+ id : uuid .New (),
26+ }
27+
28+ _ , err := healthcheck .Register (ctx , thread .dbNoContext , thread .id , model .DatasetWorker , true )
29+ require .NoError (t , err )
30+
31+ for _ , jt := range []model.JobType {model .Scan , model .Pack , model .DagGen } {
32+ err = db .Create (& model.Job {
33+ AttachmentID : nil ,
34+ State : model .Ready ,
35+ Type : jt ,
36+ }).Error
37+ require .NoError (t , err )
38+ }
39+
40+ for _ , jt := range []model.JobType {model .Scan , model .Pack , model .DagGen } {
41+ found , err := thread .findJob (ctx , []model.JobType {jt })
42+ require .NoError (t , err )
43+ require .Nil (t , found , "orphaned %s job must not be claimed" , jt )
44+ }
45+ })
46+ }
47+
1648func TestFindPackWork (t * testing.T ) {
1749 testutil .All (t , func (ctx context.Context , t * testing.T , db * gorm.DB ) {
1850 thread := & Thread {
0 commit comments