diff --git a/src/main/Hangfire.Storage.SQLite/CountersAggregator.cs b/src/main/Hangfire.Storage.SQLite/CountersAggregator.cs index 66f682c..e1a0288 100644 --- a/src/main/Hangfire.Storage.SQLite/CountersAggregator.cs +++ b/src/main/Hangfire.Storage.SQLite/CountersAggregator.cs @@ -1,10 +1,10 @@ using Hangfire.Annotations; using Hangfire.Logging; using Hangfire.Server; +using Hangfire.Storage.SQLite.Entities; using System; using System.Linq; using System.Threading; -using Hangfire.Storage.SQLite.Entities; namespace Hangfire.Storage.SQLite { diff --git a/src/main/Hangfire.Storage.SQLite/Hangfire.Storage.SQLite.csproj b/src/main/Hangfire.Storage.SQLite/Hangfire.Storage.SQLite.csproj index b5601ba..e7e2c1e 100644 --- a/src/main/Hangfire.Storage.SQLite/Hangfire.Storage.SQLite.csproj +++ b/src/main/Hangfire.Storage.SQLite/Hangfire.Storage.SQLite.csproj @@ -1,42 +1,43 @@  - - netstandard2.0 - - - netstandard2.0;net48 - - - 0.4.2 - RaisedApp - RaisedApp - Copyright © 2019 - Present - LICENSE - https://github.com/raisedapp/Hangfire.Storage.SQLite - https://github.com/raisedapp/Hangfire.Storage.SQLite - git - Hangfire Hangfire-Storage Hangfire-Extension SQLite - true - Hangfire Storage SQLite - An Alternative SQLite Storage for Hangfire - - 0.4.2 - -remove re-entrancy (fixes SQLiteDistributedLock doesn't play right with async #68). Thanks to @kirides - -pause heartbeat timer while processing. Thanks to @kirides - -update expiration using SQL Update statement in a single step. Thanks to @kirides - -Added Heartbeat event (for testing). Thanks to @kirides - -if we no longer own the lock, we immediately dispose the heartbeat timer (fixes Unable to update heartbeat - still happening in .NET 6.0 #69). Thanks to @kirides - - - - - True - - - - - - - + + netstandard2.0 + + + netstandard2.0;net48 + + + 0.4.3 + RaisedApp + RaisedApp + Copyright © 2019 - Present + LICENSE + https://github.com/raisedapp/Hangfire.Storage.SQLite + https://github.com/raisedapp/Hangfire.Storage.SQLite + git + Hangfire Hangfire-Storage Hangfire-Extension SQLite + true + Hangfire Storage SQLite + An Alternative SQLite Storage for Hangfire + + 0.4.3 + - Upgrade projects to .NET 8.0 (LTS). + - Update dependencies (Hangfire 1.8.23, Newtonsoft.Json 13.0.4). + - Explicitly referenced SQLitePCLRaw.bundle_green 2.1.11 to resolve NETSDK1206 RID-related warnings. + - Support for modern Hangfire 1.8 background process registration (GetStorageWideProcesses). + + + + + True + + + + + + + + + \ No newline at end of file diff --git a/src/main/Hangfire.Storage.SQLite/HangfireDbContext.cs b/src/main/Hangfire.Storage.SQLite/HangfireDbContext.cs index 539b011..c5a53bc 100644 --- a/src/main/Hangfire.Storage.SQLite/HangfireDbContext.cs +++ b/src/main/Hangfire.Storage.SQLite/HangfireDbContext.cs @@ -1,6 +1,5 @@ using Hangfire.Logging; using Hangfire.Storage.SQLite.Entities; -using Newtonsoft.Json; using SQLite; using System; using System.Threading; @@ -42,7 +41,7 @@ internal HangfireDbContext(SQLiteConnection connection, string prefix = "hangfir ConnectionId = Guid.NewGuid().ToString(); } - + /// /// Initializes initial tables schema for Hangfire /// @@ -62,7 +61,7 @@ public void Init(SQLiteStorageOptions storageOptions) TryFewTimesDueToConcurrency(() => Database.CreateTable()); TryFewTimesDueToConcurrency(() => Database.CreateTable()); TryFewTimesDueToConcurrency(() => Database.CreateTable()); - + void TryFewTimesDueToConcurrency(Action action, int times = 10) { var current = 0; @@ -136,7 +135,7 @@ protected virtual void Dispose(bool disposing) Database = null; } } - + public void Dispose() { Dispose(true); diff --git a/src/main/Hangfire.Storage.SQLite/PooledHangfireDbContext.cs b/src/main/Hangfire.Storage.SQLite/PooledHangfireDbContext.cs index d874996..c3b62a5 100644 --- a/src/main/Hangfire.Storage.SQLite/PooledHangfireDbContext.cs +++ b/src/main/Hangfire.Storage.SQLite/PooledHangfireDbContext.cs @@ -1,5 +1,5 @@ -using System; -using SQLite; +using SQLite; +using System; namespace Hangfire.Storage.SQLite { @@ -8,7 +8,7 @@ internal class PooledHangfireDbContext : HangfireDbContext private readonly Action _onDispose; public bool PhaseOut { get; set; } - internal PooledHangfireDbContext(SQLiteConnection connection, Action onDispose, string prefix = "hangfire") + internal PooledHangfireDbContext(SQLiteConnection connection, Action onDispose, string prefix = "hangfire") : base(connection, prefix) { _onDispose = onDispose ?? throw new ArgumentNullException(nameof(onDispose)); diff --git a/src/main/Hangfire.Storage.SQLite/SQLiteDbConnectionFactory.cs b/src/main/Hangfire.Storage.SQLite/SQLiteDbConnectionFactory.cs index 9c91fe5..5b883bf 100644 --- a/src/main/Hangfire.Storage.SQLite/SQLiteDbConnectionFactory.cs +++ b/src/main/Hangfire.Storage.SQLite/SQLiteDbConnectionFactory.cs @@ -1,5 +1,5 @@ -using System; -using SQLite; +using SQLite; +using System; namespace Hangfire.Storage.SQLite { diff --git a/src/main/Hangfire.Storage.SQLite/SQLiteDistributedLock.cs b/src/main/Hangfire.Storage.SQLite/SQLiteDistributedLock.cs index 6b78114..bd1b277 100644 --- a/src/main/Hangfire.Storage.SQLite/SQLiteDistributedLock.cs +++ b/src/main/Hangfire.Storage.SQLite/SQLiteDistributedLock.cs @@ -28,7 +28,7 @@ public class SQLiteDistributedLock : IDisposable private string EventWaitHandleName => string.Intern($@"{GetType().FullName}.{_resource}"); public event Action Heartbeat; - + /// /// Creates SQLite distributed lock /// @@ -117,7 +117,7 @@ private void Acquire(TimeSpan timeout) return; } - var waitTime = (int) timeout.TotalMilliseconds / 10; + var waitTime = (int)timeout.TotalMilliseconds / 10; // either wait for the event to be raised, or timeout lock (EventWaitHandleName) { @@ -134,7 +134,8 @@ private void Acquire(TimeSpan timeout) /// private void Release() { - Retry.Twice((retry) => { + Retry.Twice((retry) => + { // Remove resource lock (if it's still ours) var count = _dbContext.DistributedLockRepository.Delete(_ => _.Resource == _resource && _.ResourceKey == _resourceKey); @@ -150,7 +151,8 @@ private void Cleanup() { try { - Retry.Twice((_) => { + Retry.Twice((_) => + { // Delete expired locks (of any owner) _dbContext.DistributedLockRepository. Delete(x => x.Resource == _resource && x.ExpireAt < DateTime.UtcNow); diff --git a/src/main/Hangfire.Storage.SQLite/SQLiteMonitoringApi.cs b/src/main/Hangfire.Storage.SQLite/SQLiteMonitoringApi.cs index 72adbce..a05b0f5 100644 --- a/src/main/Hangfire.Storage.SQLite/SQLiteMonitoringApi.cs +++ b/src/main/Hangfire.Storage.SQLite/SQLiteMonitoringApi.cs @@ -1,12 +1,11 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Hangfire.Common; +using Hangfire.Common; using Hangfire.States; using Hangfire.Storage.Monitoring; using Hangfire.Storage.SQLite.Entities; using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; namespace Hangfire.Storage.SQLite { diff --git a/src/main/Hangfire.Storage.SQLite/SQLiteStorage.cs b/src/main/Hangfire.Storage.SQLite/SQLiteStorage.cs index 7f7adc3..85a452a 100644 --- a/src/main/Hangfire.Storage.SQLite/SQLiteStorage.cs +++ b/src/main/Hangfire.Storage.SQLite/SQLiteStorage.cs @@ -58,7 +58,8 @@ public SQLiteStorage(string databasePath, SQLiteStorageOptions storageOptions) string.IsNullOrWhiteSpace(databasePath) ? throw new ArgumentNullException(nameof(databasePath)) : databasePath, SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.Create | SQLiteOpenFlags.NoMutex, storeDateTimeAsTicks: true - ) {BusyTimeout = TimeSpan.FromSeconds(10)}), storageOptions) + ) + { BusyTimeout = TimeSpan.FromSeconds(10) }), storageOptions) { } @@ -135,6 +136,8 @@ public override bool HasFeature(string featureId) { if (featureId == null) throw new ArgumentNullException(nameof(featureId)); + if (featureId == "JobStorage.ProcessesInsteadOfComponents") return true; + return _features.TryGetValue(featureId, out var isSupported) ? isSupported : base.HasFeature(featureId); @@ -187,9 +190,18 @@ private static void ThrowObjectDisposedException() /// /// /// -#pragma warning disable 618 + public override IEnumerable GetStorageWideProcesses() + { + yield return new ExpirationManager(this, _storageOptions.JobExpirationCheckInterval); + yield return new CountersAggregator(this, _storageOptions.CountersAggregateInterval); + } + + /// + /// + /// + /// + [Obsolete("Please use GetStorageWideProcesses instead. Will be removed with Hangfire.Core 2.0.0.")] public override IEnumerable GetComponents() -#pragma warning restore 618 { yield return new ExpirationManager(this, _storageOptions.JobExpirationCheckInterval); yield return new CountersAggregator(this, _storageOptions.CountersAggregateInterval); diff --git a/src/main/Hangfire.Storage.SQLite/SQLiteStorageExtensions.cs b/src/main/Hangfire.Storage.SQLite/SQLiteStorageExtensions.cs index 7579d0d..e4f1206 100644 --- a/src/main/Hangfire.Storage.SQLite/SQLiteStorageExtensions.cs +++ b/src/main/Hangfire.Storage.SQLite/SQLiteStorageExtensions.cs @@ -1,7 +1,5 @@ using Hangfire.Annotations; using System; -using System.Collections.Generic; -using System.Text; namespace Hangfire.Storage.SQLite { @@ -20,9 +18,9 @@ public static IGlobalConfiguration UseSQLiteStorage( [NotNull] this IGlobalConfiguration configuration) { if (configuration == null) throw new ArgumentNullException(nameof(configuration)); - + var storage = new SQLiteStorage("Hangfire.db", new SQLiteStorageOptions()); - + return configuration.UseStorage(storage); } @@ -42,9 +40,9 @@ public static IGlobalConfiguration UseSQLiteStorage( if (configuration == null) throw new ArgumentNullException(nameof(configuration)); if (nameOrConnectionString == null) throw new ArgumentNullException(nameof(nameOrConnectionString)); if (options == null) options = new SQLiteStorageOptions(); - + var storage = new SQLiteStorage(nameOrConnectionString, options); - + return configuration.UseStorage(storage); } diff --git a/src/main/Hangfire.Storage.SQLite/SQLiteWriteOnlyTransaction.cs b/src/main/Hangfire.Storage.SQLite/SQLiteWriteOnlyTransaction.cs index 65d3e19..81cccb3 100644 --- a/src/main/Hangfire.Storage.SQLite/SQLiteWriteOnlyTransaction.cs +++ b/src/main/Hangfire.Storage.SQLite/SQLiteWriteOnlyTransaction.cs @@ -1,11 +1,9 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Linq.Expressions; -using System.Text; -using Hangfire.States; +using Hangfire.States; using Hangfire.Storage.SQLite.Entities; using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; namespace Hangfire.Storage.SQLite { @@ -113,7 +111,8 @@ public override void AddToSet(string key, string value, double score) public override void Commit() { - Retry.Twice((attempts) => { + Retry.Twice((attempts) => + { lock (_lockObject) { diff --git a/src/samples/ConsoleSample/ConsoleSample.csproj b/src/samples/ConsoleSample/ConsoleSample.csproj index 4c37de1..331712c 100644 --- a/src/samples/ConsoleSample/ConsoleSample.csproj +++ b/src/samples/ConsoleSample/ConsoleSample.csproj @@ -2,7 +2,7 @@ Exe - net6.0 + net8.0 enable enable diff --git a/src/samples/WebSample/WebSample.csproj b/src/samples/WebSample/WebSample.csproj index d3dab83..fde45ab 100644 --- a/src/samples/WebSample/WebSample.csproj +++ b/src/samples/WebSample/WebSample.csproj @@ -7,10 +7,10 @@ - + - + diff --git a/src/test/Hangfire.Storage.SQLite.Test/Hangfire.Storage.SQLite.Test.csproj b/src/test/Hangfire.Storage.SQLite.Test/Hangfire.Storage.SQLite.Test.csproj index 62d7c60..e8dbd14 100644 --- a/src/test/Hangfire.Storage.SQLite.Test/Hangfire.Storage.SQLite.Test.csproj +++ b/src/test/Hangfire.Storage.SQLite.Test/Hangfire.Storage.SQLite.Test.csproj @@ -1,7 +1,7 @@  - net6.0 + net8.0 false RaisedApp RaisedApp @@ -13,12 +13,12 @@ - - - - - - + + + + + + diff --git a/src/test/Hangfire.Storage.SQLite.Test/SQLiteDistributedLockFacts.cs b/src/test/Hangfire.Storage.SQLite.Test/SQLiteDistributedLockFacts.cs index f536ab2..6b4c4c5 100644 --- a/src/test/Hangfire.Storage.SQLite.Test/SQLiteDistributedLockFacts.cs +++ b/src/test/Hangfire.Storage.SQLite.Test/SQLiteDistributedLockFacts.cs @@ -84,7 +84,7 @@ public void Ctor_AcquireLockWithinSameThread_WhenResourceIsLocked_Should_Fail() } }); } - + private Thread NewBackgroundThread(ThreadStart start) { return new Thread(start) @@ -156,7 +156,7 @@ public void Ctor_WaitForLock_OnlySingleLockCanBeAcquired() using var manualResetEvent = new ManualResetEventSlim(); var success = new bool[numThreads]; var storage = ConnectionUtils.CreateStorage(); - + // Spawn multiple threads to race each other. var threads = Enumerable.Range(0, numThreads).Select(i => NewBackgroundThread(() => { @@ -244,7 +244,7 @@ public void Ctor_SetLockExpireAtWorks_WhenResourceIsLockedAndExpiring() } }); } - + [Fact] public async Task Heartbeat_Fires_WithSuccess() { @@ -260,7 +260,7 @@ await UseConnectionAsync(async database => Assert.True(result); }); } - + [Fact] public void Heartbeat_Fires_With_Fail_If_Lock_No_Longer_Exists() { @@ -305,13 +305,13 @@ private async Task WaitForHeartBeat(SQLiteDistributedLock slock, TimeSpan slock.Heartbeat -= onHeartbeat; } } - + private static void UseConnection(Action action, SQLiteStorage storage = null) { using var connection = storage?.CreateAndOpenConnection() ?? ConnectionUtils.CreateConnection(); action(connection); } - + private static async Task UseConnectionAsync(Func func, SQLiteStorage storage = null) { using var connection = storage?.CreateAndOpenConnection() ?? ConnectionUtils.CreateConnection(); diff --git a/src/test/Hangfire.Storage.SQLite.Test/SQLiteWriteOnlyTransactionFacts.cs b/src/test/Hangfire.Storage.SQLite.Test/SQLiteWriteOnlyTransactionFacts.cs index f74ea12..bff9057 100644 --- a/src/test/Hangfire.Storage.SQLite.Test/SQLiteWriteOnlyTransactionFacts.cs +++ b/src/test/Hangfire.Storage.SQLite.Test/SQLiteWriteOnlyTransactionFacts.cs @@ -860,7 +860,7 @@ public void AddRangeToSet_AddToExistingSetData() var testSet2 = GetTestSet(database, set2.Key); Assert.NotNull(testSet2); - Assert.Equal(1, testSet2.Count); + Assert.Single(testSet2); }); } @@ -882,10 +882,10 @@ public void RemoveSet_ClearsTheSetData() Commit(database, x => x.RemoveSet(set1Val1.Key)); var testSet1 = GetTestSet(database, set1Val1.Key); - Assert.Equal(0, testSet1.Count); + Assert.Empty(testSet1); var testSet2 = GetTestSet(database, set2.Key); - Assert.Equal(1, testSet2.Count); + Assert.Single(testSet2); }); } diff --git a/src/test/Hangfire.Storage.SQLite.Test/Utils/ConnectionUtils.cs b/src/test/Hangfire.Storage.SQLite.Test/Utils/ConnectionUtils.cs index 28ba152..190cc08 100644 --- a/src/test/Hangfire.Storage.SQLite.Test/Utils/ConnectionUtils.cs +++ b/src/test/Hangfire.Storage.SQLite.Test/Utils/ConnectionUtils.cs @@ -1,5 +1,5 @@ -using System; using SQLite; +using System; namespace Hangfire.Storage.SQLite.Test.Utils { @@ -16,12 +16,12 @@ public static SQLiteStorage CreateStorage(SQLiteStorageOptions storageOptions) { // See SQLite Docs: https://www.sqlite.org/c3ref/c_open_autoproxy.html // const SQLiteOpenFlags SQLITE_OPEN_MEMORY = (SQLiteOpenFlags) 0x00000080; - const SQLiteOpenFlags SQLITE_OPEN_URI = (SQLiteOpenFlags) 0x00000040; + const SQLiteOpenFlags SQLITE_OPEN_URI = (SQLiteOpenFlags)0x00000040; const SQLiteOpenFlags flags = // open the database in memory - // SQLITE_OPEN_MEMORY | - // SQLiteOpenFlags.SharedCache | - // for whatever reason, if we don't use URI-mode, - // shared in-memory databases dont work properly. + // SQLITE_OPEN_MEMORY | + // SQLiteOpenFlags.SharedCache | + // for whatever reason, if we don't use URI-mode, + // shared in-memory databases dont work properly. SQLITE_OPEN_URI | // open the database in read/write mode SQLiteOpenFlags.ReadWrite |