Skip to content

Commit 6c2ad0d

Browse files
committed
fix: job serialization for interface types
Ensures correct job type resolution when enqueuing jobs that implement interfaces. Previously, the job type was not correctly resolved when an interface was used as the type of the object containing the method to be executed. This commit updates the logic to correctly determine the underlying type of the object, ensuring proper serialization and subsequent execution of the job.
1 parent 1a557ee commit 6c2ad0d

2 files changed

Lines changed: 37 additions & 2 deletions

File tree

src/ByteBard.GUSTO.JobQueue/JobQueue.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,14 @@ public TStorageRecord ConstructRecordFromExpression(Expression expression, DateT
4141
var methodCallExpression = (MethodCallExpression)expression;
4242
var method = methodCallExpression.Method;
4343
var arguments = methodCallExpression.Arguments.Select(arg => Expression.Lambda(arg).Compile().DynamicInvoke()).ToArray();
44-
var targetType = method.DeclaringType;
44+
45+
Type targetType = methodCallExpression.Object switch
46+
{
47+
ConstantExpression c when c.Value != null => c.Value.GetType(),
48+
MemberExpression m => Expression.Lambda(m).Compile().DynamicInvoke()?.GetType() ?? method.DeclaringType,
49+
_ => method.DeclaringType
50+
};
51+
4552
var record = new TStorageRecord
4653
{
4754
TrackingId = Guid.NewGuid(),

src/ByteBard.GUSTO.Tests/JobQueueTests.cs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,42 @@ public class TestJobStorageRecord : IJobStorageRecord
1717
public bool IsComplete { get; set; }
1818
}
1919

20-
private class TestJob
20+
private interface ITestJob
21+
{
22+
Task DoSomethingAsync(string input);
23+
}
24+
25+
private class TestJob : ITestJob
2126
{
2227
public virtual Task DoSomethingAsync(string input)
2328
{
2429
return Task.CompletedTask;
2530
}
2631
}
2732

33+
[Fact]
34+
public async Task EnqueueAsync_ValidInterfaceJobType_StoresSerializedJobWithRealType()
35+
{
36+
// Arrange
37+
var storageProvider = Substitute.For<IJobStorageProvider<TestJobStorageRecord>>();
38+
var jobQueue = new JobQueue<TestJobStorageRecord>(storageProvider);
39+
var cancellationToken = CancellationToken.None;
40+
ITestJob testJob = new TestJob();
41+
42+
// Act
43+
var trackingId = await jobQueue.EnqueueAsync(() => testJob.DoSomethingAsync("hello"), null, cancellationToken);
44+
45+
// Assert
46+
await storageProvider.Received(1).StoreJobAsync(
47+
Arg.Is<TestJobStorageRecord>(record =>
48+
record.TrackingId == trackingId &&
49+
record.MethodName == "DoSomethingAsync" &&
50+
record.JobType == typeof(TestJob).AssemblyQualifiedName &&
51+
JsonConvert.DeserializeObject<string[]>(record.ArgumentsJson)[0] == "hello" &&
52+
!record.IsComplete),
53+
cancellationToken);
54+
}
55+
2856
[Fact]
2957
public async Task EnqueueAsync_ValidMethodCall_StoresSerializedJob()
3058
{

0 commit comments

Comments
 (0)