Skip to content

Commit 3dae7c5

Browse files
authored
Merge pull request #203 from Plasma/feature-expiration-manager-improvements
Improve ExpirationManager performance and options
2 parents e920229 + 121333d commit 3dae7c5

File tree

4 files changed

+54
-5
lines changed

4 files changed

+54
-5
lines changed

src/Hangfire.PostgreSql/ExpirationManager.cs

+2-3
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ namespace Hangfire.PostgreSql
3232
internal class ExpirationManager : IBackgroundProcess, IServerComponent
3333
{
3434
private static readonly TimeSpan DelayBetweenPasses = TimeSpan.FromSeconds(1);
35-
private const int NumberOfRecordsInSinglePass = 1000;
3635

3736
private static readonly ILog Logger = LogProvider.GetLogger(typeof(ExpirationManager));
3837

@@ -56,7 +55,7 @@ internal class ExpirationManager : IBackgroundProcess, IServerComponent
5655
private readonly TimeSpan _checkInterval;
5756

5857
public ExpirationManager(PostgreSqlStorage storage, PostgreSqlStorageOptions options)
59-
: this(storage, options, TimeSpan.FromHours(1))
58+
: this(storage, options, options.JobExpirationCheckInterval)
6059
{
6160
}
6261

@@ -93,7 +92,7 @@ DELETE FROM """ + _options.SchemaName + @""".""{0}""
9392
FROM """ + _options.SchemaName + @""".""{0}""
9493
WHERE ""expireat"" < NOW() AT TIME ZONE 'UTC'
9594
LIMIT {1}
96-
)", table, NumberOfRecordsInSinglePass.ToString(CultureInfo.InvariantCulture)), transaction);
95+
)", table, _options.DeleteExpiredBatchSize.ToString(CultureInfo.InvariantCulture)), transaction);
9796

9897
transaction.Commit();
9998
}

src/Hangfire.PostgreSql/PostgreSqlStorageOptions.cs

+34-1
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,20 @@ public class PostgreSqlStorageOptions
2929
private TimeSpan _invisibilityTimeout;
3030
private TimeSpan _distributedLockTimeout;
3131
private TimeSpan _transactionSerializationTimeout;
32+
private TimeSpan _jobExpirationCheckInterval;
33+
private int _deleteExpiredBatchSize;
3234

3335
public PostgreSqlStorageOptions()
3436
{
3537
QueuePollInterval = TimeSpan.FromSeconds(15);
3638
InvisibilityTimeout = TimeSpan.FromMinutes(30);
3739
DistributedLockTimeout = TimeSpan.FromMinutes(10);
3840
TransactionSynchronisationTimeout = TimeSpan.FromMilliseconds(500);
41+
JobExpirationCheckInterval = TimeSpan.FromHours(1);
3942
SchemaName = "hangfire";
4043
UseNativeDatabaseTransactions = true;
4144
PrepareSchemaIfNecessary = true;
45+
DeleteExpiredBatchSize = 1000;
4246
}
4347

4448
public TimeSpan QueuePollInterval
@@ -81,7 +85,30 @@ public TimeSpan TransactionSynchronisationTimeout
8185
}
8286
}
8387

84-
public bool UseNativeDatabaseTransactions { get; set; }
88+
public TimeSpan JobExpirationCheckInterval
89+
{
90+
get => _jobExpirationCheckInterval;
91+
set
92+
{
93+
ThrowIfValueIsNotPositive(value, nameof(JobExpirationCheckInterval));
94+
_jobExpirationCheckInterval = value;
95+
}
96+
}
97+
98+
/// <summary>
99+
/// Gets or sets the number of records deleted in a single batch in expiration manager
100+
/// </summary>
101+
public int DeleteExpiredBatchSize
102+
{
103+
get => _deleteExpiredBatchSize;
104+
set
105+
{
106+
ThrowIfValueIsNotPositive(value, nameof(DeleteExpiredBatchSize));
107+
_deleteExpiredBatchSize = value;
108+
}
109+
}
110+
111+
public bool UseNativeDatabaseTransactions { get; set; }
85112
public bool PrepareSchemaIfNecessary { get; set; }
86113
public string SchemaName { get; set; }
87114
public bool EnableTransactionScopeEnlistment { get; set; }
@@ -99,5 +126,11 @@ private static void ThrowIfValueIsNotPositive(TimeSpan value, string fieldName)
99126
throw new ArgumentException(message, nameof(value));
100127
}
101128
}
129+
130+
private static void ThrowIfValueIsNotPositive(int value, string fieldName)
131+
{
132+
if (value <= 0)
133+
throw new ArgumentException($"The {fieldName} property value should be positive. Given: {value}.");
134+
}
102135
}
103136
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
SET search_path = 'hangfire';
2+
3+
DO
4+
$$
5+
BEGIN
6+
IF EXISTS (SELECT 1 FROM "schema" WHERE "version"::integer >= 15) THEN
7+
RAISE EXCEPTION 'version-already-applied';
8+
END IF;
9+
END
10+
$$;
11+
12+
CREATE INDEX ix_hangfire_job_expireat ON "job" (expireat);
13+
CREATE INDEX ix_hangfire_list_expireat ON "list" (expireat);
14+
CREATE INDEX ix_hangfire_set_expireat ON "set" (expireat);
15+
CREATE INDEX ix_hangfire_hash_expireat ON "hash" (expireat);
16+
17+
RESET search_path;

tests/Hangfire.PostgreSql.Tests/PostgreSqlInstallerFacts.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public void InstallingSchemaUpdatesVersionAndShouldNotThrowAnException()
2020
PostgreSqlObjectsInstaller.Install(connection, schemaName);
2121

2222
var lastVersion = connection.Query<int>(@"select version from """ + schemaName + @""".""schema""").Single();
23-
Assert.Equal(14, lastVersion);
23+
Assert.Equal(15, lastVersion);
2424

2525
connection.Execute($@"DROP SCHEMA ""{schemaName}"" CASCADE;");
2626
});

0 commit comments

Comments
 (0)