@@ -416,12 +416,12 @@ func (s *databaseSemaphore) checkAcquire(holderKey string, tx *transaction) (boo
416416 return true , false , ""
417417}
418418
419- func (s * databaseSemaphore ) acquire (holderKey string , tx * transaction ) bool {
419+ func (s * databaseSemaphore ) acquire (holderKey string , tx * transaction ) ( bool , error ) {
420420 limit := s .getLimit ()
421421 existing , err := s .currentHoldersSession (* tx .db )
422422 if err != nil {
423423 s .log .WithField ("key" , holderKey ).WithError (err ).Error ("Failed to acquire lock" )
424- return false
424+ return false , err
425425 }
426426 if len (existing ) < limit {
427427 var pending []stateRecord
@@ -435,7 +435,7 @@ func (s *databaseSemaphore) acquire(holderKey string, tx *transaction) bool {
435435 All (& pending )
436436 if err != nil {
437437 s .log .WithField ("key" , holderKey ).WithError (err ).Error ("Failed to acquire lock" )
438- return false
438+ return false , err
439439 }
440440 if len (pending ) > 0 {
441441 _ , err := (* tx .db ).SQL ().Update (s .info .config .stateTable ).
@@ -447,7 +447,7 @@ func (s *databaseSemaphore) acquire(holderKey string, tx *transaction) bool {
447447 Exec ()
448448 if err != nil {
449449 s .log .WithField ("key" , holderKey ).WithError (err ).Error ("Failed to acquire lock" )
450- return false
450+ return false , err
451451 }
452452 } else {
453453 record := & stateRecord {
@@ -459,14 +459,14 @@ func (s *databaseSemaphore) acquire(holderKey string, tx *transaction) bool {
459459 _ , err := (* tx .db ).Collection (s .info .config .stateTable ).Insert (record )
460460 if err != nil {
461461 s .log .WithField ("key" , holderKey ).WithError (err ).Error ("Failed to acquire lock" )
462- return false
462+ return false , err
463463 }
464464 }
465465 s .log .WithFields (log.Fields {
466466 "key" : holderKey ,
467467 "result" : true ,
468468 }).Info ("Acquire succeeded" )
469- return true
469+ return true , nil
470470 }
471471 s .log .WithFields (log.Fields {
472472 "key" : holderKey ,
@@ -475,41 +475,62 @@ func (s *databaseSemaphore) acquire(holderKey string, tx *transaction) bool {
475475 "current_holders" : len (existing ),
476476 "limit" : limit ,
477477 }).Info ("Acquire failed" )
478- return false
478+ return false , nil
479+ }
480+
481+ // reacquire asserts at startup that the recorded holder still holds this lock
482+ // in the database. The database is the single source of truth for a
483+ // database-backed lock: the held row is durable and survives the controller
484+ // restart, so nothing is inserted or mutated here. A missing row means the
485+ // hold no longer exists - e.g. it was expired by ExpireInactiveLocks while the
486+ // controller was down and may since have been acquired by another holder - so
487+ // the workflow's recorded hold is stale and the caller fails the workflow
488+ // rather than resurrect a hold the database does not back.
489+ func (s * databaseSemaphore ) reacquire (holderKey string , tx * transaction ) error {
490+ holders , err := s .currentHoldersSession (* tx .db )
491+ if err != nil {
492+ return fmt .Errorf ("could not verify hold on %s for %s: %w" , s .longDBKey (), holderKey , err )
493+ }
494+ if ! slices .Contains (holders , holderKey ) {
495+ return fmt .Errorf ("hold on %s for %s is not present in the database" , s .longDBKey (), holderKey )
496+ }
497+ return nil
479498}
480499
481- func (s * databaseSemaphore ) tryAcquire (holderKey string , tx * transaction ) (bool , string ) {
500+ func (s * databaseSemaphore ) tryAcquire (holderKey string , tx * transaction ) (bool , string , error ) {
482501 acq , already , msg := s .checkAcquire (holderKey , tx )
483502 if already {
484503 s .log .WithFields (log.Fields {
485504 "key" : holderKey ,
486505 "result" : true ,
487506 "message" : msg ,
488507 }).Info ("tryAcquire - already held" )
489- return true , msg
508+ return true , msg , nil
490509 }
491510 if ! acq {
492511 s .log .WithFields (log.Fields {
493512 "key" : holderKey ,
494513 "result" : false ,
495514 "message" : msg ,
496515 }).Info ("tryAcquire - cannot acquire" )
497- return false , msg
516+ return false , msg , nil
498517 }
499- if s .acquire (holderKey , tx ) {
518+ acquired , err := s .acquire (holderKey , tx )
519+ if acquired {
500520 s .log .WithFields (log.Fields {
501521 "key" : holderKey ,
502522 "result" : true ,
503523 }).Info ("tryAcquire succeeded" )
504524 s .notifyWaiters ()
505- return true , ""
525+ return true , "" , nil
506526 }
507527 s .log .WithFields (log.Fields {
508528 "key" : holderKey ,
509529 "result" : false ,
510530 "message" : msg ,
531+ "error" : err ,
511532 }).Info ("tryAcquire failed" )
512- return false , msg
533+ return false , msg , err
513534}
514535
515536func (s * databaseSemaphore ) expireLocks () {
0 commit comments