diff --git a/Source/EventFlow.Hangfire.Tests/Integration/HangfireJobRunnerBackwardCompatibilityTests.cs b/Source/EventFlow.Hangfire.Tests/Integration/HangfireJobRunnerBackwardCompatibilityTests.cs new file mode 100644 index 000000000..965416e00 --- /dev/null +++ b/Source/EventFlow.Hangfire.Tests/Integration/HangfireJobRunnerBackwardCompatibilityTests.cs @@ -0,0 +1,99 @@ +// The MIT License (MIT) +// +// Copyright (c) 2015-2025 Rasmus Mikkelsen +// https://github.com/eventflow/EventFlow +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +using System.Threading; +using System.Threading.Tasks; +using EventFlow.Hangfire.Integration; +using EventFlow.Jobs; +using NUnit.Framework; +using Shouldly; + +namespace EventFlow.Hangfire.Tests.Integration +{ + /// + /// Exercises the legacy Hangfire job runner signatures removed in EventFlow 1.x to ensure + /// that jobs enqueued by EventFlow.Hangfire 0.x still deserialize and execute via the + /// forwarding overloads introduced to address issue #1109. + /// + [TestFixture] + public class HangfireJobRunnerBackwardCompatibilityTests + { + private sealed class RecordingJobRunner : IJobRunner + { + public (string JobName, int Version, string Job, CancellationToken CancellationToken)? LastCall { get; private set; } + + public Task ExecuteAsync(string jobName, int version, string json, CancellationToken cancellationToken) + { + LastCall = (jobName, version, json, cancellationToken); + return Task.CompletedTask; + } + + public void Reset() + { + LastCall = null; + } + } + + [Test] + public void OldJobRunnerSignatureIsStillExposed() + { + var methodInfo = typeof(IHangfireJobRunner).GetMethod( + "ExecuteAsync", + new[] + { + typeof(string), + typeof(string), + typeof(int), + typeof(string), + typeof(string), + }); + + methodInfo.ShouldNotBeNull(); + } + + [Test] + public async Task OldSignatureDelegatesToModernImplementation() + { + var recordingJobRunner = new RecordingJobRunner(); + var hangfireJobRunner = new HangfireJobRunner(recordingJobRunner); + + #pragma warning disable CS0618 + await hangfireJobRunner.ExecuteAsync("display", "job", 7, "payload").ConfigureAwait(false); + + recordingJobRunner.LastCall.ShouldNotBeNull(); + recordingJobRunner.LastCall.Value.JobName.ShouldBe("job"); + recordingJobRunner.LastCall.Value.Version.ShouldBe(7); + recordingJobRunner.LastCall.Value.Job.ShouldBe("payload"); + recordingJobRunner.LastCall.Value.CancellationToken.ShouldBe(CancellationToken.None); + + recordingJobRunner.Reset(); + + await hangfireJobRunner.ExecuteAsync("display", "job", 7, "payload", "queue").ConfigureAwait(false); + #pragma warning restore CS0618 + + recordingJobRunner.LastCall.ShouldNotBeNull(); + recordingJobRunner.LastCall.Value.JobName.ShouldBe("job"); + recordingJobRunner.LastCall.Value.Version.ShouldBe(7); + recordingJobRunner.LastCall.Value.Job.ShouldBe("payload"); + } + } +} diff --git a/Source/EventFlow.Hangfire/Integration/HangfireJobRunner.cs b/Source/EventFlow.Hangfire/Integration/HangfireJobRunner.cs index dc4ac5ae1..8463b6c4c 100644 --- a/Source/EventFlow.Hangfire/Integration/HangfireJobRunner.cs +++ b/Source/EventFlow.Hangfire/Integration/HangfireJobRunner.cs @@ -20,6 +20,7 @@ // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +using System; using System.Threading; using System.Threading.Tasks; using EventFlow.Jobs; @@ -36,9 +37,24 @@ public HangfireJobRunner( _jobRunner = jobRunner; } + [Obsolete("For backwards compatibility with jobs enqueued before EventFlow 1.x. Use ExecuteAsync(string jobName, int version, string job).")] + public Task ExecuteAsync(string displayName, string jobName, int version, string job) + { + _ = displayName; + return ExecuteAsync(jobName, version, job); + } + + [Obsolete("For backwards compatibility with jobs enqueued before EventFlow 1.x. Use ExecuteAsync(string jobName, int version, string job).")] + public Task ExecuteAsync(string displayName, string jobName, int version, string job, string queueName) + { + _ = displayName; + _ = queueName; + return ExecuteAsync(jobName, version, job); + } + public Task ExecuteAsync(string jobName, int version, string job) { return _jobRunner.ExecuteAsync(jobName, version, job, CancellationToken.None); } } -} \ No newline at end of file +} diff --git a/Source/EventFlow.Hangfire/Integration/IHangfireJobRunner.cs b/Source/EventFlow.Hangfire/Integration/IHangfireJobRunner.cs index e2eaaa6cc..f2ff14882 100644 --- a/Source/EventFlow.Hangfire/Integration/IHangfireJobRunner.cs +++ b/Source/EventFlow.Hangfire/Integration/IHangfireJobRunner.cs @@ -20,6 +20,7 @@ // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +using System; using System.ComponentModel; using System.Threading.Tasks; @@ -27,7 +28,15 @@ namespace EventFlow.Hangfire.Integration { public interface IHangfireJobRunner { + [Obsolete("For backwards compatibility with jobs enqueued before EventFlow 1.x. Use ExecuteAsync(string jobName, int version, string job).")] + [DisplayName("{0}")] + Task ExecuteAsync(string displayName, string jobName, int version, string job); + + [Obsolete("For backwards compatibility with jobs enqueued before EventFlow 1.x. Use ExecuteAsync(string jobName, int version, string job).")] + [DisplayName("{0}")] + Task ExecuteAsync(string displayName, string jobName, int version, string job, string queueName); + [DisplayName("{0}")] Task ExecuteAsync(string jobName, int version, string job); } -} \ No newline at end of file +}