diff --git a/src/Evolve/Dialect/Cassandra/CassandraCluster.cs b/src/Evolve/Dialect/Cassandra/CassandraCluster.cs
index c2245a3c..0936131a 100644
--- a/src/Evolve/Dialect/Cassandra/CassandraCluster.cs
+++ b/src/Evolve/Dialect/Cassandra/CassandraCluster.cs
@@ -39,7 +39,7 @@ public override IEvolveMetadata GetMetadataTable(string schema, string tableName
/// Will check for a predefined keyspace and table to see if there is a lock.
/// Otherwise, always returns true, because the lock is granted at table level.
///
- public override bool TryAcquireApplicationLock()
+ public override bool TryAcquireApplicationLock(object? lockId = null)
{
string clusterLockKeyspaceName = "cluster_lock";
string clusterLockTableName = "lock";
@@ -54,6 +54,9 @@ public override bool TryAcquireApplicationLock()
clusterLockTableName = clusterLock!.GetValue("defaultClusterLockTable", clusterLockTableName)!;
}
+ // Input parameter overrides both the above variants
+ clusterLockTableName = lockId?.ToString() ?? clusterLockTableName;
+
try
{
return WrappedConnection.QueryForLong($"select count(locked) from {clusterLockKeyspaceName}.{clusterLockTableName}") == 0;
@@ -71,7 +74,7 @@ public override bool TryAcquireApplicationLock()
///
/// Returns always true, because the lock is released at table level.
///
- public override bool ReleaseApplicationLock() => true;
+ public override bool ReleaseApplicationLock(object? lockId = null) => true;
public override SqlStatementBuilderBase SqlStatementBuilder { get; } = new CqlStatementBuilder();
}
diff --git a/src/Evolve/Dialect/CockroachDB/CockroachDBCluster.cs b/src/Evolve/Dialect/CockroachDB/CockroachDBCluster.cs
index 6da3a87f..f7526168 100644
--- a/src/Evolve/Dialect/CockroachDB/CockroachDBCluster.cs
+++ b/src/Evolve/Dialect/CockroachDB/CockroachDBCluster.cs
@@ -21,8 +21,8 @@ public CockroachDBCluster(WrappedConnection wrappedConnection) : base(wrappedCon
public override Schema GetSchema(string schemaName) => new CockroachDBDatabase(schemaName, WrappedConnection);
- public override bool TryAcquireApplicationLock() => true;
+ public override bool TryAcquireApplicationLock(object? lockId = null) => true;
- public override bool ReleaseApplicationLock() => true;
+ public override bool ReleaseApplicationLock(object? lockId = null) => true;
}
}
\ No newline at end of file
diff --git a/src/Evolve/Dialect/DatabaseHelper.cs b/src/Evolve/Dialect/DatabaseHelper.cs
index 19bb8d8e..887e15d7 100644
--- a/src/Evolve/Dialect/DatabaseHelper.cs
+++ b/src/Evolve/Dialect/DatabaseHelper.cs
@@ -28,9 +28,9 @@ protected DatabaseHelper(WrappedConnection wrappedConnection)
public abstract IEvolveMetadata GetMetadataTable(string schema, string tableName);
- public abstract bool TryAcquireApplicationLock();
+ public abstract bool TryAcquireApplicationLock(object? lockId = null);
- public abstract bool ReleaseApplicationLock();
+ public abstract bool ReleaseApplicationLock(object? lockId = null);
public void Dispose()
{
diff --git a/src/Evolve/Dialect/MySQL/MySQLDatabase.cs b/src/Evolve/Dialect/MySQL/MySQLDatabase.cs
index 80b5d8c0..2198d07b 100644
--- a/src/Evolve/Dialect/MySQL/MySQLDatabase.cs
+++ b/src/Evolve/Dialect/MySQL/MySQLDatabase.cs
@@ -24,8 +24,8 @@ public MySQLDatabase(WrappedConnection wrappedConnection) : base(wrappedConnecti
public override Schema GetSchema(string schemaName) => new MySQLSchema(schemaName, WrappedConnection);
- public override bool TryAcquireApplicationLock() => WrappedConnection.QueryForLong($"SELECT GET_LOCK('{LOCK_ID}', 0);") == 1;
+ public override bool TryAcquireApplicationLock(object? lockId = null) => WrappedConnection.QueryForLong($"SELECT GET_LOCK('{lockId?? LOCK_ID}', 0);") == 1;
- public override bool ReleaseApplicationLock() => WrappedConnection.QueryForLong($"SELECT RELEASE_LOCK('{LOCK_ID}');") == 1;
+ public override bool ReleaseApplicationLock(object? lockId = null) => WrappedConnection.QueryForLong($"SELECT RELEASE_LOCK('{lockId ?? LOCK_ID}');") == 1;
}
}
diff --git a/src/Evolve/Dialect/PostgreSQL/PostgreSQLDatabase.cs b/src/Evolve/Dialect/PostgreSQL/PostgreSQLDatabase.cs
index 0570b133..2c7d9276 100644
--- a/src/Evolve/Dialect/PostgreSQL/PostgreSQLDatabase.cs
+++ b/src/Evolve/Dialect/PostgreSQL/PostgreSQLDatabase.cs
@@ -23,9 +23,9 @@ public PostgreSQLDatabase(WrappedConnection wrappedConnection) : base(wrappedCon
public override Schema GetSchema(string schemaName) => new PostgreSQLSchema(schemaName, WrappedConnection);
- public override bool TryAcquireApplicationLock() => WrappedConnection.QueryForBool($"SELECT pg_try_advisory_lock({LOCK_ID})");
+ public override bool TryAcquireApplicationLock(object? lockId = null) => WrappedConnection.QueryForBool($"SELECT pg_try_advisory_lock({lockId ?? LOCK_ID})");
- public override bool ReleaseApplicationLock() => WrappedConnection.QueryForBool($"SELECT pg_advisory_unlock({LOCK_ID})");
+ public override bool ReleaseApplicationLock(object? lockId = null) => WrappedConnection.QueryForBool($"SELECT pg_advisory_unlock({lockId ?? LOCK_ID})");
private string CleanSchemaName(string schemaName)
{
diff --git a/src/Evolve/Dialect/SQLServer/SQLServerDatabase.cs b/src/Evolve/Dialect/SQLServer/SQLServerDatabase.cs
index 9679dc5a..14c02e91 100644
--- a/src/Evolve/Dialect/SQLServer/SQLServerDatabase.cs
+++ b/src/Evolve/Dialect/SQLServer/SQLServerDatabase.cs
@@ -23,7 +23,7 @@ public SQLServerDatabase(WrappedConnection wrappedConnection) : base(wrappedConn
public override Schema GetSchema(string schemaName) => new SQLServerSchema(schemaName, WrappedConnection);
- public override bool TryAcquireApplicationLock()
+ public override bool TryAcquireApplicationLock(object? lockId = null)
{
return WrappedConnection.ExecuteDbCommand("sp_getapplock", cmd =>
{
@@ -37,7 +37,7 @@ public override bool TryAcquireApplicationLock()
var inParam1 = cmd.CreateParameter();
inParam1.ParameterName = "@Resource";
- inParam1.Value = LOCK_ID;
+ inParam1.Value = lockId ?? LOCK_ID;
inParam1.DbType = DbType.String;
inParam1.Direction = ParameterDirection.Input;
cmd.Parameters.Add(inParam1);
@@ -70,7 +70,7 @@ public override bool TryAcquireApplicationLock()
}) >= 0;
}
- public override bool ReleaseApplicationLock()
+ public override bool ReleaseApplicationLock(object? lockId = null)
{
return WrappedConnection.ExecuteDbCommand("sp_releaseapplock", cmd =>
{
@@ -84,7 +84,7 @@ public override bool ReleaseApplicationLock()
var inParam1 = cmd.CreateParameter();
inParam1.ParameterName = "@Resource";
- inParam1.Value = LOCK_ID;
+ inParam1.Value = lockId ?? LOCK_ID;
inParam1.DbType = DbType.String;
inParam1.Direction = ParameterDirection.Input;
cmd.Parameters.Add(inParam1);
diff --git a/src/Evolve/Dialect/SQLite/SQLiteDatabase.cs b/src/Evolve/Dialect/SQLite/SQLiteDatabase.cs
index 4af9bd74..ac14a847 100644
--- a/src/Evolve/Dialect/SQLite/SQLiteDatabase.cs
+++ b/src/Evolve/Dialect/SQLite/SQLiteDatabase.cs
@@ -26,12 +26,12 @@ public SQLiteDatabase(WrappedConnection wrappedConnection) : base(wrappedConnect
/// Not supported in SQLite.
///
/// Always true
- public override bool TryAcquireApplicationLock() => true;
+ public override bool TryAcquireApplicationLock(object? lockId = null) => true;
///
/// Not supported in SQLite.
///
/// Always true
- public override bool ReleaseApplicationLock() => true;
+ public override bool ReleaseApplicationLock(object? lockId = null) => true;
}
}
diff --git a/src/Evolve/Evolve.cs b/src/Evolve/Evolve.cs
index 64510adb..bfd80153 100644
--- a/src/Evolve/Evolve.cs
+++ b/src/Evolve/Evolve.cs
@@ -77,6 +77,7 @@ public string MetadataTableSchema
public bool RetryRepeatableMigrationsUntilNoError { get; set; }
public TransactionKind TransactionMode { get; set; } = TransactionKind.CommitEach;
public bool SkipNextMigrations { get; set; } = false;
+ public object? ApplicationLockId { get; set; } = null;
private IMigrationLoader? _migrationLoader;
public IMigrationLoader MigrationLoader
@@ -772,7 +773,7 @@ private void InternalExecuteCommand(Action commandAction)
if (EnableClusterMode)
{
var metadata = db.GetMetadataTable(MetadataTableSchema, MetadataTableName);
- if (!db.ReleaseApplicationLock() || !metadata.ReleaseLock())
+ if (!db.ReleaseApplicationLock(ApplicationLockId) || !metadata.ReleaseLock())
{
_log("Error trying to release Evolve lock.");
}
@@ -881,7 +882,7 @@ private void WaitForApplicationLock(DatabaseHelper db)
{
while (true)
{
- if (db.TryAcquireApplicationLock())
+ if (db.TryAcquireApplicationLock(ApplicationLockId))
{
break;
}
diff --git a/test/Evolve.Tests/Integration/PostgreSQL/Scenario010.cs b/test/Evolve.Tests/Integration/PostgreSQL/Scenario010.cs
new file mode 100644
index 00000000..d9a4a9c3
--- /dev/null
+++ b/test/Evolve.Tests/Integration/PostgreSQL/Scenario010.cs
@@ -0,0 +1,20 @@
+using EvolveDb.Tests.Infrastructure;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace EvolveDb.Tests.Integration.PostgreSql
+{
+ [Collection("PostgreSql collection")]
+ public class Scenario010 : Scenario
+ {
+ public Scenario010(PostgreSqlFixture dbContainer, ITestOutputHelper output) : base(dbContainer, output) {}
+
+ [Fact]
+ [Category(Test.PostgreSQL, Test.Sceanario)]
+ public void Scenario_lockIdSpecific()
+ {
+ Evolve.ApplicationLockId = 27893423;
+ Evolve.Migrate();
+ }
+ }
+}