Skip to content

PostgreSqlFetchedJob npgsql DateTimeOffset change for timestamptz column #385

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/Hangfire.PostgreSql/PostgreSqlFetchedJob.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// This file is part of Hangfire.PostgreSql.
// This file is part of Hangfire.PostgreSql.
// Copyright © 2014 Frank Hommers <http://hmm.rs/Hangfire.PostgreSql>.
//
// Hangfire.PostgreSql is free software: you can redistribute it and/or modify
@@ -46,7 +46,7 @@ public PostgreSqlFetchedJob(
long id,
string jobId,
string queue,
DateTime? fetchedAt)
DateTimeOffset? fetchedAt)
{
_storage = storage ?? throw new ArgumentNullException(nameof(storage));

@@ -66,7 +66,7 @@ public PostgreSqlFetchedJob(
public long Id { get; }
public string Queue { get; }
public string JobId { get; }
internal DateTime? FetchedAt { get; private set; }
internal DateTimeOffset? FetchedAt { get; private set; }

public void RemoveFromQueue()
{
@@ -167,7 +167,7 @@ internal void ExecuteKeepAliveQueryIfRequired()
{
_storage.UseConnection(null, connection =>
{
FetchedAt = connection.ExecuteScalar<DateTime?>(updateFetchAtSql,
FetchedAt = connection.ExecuteScalar<DateTimeOffset?>(updateFetchAtSql,
new { queue = Queue, id = Id, fetchedAt = FetchedAt });
});

2 changes: 1 addition & 1 deletion src/Hangfire.PostgreSql/PostgreSqlJobQueue.cs
Original file line number Diff line number Diff line change
@@ -323,7 +323,7 @@ private class FetchedJob
public long Id { get; set; }
public long JobId { get; set; }
public string Queue { get; set; }
public DateTime? FetchedAt { get; set; }
public DateTimeOffset? FetchedAt { get; set; }
public int UpdateCount { get; set; }
}
}
10 changes: 5 additions & 5 deletions tests/Hangfire.PostgreSql.Tests/PostgreSqlFetchedJobFacts.cs
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@
{
private const string JobId = "id";
private const string Queue = "queue";
private DateTime _fetchedAt = DateTime.UtcNow;
private DateTimeOffset _fetchedAt = DateTimeOffset.UtcNow;

private readonly PostgreSqlStorage _storage;

@@ -123,7 +123,7 @@
{
_storage.UseConnection(null, connection => {
// Arrange
var fetchedAt = DateTime.UtcNow.AddMinutes(-5);
var fetchedAt = DateTimeOffset.UtcNow.AddMinutes(-5);
long id = CreateJobQueueRecord(_storage, "1", "default", fetchedAt);
using (var processingJob = new PostgreSqlFetchedJob(_storage, id, "1", "default", fetchedAt))
{
@@ -134,8 +134,8 @@
dynamic record = connection.Query($@"SELECT * FROM ""{GetSchemaName()}"".""jobqueue""").Single();

Assert.NotNull(processingJob.FetchedAt);
Assert.Equal<DateTime?>(processingJob.FetchedAt, record.fetchedat);
DateTime now = DateTime.UtcNow;
Assert.Equal<DateTimeOffset?>(processingJob.FetchedAt, record.fetchedat);

Check failure on line 137 in tests/Hangfire.PostgreSql.Tests/PostgreSqlFetchedJobFacts.cs

GitHub Actions / Test results

Hangfire.PostgreSql.Tests.PostgreSqlFetchedJobFacts ► Timer_UpdatesFetchedAtColumn

Failed test found in: tests/Hangfire.PostgreSql.Tests/TestResults/TestResults.trx Error: Assert.Equal() Failure Expected: 2025-04-02T19:46:43.0986448+00:00 Actual: 2025-04-02T19:51:53.1016630+00:00
Raw output
Assert.Equal() Failure
Expected: 2025-04-02T19:46:43.0986448+00:00
Actual:   2025-04-02T19:51:53.1016630+00:00
   at CallSite.Target(Closure, CallSite, Type, Nullable`1, Object)
   at System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid3[T0,T1,T2](CallSite site, T0 arg0, T1 arg1, T2 arg2)
   at Hangfire.PostgreSql.Tests.PostgreSqlFetchedJobFacts.<Timer_UpdatesFetchedAtColumn>b__13_0(DbConnection connection) in /home/runner/work/Hangfire.PostgreSql/Hangfire.PostgreSql/tests/Hangfire.PostgreSql.Tests/PostgreSqlFetchedJobFacts.cs:line 137
   at Hangfire.PostgreSql.PostgreSqlStorage.<>c__DisplayClass31_0.<UseConnection>b__0(DbConnection connection) in /home/runner/work/Hangfire.PostgreSql/Hangfire.PostgreSql/src/Hangfire.PostgreSql/PostgreSqlStorage.cs:line 310
   at Hangfire.PostgreSql.PostgreSqlStorage.UseConnection[T](DbConnection dedicatedConnection, Func`2 func) in /home/runner/work/Hangfire.PostgreSql/Hangfire.PostgreSql/src/Hangfire.PostgreSql/PostgreSqlStorage.cs:line 322
   at Hangfire.PostgreSql.PostgreSqlStorage.UseConnection(DbConnection dedicatedConnection, Action`1 action) in /home/runner/work/Hangfire.PostgreSql/Hangfire.PostgreSql/src/Hangfire.PostgreSql/PostgreSqlStorage.cs:line 309
   at Hangfire.PostgreSql.Tests.PostgreSqlFetchedJobFacts.Timer_UpdatesFetchedAtColumn() in /home/runner/work/Hangfire.PostgreSql/Hangfire.PostgreSql/tests/Hangfire.PostgreSql.Tests/PostgreSqlFetchedJobFacts.cs:line 124
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
   at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
DateTimeOffset now = DateTimeOffset.UtcNow;
Assert.True(now.AddSeconds(-5) < record.fetchedat, (now - record.fetchedat).ToString());
}
});
@@ -202,7 +202,7 @@
Assert.Null(record.fetchedat);
}

private static long CreateJobQueueRecord(PostgreSqlStorage storage, string jobId, string queue, DateTime? fetchedAt)
private static long CreateJobQueueRecord(PostgreSqlStorage storage, string jobId, string queue, DateTimeOffset? fetchedAt)
{
string arrangeSql = $@"
INSERT INTO ""{GetSchemaName()}"".""jobqueue"" (""jobid"", ""queue"", ""fetchedat"")

Unchanged files with check annotations Beta

queue.Enqueue(connection, "2", "2");
queue.Enqueue(connection, "3", "3");
Assert.Equal("1", queue.Dequeue(new[] { "1", "2", "3" }, token).JobId);

Check warning on line 60 in tests/Hangfire.PostgreSql.Tests/PostgreSqlJobQueueFacts.cs

GitHub Actions / build-and-test

Prefer 'static readonly' fields over constant array arguments if the called method is called repeatedly and is not mutating the passed array (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1861)
Assert.Equal("2", queue.Dequeue(new[] { "2", "3", "1" }, token).JobId);

Check warning on line 61 in tests/Hangfire.PostgreSql.Tests/PostgreSqlJobQueueFacts.cs

GitHub Actions / build-and-test

Prefer 'static readonly' fields over constant array arguments if the called method is called repeatedly and is not mutating the passed array (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1861)
Assert.Equal("3", queue.Dequeue(new[] { "3", "1", "2" }, token).JobId);

Check warning on line 62 in tests/Hangfire.PostgreSql.Tests/PostgreSqlJobQueueFacts.cs

GitHub Actions / build-and-test

Prefer 'static readonly' fields over constant array arguments if the called method is called repeatedly and is not mutating the passed array (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1861)
});
}
{
UseConnection(connection => {
CancellationToken token = new();
string[] queues = { "default" };

Check warning on line 57 in tests/Hangfire.PostgreSql.Tests/PostgreSqlConnectionFacts.cs

GitHub Actions / build-and-test

Prefer 'static readonly' fields over constant array arguments if the called method is called repeatedly and is not mutating the passed array (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1861)
connection.FetchNextJob(queues, token);
UseConnection(connection => {
CancellationToken token = new CancellationToken();
Mock<IPersistentJobQueueProvider> anotherProvider = new Mock<IPersistentJobQueueProvider>();
_fixture.PersistentJobQueueProviderCollection.Add(anotherProvider.Object, new[] { "critical" });

Check warning on line 72 in tests/Hangfire.PostgreSql.Tests/PostgreSqlConnectionFacts.cs

GitHub Actions / build-and-test

Prefer 'static readonly' fields over constant array arguments if the called method is called repeatedly and is not mutating the passed array (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1861)
try
{
Assert.Throws<InvalidOperationException>(() => connection.FetchNextJob(new[] { "critical", "default" }, token));

Check warning on line 76 in tests/Hangfire.PostgreSql.Tests/PostgreSqlConnectionFacts.cs

GitHub Actions / build-and-test

Prefer 'static readonly' fields over constant array arguments if the called method is called repeatedly and is not mutating the passed array (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1861)
}
finally
{
public static string GetMasterConnectionString()
{
return string.Format(CultureInfo.InvariantCulture, GetConnectionStringTemplate(), MasterDatabaseName);

Check warning on line 34 in tests/Hangfire.PostgreSql.Tests/Utils/ConnectionUtils.cs

GitHub Actions / build-and-test

Cache a 'CompositeFormat' for repeated use in this formatting operation (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1863)
}
public static string GetConnectionString()
{
return string.Format(CultureInfo.InvariantCulture, GetConnectionStringTemplate(), GetDatabaseName());

Check warning on line 39 in tests/Hangfire.PostgreSql.Tests/Utils/ConnectionUtils.cs

GitHub Actions / build-and-test

Cache a 'CompositeFormat' for repeated use in this formatting operation (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1863)
}
public static NpgsqlConnectionFactory GetDefaultConnectionFactory([CanBeNull] PostgreSqlStorageOptions options = null)
BackgroundJob.Enqueue<TestJobs>("offline", job => job.Run("offline"));
BackgroundJobServer unused = new(new BackgroundJobServerOptions() {
Queues = new[] { "critical" },

Check warning on line 32 in tests/Hangfire.PostgreSql.Tests/FirstClassQueueFeatureSupportTests.cs

GitHub Actions / build-and-test

Prefer 'static readonly' fields over constant array arguments if the called method is called repeatedly and is not mutating the passed array (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1861)
});
Thread.Sleep(200);
{
public static void CleanTables(NpgsqlConnection connection)
{
if (connection == null) throw new ArgumentNullException(nameof(connection));

Check warning on line 34 in tests/Hangfire.PostgreSql.Tests/Utils/PostgreSqlTestObjectsInitializer.cs

GitHub Actions / build-and-test

Use 'ArgumentNullException.ThrowIfNull' instead of explicitly throwing a new exception instance (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1510)
string script = GetStringResource(typeof(PostgreSqlTestObjectsInitializer).GetTypeInfo().Assembly,
"Hangfire.PostgreSql.Tests.Scripts.Clean.sql").Replace("'hangfire'", $"'{ConnectionUtils.GetSchemaName()}'");