@@ -110,7 +110,6 @@ var RetentionHigh = Retention{
110110type Job struct {
111111 context.Context
112112 entryID * cron.EntryID
113- lock * sync.Mutex
114113 initialized bool
115114 unschedule func ()
116115 statusRing StatusRing
@@ -124,7 +123,7 @@ type Job struct {
124123 Fn func (ctx JobRuntime ) error
125124 JobHistory bool
126125 RunNow bool
127- ID string
126+ Aliases [] string
128127 ResourceID , ResourceType string
129128 IgnoreSuccessHistory bool
130129 lastHistoryCleanup time.Time
@@ -141,19 +140,23 @@ type Job struct {
141140
142141func (j * Job ) GetContext () map [string ]any {
143142 return map [string ]any {
144- "id" : j .ID ,
143+ "id" : j .ID (),
144+ "aliases" : j .Aliases ,
145145 "resourceID" : j .ResourceID ,
146146 "resourceType" : j .ResourceType ,
147147 "name" : j .Name ,
148148 "schedule" : j .Schedule ,
149149 }
150150}
151151
152- func (j * Job ) PK () string {
153- return strings .TrimSuffix (
154- strings .TrimSpace (fmt .Sprintf ("%s/%s" , j .Name , lo .CoalesceOrEmpty (j .ID , j .ResourceID ))),
155- "/" ,
156- )
152+ // ID returns the canonical logical identity for a job.
153+ // Aliases are intentionally excluded; they are configuration/display names.
154+ func (j * Job ) ID () string {
155+ parts := []string {strings .TrimSpace (j .Name )}
156+ if j .ResourceID != "" {
157+ parts = append (parts , strings .TrimSpace (j .ResourceType ), strings .TrimSpace (j .ResourceID ))
158+ }
159+ return strings .Join (lo .Compact (parts ), "/" )
157160}
158161
159162type StatusRing struct {
@@ -352,8 +355,9 @@ func (j *Job) Retain(r Retention) *Job {
352355 return j
353356}
354357
355- func (j * Job ) SetID (id string ) * Job {
356- j .ID = id
358+ // SetAliases sets friendly names used for job properties and display.
359+ func (j * Job ) SetAliases (aliases ... string ) * Job {
360+ j .Aliases = aliases
357361 return j
358362}
359363
@@ -379,7 +383,7 @@ func (j *Job) Run() {
379383 }
380384
381385 ctx , span := j .Context .StartSpan (j .Name )
382- ctx = ctx .WithName ("job." + j .PK ())
386+ ctx = ctx .WithName ("job." + j .ID ())
383387 defer span .End ()
384388
385389 r := JobRuntime {
@@ -406,32 +410,31 @@ func (j *Job) Run() {
406410 r .start ()
407411 defer r .end ()
408412 if j .Singleton {
409- ctx .Logger .V (4 ).Infof ("acquiring lock" )
413+ key := j .ID ()
414+ ctx .Logger .V (4 ).Infof ("acquiring lock %s" , key )
410415
411- if j .lock == nil {
412- j .lock = & sync.Mutex {}
413- }
414- if ! j .lock .TryLock () {
416+ unlock , ok := singletonLocks .TryLock (key )
417+ if ! ok {
415418 r .History .Status = models .StatusSkipped
416- ctx .Tracef ("failed to acquire lock" )
419+ ctx .Tracef ("failed to acquire lock %s" , key )
417420 r .Skipped ("job already running, skipping" )
418421 return
419422 }
420- defer j . lock . Unlock ()
423+ defer unlock ()
421424 }
422425
423426 for i , lock := range j .Semaphores {
424- ctx .Logger .V (6 ).Infof ("[%s] acquiring sempahore [%d/%d]" , j .ID , i + 1 , len (j .Semaphores ))
427+ ctx .Logger .V (6 ).Infof ("[%s] acquiring sempahore [%d/%d]" , j .ID () , i + 1 , len (j .Semaphores ))
425428 if err := lock .Acquire (ctx , 1 ); err != nil {
426429 r .Skipped ("too many concurrent jobs, skipping" )
427430 return
428431 }
429- ctx .Logger .V (7 ).Infof ("[%s] acquired sempahore [%d/%d]" , j .ID , i + 1 , len (j .Semaphores ))
432+ ctx .Logger .V (7 ).Infof ("[%s] acquired sempahore [%d/%d]" , j .ID () , i + 1 , len (j .Semaphores ))
430433
431434 defer func (s * semaphore.Weighted , msg string ) {
432435 s .Release (1 )
433436 ctx .Logger .V (6 ).Infof (msg )
434- }(lock , fmt .Sprintf ("[%s] released sempahore [%d/%d]" , j .ID , i + 1 , len (j .Semaphores )))
437+ }(lock , fmt .Sprintf ("[%s] released sempahore [%d/%d]" , j .ID () , i + 1 , len (j .Semaphores )))
435438 }
436439
437440 if j .Timeout > 0 {
@@ -449,41 +452,59 @@ func (j *Job) Run() {
449452}
450453
451454func (j * Job ) getPropertyNames (key string ) []string {
452- if j .ID == "" {
453- return []string {
454- fmt .Sprintf ("jobs.%s.%s" , j .Name , key ),
455- fmt .Sprintf ("jobs.%s" , key )}
455+ names := make ([]string , 0 , len (j .Aliases )+ 2 )
456+ for _ , alias := range j .aliases () {
457+ names = append (names , fmt .Sprintf ("jobs.%s.%s.%s" , j .Name , alias , key ))
456458 }
457- return []string {
458- fmt .Sprintf ("jobs.%s.%s.%s" , j .Name , j .ID , key ),
459+ return append (names ,
459460 fmt .Sprintf ("jobs.%s.%s" , j .Name , key ),
460- fmt .Sprintf ("jobs.%s" , key )}
461+ fmt .Sprintf ("jobs.%s" , key ),
462+ )
461463}
462464
463465func (j * Job ) GetProperty (property string ) (string , bool ) {
464- if val := j .Context .Properties ().String ("jobs." + j .Name + "." + property , "" ); val != "" {
465- return val , true
466- }
467- if j .ID != "" {
468- if val := j .Context .Properties ().String (fmt .Sprintf ("jobs.%s.%s.%s" , j .Name , j .ID , property ), "" ); val != "" {
466+ for _ , name := range j .getPropertyNames (property ) {
467+ if val := j .Context .Properties ().String (name , "" ); val != "" {
469468 return val , true
470469 }
471470 }
472471 return "" , false
473472}
474473
475474func (j * Job ) GetPropertyInt (property string , def int ) int {
476- if val := j .Context .Properties ().Int ("jobs." + j .Name + "." + property , def ); val != def {
477- return val
478- }
479- if j .ID != "" {
480- if val := j .Context .Properties ().Int (fmt .Sprintf ("jobs.%s.%s.%s" , j .Name , j .ID , property ), def ); val != def {
475+ for _ , name := range j .getPropertyNames (property ) {
476+ if val := j .Context .Properties ().Int (name , def ); val != def {
481477 return val
482478 }
483479 }
484480 return def
485481}
486482
483+ func (j * Job ) aliases () []string {
484+ aliases := make ([]string , 0 , len (j .Aliases ))
485+ seen := make (map [string ]struct {}, len (j .Aliases ))
486+ for _ , alias := range j .Aliases {
487+ alias = strings .TrimSpace (alias )
488+ if alias == "" {
489+ continue
490+ }
491+ if _ , ok := seen [alias ]; ok {
492+ continue
493+ }
494+ seen [alias ] = struct {}{}
495+ aliases = append (aliases , alias )
496+ }
497+ return aliases
498+ }
499+
500+ func (j * Job ) primaryAlias () string {
501+ aliases := j .aliases ()
502+ if len (aliases ) == 0 {
503+ return ""
504+ }
505+ return aliases [0 ]
506+ }
507+
487508func (j * Job ) init () error {
488509 StartJobHistoryEvictor (j .Context )
489510
@@ -544,8 +565,8 @@ func (j *Job) init() error {
544565 j .Context = j .Context .WithDBLogLevel (dbLevel )
545566 }
546567
547- if j . ID != "" {
548- j .Context = j .Context .WithName (fmt .Sprintf ("%s.%s" , strings .ToLower (j .Name ), j . ID ))
568+ if alias := j . primaryAlias (); alias != "" {
569+ j .Context = j .Context .WithName (fmt .Sprintf ("%s.%s" , strings .ToLower (j .Name ), alias ))
549570 } else if j .ResourceID != "" {
550571 j .Context = j .Context .WithName (fmt .Sprintf ("%s.%s" , strings .ToLower (j .Name ), j .ResourceID ))
551572 } else {
@@ -564,8 +585,8 @@ func (j *Job) init() error {
564585}
565586
566587func (j * Job ) Label () string {
567- if j . ID != "" {
568- return fmt .Sprintf ("%s/%s" , j .Name , j . ID )
588+ if alias := j . primaryAlias (); alias != "" {
589+ return fmt .Sprintf ("%s/%s" , j .Name , alias )
569590 }
570591 return j .Name
571592}
@@ -582,8 +603,8 @@ func (j *Job) String() string {
582603}
583604
584605func (j * Job ) GetResourcedName () string {
585- if j . ID != "" {
586- return fmt .Sprintf ("%s [%s]" , j .Name , j . ID )
606+ if alias := j . primaryAlias (); alias != "" {
607+ return fmt .Sprintf ("%s [%s]" , j .Name , alias )
587608 }
588609
589610 return j .Name
0 commit comments