Skip to content

Commit 2de78e0

Browse files
authored
Merge pull request #254 from NCronJob-Dev/ntk/delegates
Straighten registration of untyped named jobs
2 parents 9356df3 + fd1414d commit 2de78e0

File tree

5 files changed

+68
-5
lines changed

5 files changed

+68
-5
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ All notable changes to **NCronJob** will be documented in this file. The project
66

77
## [Unreleased]
88

9+
- Allow the registration of the same untyped job with different names. Reported by [@Mangatome](https://github.com/Mangatome) in [#~253](https://github.com/NCronJob-Dev/NCronJob/issues/253). Fixed by [@nulltoken](https://github.com/nulltoken) in [#252](https://github.com/NCronJob-Dev/NCronJob/pull/252) and [#254](https://github.com/NCronJob-Dev/NCronJob/pull/254).
10+
911
## [v4.4.0] - 2025-03-10
1012

1113
### Added

src/NCronJob/Registry/JobDefinition.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ private JobDefinition(
2828

2929
Delegate = jobDelegate;
3030
IsTypedJob = false;
31-
JobFullName = $"Untyped job {typeof(DynamicJobFactory).Namespace}.{DynamicJobNameGenerator.GenerateJobName(jobDelegate)}";
31+
JobFullName = customName is not null ?
32+
$"Untyped job {customName}" :
33+
$"Untyped job {typeof(DynamicJobFactory).Namespace}.{DynamicJobNameGenerator.GenerateJobName(jobDelegate)}";
3234

3335
JobPolicyMetadata = new JobExecutionAttributes(jobDelegate);
3436
}

src/NCronJob/Registry/JobRegistry.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,15 +145,15 @@ private sealed class JobDefinitionEqualityComparer : IEqualityComparer<JobDefini
145145

146146
public bool Equals(JobDefinition? x, JobDefinition? y) =>
147147
(x is null && y is null) || (x is not null && y is not null
148-
&& x.Type == y.Type && x.IsTypedJob
148+
&& x.JobFullName == y.JobFullName
149149
&& x.Parameter == y.Parameter
150150
&& x.CronExpression == y.CronExpression
151151
&& x.TimeZone == y.TimeZone
152152
&& x.CustomName == y.CustomName
153153
&& x.IsStartupJob == y.IsStartupJob);
154154

155155
public int GetHashCode(JobDefinition obj) => HashCode.Combine(
156-
obj.Type,
156+
obj.JobFullName,
157157
obj.Parameter,
158158
obj.CronExpression,
159159
obj.TimeZone,

tests/NCronJob.Tests/IntegrationTests.cs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -663,13 +663,40 @@ public async Task StaticAnonymousJobsCanBeExecutedMultipleTimes()
663663
}
664664

665665
[Fact]
666-
public void AddingJobsWithTheSameCustomNameLeadsToException()
666+
public void AddingUntypedJobsWithTheSameCustomNameLeadsToException()
667667
{
668668
Action act = () => ServiceCollection.AddNCronJob(
669669
n => n.AddJob(() => { }, Cron.AtEveryMinute, jobName: "Job1")
670670
.AddJob(() => { }, Cron.AtMinute0, jobName: "Job1"));
671671

672-
act.ShouldThrow<InvalidOperationException>();
672+
var e = act.ShouldThrow<InvalidOperationException>();
673+
e.Message.ShouldStartWith("Job registration conflict detected. A job has already been registered with the name 'Job1'.");
674+
}
675+
676+
[Fact]
677+
public void AddingUntypedJobsWithTheSameDelegateLeadsToException()
678+
{
679+
Delegate jobDelegate = () => { };
680+
681+
Action act = () => ServiceCollection.AddNCronJob(
682+
n => n.AddJob(jobDelegate, Cron.AtEveryMinute)
683+
.AddJob(jobDelegate, Cron.AtEveryMinute));
684+
685+
var e = act.ShouldThrow<InvalidOperationException>();
686+
e.Message.ShouldStartWith("Job registration conflict for job 'Untyped job NCronJob.UntypedJob_2SdMu4GO' detected. ");
687+
}
688+
689+
[Fact]
690+
public void CanAddUntypedJobsWithTheSameDelegateWithDifferentNames()
691+
{
692+
Delegate jobDelegate = () => { };
693+
694+
Action act = () => ServiceCollection.AddNCronJob(
695+
n => n.AddJob(jobDelegate, Cron.AtEveryMinute)
696+
.AddJob(jobDelegate, Cron.AtEveryMinute, jobName: "one")
697+
.AddJob(jobDelegate, Cron.AtEveryMinute, jobName: "another"));
698+
699+
act.ShouldNotThrow();
673700
}
674701

675702
[Fact]

tests/NCronJob.Tests/RuntimeJobRegistryTests.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,38 @@ public async Task MultipleDynamicallyAddedJobsAreExecuted()
6767
Storage.Entries.Count.ShouldBe(2);
6868
}
6969

70+
[Fact]
71+
public async Task CanRegisterMultipleTimesTheSameDelegateWithDifferentNames()
72+
{
73+
ServiceCollection.AddNCronJob();
74+
75+
await StartNCronJob(startMonitoringEvents: false);
76+
77+
var registry = ServiceProvider.GetRequiredService<IRuntimeJobRegistry>();
78+
79+
Events.Count.ShouldBe(0);
80+
81+
Delegate jobDelegate = () => { };
82+
83+
// Trying to register twice the same unnamed delegates fails
84+
registry.TryRegister(s => s.AddJob(jobDelegate, Cron.AtEveryMinute), out _).ShouldBe(true);
85+
86+
registry.TryRegister(s => s.AddJob(jobDelegate, Cron.AtEveryMinute), out Exception? unNamedUntypedJobException).ShouldBe(false);
87+
unNamedUntypedJobException.ShouldNotBeNull();
88+
unNamedUntypedJobException.Message.ShouldStartWith("Job registration conflict for job 'Untyped job NCronJob.UntypedJob_I2s40FrC' detected.");
89+
90+
// Trying to register twice the same named delegates fails as well
91+
registry.TryRegister(s => s.AddJob(jobDelegate, Cron.AtEveryMinute, jobName: "one"), out _).ShouldBe(true);
92+
registry.TryRegister(s => s.AddJob(jobDelegate, Cron.AtEveryMinute, jobName: "one"), out Exception? namedUntypedJobException).ShouldBe(false);
93+
namedUntypedJobException.ShouldNotBeNull();
94+
namedUntypedJobException.Message.ShouldStartWith("Job registration conflict detected. A job has already been registered with the name 'one'.");
95+
96+
registry.TryRegister(s => s.AddJob(jobDelegate, Cron.AtEveryMinute, jobName: "another"), out _).ShouldBe(true);
97+
98+
var jobRegistry = ServiceProvider.GetRequiredService<JobRegistry>();
99+
jobRegistry.GetAllJobs().Select(jd => jd.JobFullName).ShouldBe(["Untyped job NCronJob.UntypedJob_I2s40FrC", "Untyped job one", "Untyped job another"]);
100+
}
101+
70102
[Fact]
71103
public async Task CanRemoveJobByName()
72104
{

0 commit comments

Comments
 (0)