diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props
index b65321ae..9158afbd 100644
--- a/src/Directory.Packages.props
+++ b/src/Directory.Packages.props
@@ -4,10 +4,10 @@
true
-
+
-
+
@@ -22,7 +22,7 @@
-
+
diff --git a/src/DistributedLock.Azure/packages.lock.json b/src/DistributedLock.Azure/packages.lock.json
index d1945781..a4c67c2f 100644
--- a/src/DistributedLock.Azure/packages.lock.json
+++ b/src/DistributedLock.Azure/packages.lock.json
@@ -29,13 +29,9 @@
},
"Microsoft.SourceLink.GitHub": {
"type": "Direct",
- "requested": "[8.0.0, )",
- "resolved": "8.0.0",
- "contentHash": "G5q7OqtwIyGTkeIOAc3u2ZuV/kicQaec5EaRnc0pIeSnh9LUjj+PYQrJYBURvDt7twGl2PKA7nSN0kz1Zw5bnQ==",
- "dependencies": {
- "Microsoft.Build.Tasks.Git": "8.0.0",
- "Microsoft.SourceLink.Common": "8.0.0"
- }
+ "requested": "[10.0.201, )",
+ "resolved": "10.0.201",
+ "contentHash": "qxYAmO4ktzd9L+HMdnqWucxpu7bI9undPyACXOMqPyhaiMtbpbYL/n0ACyWIJlbyEJrXFwxiOaBOSasLtDvsCg=="
},
"Azure.Core": {
"type": "Transitive",
@@ -62,21 +58,11 @@
"System.IO.Hashing": "6.0.0"
}
},
- "Microsoft.Build.Tasks.Git": {
- "type": "Transitive",
- "resolved": "8.0.0",
- "contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
- },
"Microsoft.NETFramework.ReferenceAssemblies.net462": {
"type": "Transitive",
"resolved": "1.0.3",
"contentHash": "IzAV30z22ESCeQfxP29oVf4qEo8fBGXLXSU6oacv/9Iqe6PzgHDKCaWfwMBak7bSJQM0F5boXWoZS+kChztRIQ=="
},
- "Microsoft.SourceLink.Common": {
- "type": "Transitive",
- "resolved": "8.0.0",
- "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
- },
"System.Buffers": {
"type": "Transitive",
"resolved": "4.5.1",
@@ -243,12 +229,13 @@
},
"Microsoft.SourceLink.GitHub": {
"type": "Direct",
- "requested": "[8.0.0, )",
- "resolved": "8.0.0",
- "contentHash": "G5q7OqtwIyGTkeIOAc3u2ZuV/kicQaec5EaRnc0pIeSnh9LUjj+PYQrJYBURvDt7twGl2PKA7nSN0kz1Zw5bnQ==",
+ "requested": "[10.0.201, )",
+ "resolved": "10.0.201",
+ "contentHash": "qxYAmO4ktzd9L+HMdnqWucxpu7bI9undPyACXOMqPyhaiMtbpbYL/n0ACyWIJlbyEJrXFwxiOaBOSasLtDvsCg==",
"dependencies": {
- "Microsoft.Build.Tasks.Git": "8.0.0",
- "Microsoft.SourceLink.Common": "8.0.0"
+ "Microsoft.Build.Tasks.Git": "10.0.201",
+ "Microsoft.SourceLink.Common": "10.0.201",
+ "System.IO.Hashing": "10.0.5"
}
},
"NETStandard.Library": {
@@ -285,8 +272,11 @@
},
"Microsoft.Build.Tasks.Git": {
"type": "Transitive",
- "resolved": "8.0.0",
- "contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
+ "resolved": "10.0.201",
+ "contentHash": "DMYBnrFZvLnBKn14VavEuuIr31CY6YY2i2L9P8DorS/Qp6ifRR8ZPLdJCFLFfjikNq8DykbYyLd/RP6lSqHcWw==",
+ "dependencies": {
+ "System.IO.Hashing": "10.0.5"
+ }
},
"Microsoft.NETCore.Platforms": {
"type": "Transitive",
@@ -295,13 +285,13 @@
},
"Microsoft.SourceLink.Common": {
"type": "Transitive",
- "resolved": "8.0.0",
- "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
+ "resolved": "10.0.201",
+ "contentHash": "QbBYhkjgL6rCnBfDbzsAJLlsad13TlBHqYCFDIw56OO2g6ix+9RsmY8uxiQGdWwFKbZXaXyAA6jDCzFYVGCZDw=="
},
"System.Buffers": {
"type": "Transitive",
- "resolved": "4.5.1",
- "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg=="
+ "resolved": "4.6.1",
+ "contentHash": "N8GXpmiLMtljq7gwvyS+1QvKT/W2J8sNAvx+HVg4NGmsG/H+2k/y9QI23auLJRterrzCiDH+IWAw4V/GPwsMlw=="
},
"System.Diagnostics.DiagnosticSource": {
"type": "Transitive",
@@ -314,21 +304,21 @@
},
"System.IO.Hashing": {
"type": "Transitive",
- "resolved": "6.0.0",
- "contentHash": "Rfm2jYCaUeGysFEZjDe7j1R4x6Z6BzumS/vUT5a1AA/AWJuGX71PoGB0RmpyX3VmrGqVnAwtfMn39OHR8Y/5+g==",
+ "resolved": "10.0.5",
+ "contentHash": "8IBJWcCT9+e4Bmevm4T7+fQEiAh133KGiz4oiVTgJckd3Q76OFdR1falgn9lpz7+C4HJvogCDJeAa2QmvbeVtg==",
"dependencies": {
- "System.Buffers": "4.5.1",
- "System.Memory": "4.5.4"
+ "System.Buffers": "4.6.1",
+ "System.Memory": "4.6.3"
}
},
"System.Memory": {
"type": "Transitive",
- "resolved": "4.5.4",
- "contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==",
+ "resolved": "4.6.3",
+ "contentHash": "qdcDOgnFZY40+Q9876JUHnlHu7bosOHX8XISRoH94fwk6hgaeQGSgfZd8srWRZNt5bV9ZW2TljcegDNxsf+96A==",
"dependencies": {
- "System.Buffers": "4.5.1",
- "System.Numerics.Vectors": "4.4.0",
- "System.Runtime.CompilerServices.Unsafe": "4.5.3"
+ "System.Buffers": "4.6.1",
+ "System.Numerics.Vectors": "4.6.1",
+ "System.Runtime.CompilerServices.Unsafe": "6.1.2"
}
},
"System.Memory.Data": {
@@ -342,13 +332,13 @@
},
"System.Numerics.Vectors": {
"type": "Transitive",
- "resolved": "4.5.0",
- "contentHash": "QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ=="
+ "resolved": "4.6.1",
+ "contentHash": "sQxefTnhagrhoq2ReR0D/6K0zJcr9Hrd6kikeXsA1I8kOCboTavcUC4r7TSfpKFeE163uMuxZcyfO1mGO3EN8Q=="
},
"System.Runtime.CompilerServices.Unsafe": {
"type": "Transitive",
- "resolved": "6.0.0",
- "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg=="
+ "resolved": "6.1.2",
+ "contentHash": "2hBr6zdbIBTDE3EhK7NSVNdX58uTK6iHW/P/Axmm9sl1xoGSLqDvMtpecn226TNwHByFokYwJmt/aQQNlO5CRw=="
},
"System.Text.Encodings.Web": {
"type": "Transitive",
@@ -416,12 +406,13 @@
},
"Microsoft.SourceLink.GitHub": {
"type": "Direct",
- "requested": "[8.0.0, )",
- "resolved": "8.0.0",
- "contentHash": "G5q7OqtwIyGTkeIOAc3u2ZuV/kicQaec5EaRnc0pIeSnh9LUjj+PYQrJYBURvDt7twGl2PKA7nSN0kz1Zw5bnQ==",
+ "requested": "[10.0.201, )",
+ "resolved": "10.0.201",
+ "contentHash": "qxYAmO4ktzd9L+HMdnqWucxpu7bI9undPyACXOMqPyhaiMtbpbYL/n0ACyWIJlbyEJrXFwxiOaBOSasLtDvsCg==",
"dependencies": {
- "Microsoft.Build.Tasks.Git": "8.0.0",
- "Microsoft.SourceLink.Common": "8.0.0"
+ "Microsoft.Build.Tasks.Git": "10.0.201",
+ "Microsoft.SourceLink.Common": "10.0.201",
+ "System.IO.Hashing": "10.0.5"
}
},
"Azure.Core": {
@@ -457,26 +448,29 @@
},
"Microsoft.Build.Tasks.Git": {
"type": "Transitive",
- "resolved": "8.0.0",
- "contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
+ "resolved": "10.0.201",
+ "contentHash": "DMYBnrFZvLnBKn14VavEuuIr31CY6YY2i2L9P8DorS/Qp6ifRR8ZPLdJCFLFfjikNq8DykbYyLd/RP6lSqHcWw==",
+ "dependencies": {
+ "System.IO.Hashing": "10.0.5"
+ }
},
"Microsoft.SourceLink.Common": {
"type": "Transitive",
- "resolved": "8.0.0",
- "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
+ "resolved": "10.0.201",
+ "contentHash": "QbBYhkjgL6rCnBfDbzsAJLlsad13TlBHqYCFDIw56OO2g6ix+9RsmY8uxiQGdWwFKbZXaXyAA6jDCzFYVGCZDw=="
},
"System.Buffers": {
"type": "Transitive",
- "resolved": "4.5.1",
- "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg=="
+ "resolved": "4.6.1",
+ "contentHash": "N8GXpmiLMtljq7gwvyS+1QvKT/W2J8sNAvx+HVg4NGmsG/H+2k/y9QI23auLJRterrzCiDH+IWAw4V/GPwsMlw=="
},
"System.IO.Hashing": {
"type": "Transitive",
- "resolved": "6.0.0",
- "contentHash": "Rfm2jYCaUeGysFEZjDe7j1R4x6Z6BzumS/vUT5a1AA/AWJuGX71PoGB0RmpyX3VmrGqVnAwtfMn39OHR8Y/5+g==",
+ "resolved": "10.0.5",
+ "contentHash": "8IBJWcCT9+e4Bmevm4T7+fQEiAh133KGiz4oiVTgJckd3Q76OFdR1falgn9lpz7+C4HJvogCDJeAa2QmvbeVtg==",
"dependencies": {
- "System.Buffers": "4.5.1",
- "System.Memory": "4.5.4"
+ "System.Buffers": "4.6.1",
+ "System.Memory": "4.6.3"
}
},
"System.Memory": {
@@ -535,9 +529,9 @@
},
"System.Diagnostics.DiagnosticSource": {
"type": "CentralTransitive",
- "requested": "[10.0.1, )",
- "resolved": "10.0.1",
- "contentHash": "wVYO4/71Pk177uQ3TG8ZQFS3Pnmr98cF9pYxnpuIb/bMnbEWsdZZoLU/euv29mfSi2/Iuypj0TRUchPk7aqBGg==",
+ "requested": "[10.0.5, )",
+ "resolved": "10.0.5",
+ "contentHash": "CCbzHQ26L3jskdwHh+4bxxW84lUMIrAAmeSlpO69AlrQV0DKbj1/I+feLaLSuZeqXPr9UlSy0OcgZoXOk2a6/g==",
"dependencies": {
"System.Memory": "4.6.3",
"System.Runtime.CompilerServices.Unsafe": "6.1.2"
diff --git a/src/DistributedLock.Core/packages.lock.json b/src/DistributedLock.Core/packages.lock.json
index 2f96fece..aead9bfa 100644
--- a/src/DistributedLock.Core/packages.lock.json
+++ b/src/DistributedLock.Core/packages.lock.json
@@ -11,12 +11,6 @@
"System.Threading.Tasks.Extensions": "4.5.4"
}
},
- "Microsoft.CodeAnalysis.PublicApiAnalyzers": {
- "type": "Direct",
- "requested": "[3.3.4, )",
- "resolved": "3.3.4",
- "contentHash": "kNLTfXtXUWDHVt5iaPkkiPuyHYlMgLI6SOFT4w88bfeI2vqSeGgHunFkdvlaCM8RDfcY0t2+jnesQtidRJJ/DA=="
- },
"Microsoft.NETFramework.ReferenceAssemblies": {
"type": "Direct",
"requested": "[1.0.3, )",
@@ -28,13 +22,9 @@
},
"Microsoft.SourceLink.GitHub": {
"type": "Direct",
- "requested": "[8.0.0, )",
- "resolved": "8.0.0",
- "contentHash": "G5q7OqtwIyGTkeIOAc3u2ZuV/kicQaec5EaRnc0pIeSnh9LUjj+PYQrJYBURvDt7twGl2PKA7nSN0kz1Zw5bnQ==",
- "dependencies": {
- "Microsoft.Build.Tasks.Git": "8.0.0",
- "Microsoft.SourceLink.Common": "8.0.0"
- }
+ "requested": "[10.0.201, )",
+ "resolved": "10.0.201",
+ "contentHash": "qxYAmO4ktzd9L+HMdnqWucxpu7bI9undPyACXOMqPyhaiMtbpbYL/n0ACyWIJlbyEJrXFwxiOaBOSasLtDvsCg=="
},
"System.ValueTuple": {
"type": "Direct",
@@ -42,21 +32,11 @@
"resolved": "4.5.0",
"contentHash": "okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ=="
},
- "Microsoft.Build.Tasks.Git": {
- "type": "Transitive",
- "resolved": "8.0.0",
- "contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
- },
"Microsoft.NETFramework.ReferenceAssemblies.net462": {
"type": "Transitive",
"resolved": "1.0.3",
"contentHash": "IzAV30z22ESCeQfxP29oVf4qEo8fBGXLXSU6oacv/9Iqe6PzgHDKCaWfwMBak7bSJQM0F5boXWoZS+kChztRIQ=="
},
- "Microsoft.SourceLink.Common": {
- "type": "Transitive",
- "resolved": "8.0.0",
- "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
- },
"System.Runtime.CompilerServices.Unsafe": {
"type": "Transitive",
"resolved": "4.5.3",
@@ -81,20 +61,15 @@
"System.Threading.Tasks.Extensions": "4.5.4"
}
},
- "Microsoft.CodeAnalysis.PublicApiAnalyzers": {
- "type": "Direct",
- "requested": "[3.3.4, )",
- "resolved": "3.3.4",
- "contentHash": "kNLTfXtXUWDHVt5iaPkkiPuyHYlMgLI6SOFT4w88bfeI2vqSeGgHunFkdvlaCM8RDfcY0t2+jnesQtidRJJ/DA=="
- },
"Microsoft.SourceLink.GitHub": {
"type": "Direct",
- "requested": "[8.0.0, )",
- "resolved": "8.0.0",
- "contentHash": "G5q7OqtwIyGTkeIOAc3u2ZuV/kicQaec5EaRnc0pIeSnh9LUjj+PYQrJYBURvDt7twGl2PKA7nSN0kz1Zw5bnQ==",
+ "requested": "[10.0.201, )",
+ "resolved": "10.0.201",
+ "contentHash": "qxYAmO4ktzd9L+HMdnqWucxpu7bI9undPyACXOMqPyhaiMtbpbYL/n0ACyWIJlbyEJrXFwxiOaBOSasLtDvsCg==",
"dependencies": {
- "Microsoft.Build.Tasks.Git": "8.0.0",
- "Microsoft.SourceLink.Common": "8.0.0"
+ "Microsoft.Build.Tasks.Git": "10.0.201",
+ "Microsoft.SourceLink.Common": "10.0.201",
+ "System.IO.Hashing": "10.0.5"
}
},
"NETStandard.Library": {
@@ -108,8 +83,11 @@
},
"Microsoft.Build.Tasks.Git": {
"type": "Transitive",
- "resolved": "8.0.0",
- "contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
+ "resolved": "10.0.201",
+ "contentHash": "DMYBnrFZvLnBKn14VavEuuIr31CY6YY2i2L9P8DorS/Qp6ifRR8ZPLdJCFLFfjikNq8DykbYyLd/RP6lSqHcWw==",
+ "dependencies": {
+ "System.IO.Hashing": "10.0.5"
+ }
},
"Microsoft.NETCore.Platforms": {
"type": "Transitive",
@@ -118,13 +96,42 @@
},
"Microsoft.SourceLink.Common": {
"type": "Transitive",
- "resolved": "8.0.0",
- "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
+ "resolved": "10.0.201",
+ "contentHash": "QbBYhkjgL6rCnBfDbzsAJLlsad13TlBHqYCFDIw56OO2g6ix+9RsmY8uxiQGdWwFKbZXaXyAA6jDCzFYVGCZDw=="
+ },
+ "System.Buffers": {
+ "type": "Transitive",
+ "resolved": "4.6.1",
+ "contentHash": "N8GXpmiLMtljq7gwvyS+1QvKT/W2J8sNAvx+HVg4NGmsG/H+2k/y9QI23auLJRterrzCiDH+IWAw4V/GPwsMlw=="
+ },
+ "System.IO.Hashing": {
+ "type": "Transitive",
+ "resolved": "10.0.5",
+ "contentHash": "8IBJWcCT9+e4Bmevm4T7+fQEiAh133KGiz4oiVTgJckd3Q76OFdR1falgn9lpz7+C4HJvogCDJeAa2QmvbeVtg==",
+ "dependencies": {
+ "System.Buffers": "4.6.1",
+ "System.Memory": "4.6.3"
+ }
+ },
+ "System.Memory": {
+ "type": "Transitive",
+ "resolved": "4.6.3",
+ "contentHash": "qdcDOgnFZY40+Q9876JUHnlHu7bosOHX8XISRoH94fwk6hgaeQGSgfZd8srWRZNt5bV9ZW2TljcegDNxsf+96A==",
+ "dependencies": {
+ "System.Buffers": "4.6.1",
+ "System.Numerics.Vectors": "4.6.1",
+ "System.Runtime.CompilerServices.Unsafe": "6.1.2"
+ }
+ },
+ "System.Numerics.Vectors": {
+ "type": "Transitive",
+ "resolved": "4.6.1",
+ "contentHash": "sQxefTnhagrhoq2ReR0D/6K0zJcr9Hrd6kikeXsA1I8kOCboTavcUC4r7TSfpKFeE163uMuxZcyfO1mGO3EN8Q=="
},
"System.Runtime.CompilerServices.Unsafe": {
"type": "Transitive",
- "resolved": "4.5.3",
- "contentHash": "3TIsJhD1EiiT0w2CcDMN/iSSwnNnsrnbzeVHSKkaEgV85txMprmuO+Yq2AdSbeVGcg28pdNDTPK87tJhX7VFHw=="
+ "resolved": "6.1.2",
+ "contentHash": "2hBr6zdbIBTDE3EhK7NSVNdX58uTK6iHW/P/Axmm9sl1xoGSLqDvMtpecn226TNwHByFokYwJmt/aQQNlO5CRw=="
},
"System.Threading.Tasks.Extensions": {
"type": "Transitive",
@@ -136,65 +143,85 @@
}
},
".NETStandard,Version=v2.1": {
- "Microsoft.CodeAnalysis.PublicApiAnalyzers": {
- "type": "Direct",
- "requested": "[3.3.4, )",
- "resolved": "3.3.4",
- "contentHash": "kNLTfXtXUWDHVt5iaPkkiPuyHYlMgLI6SOFT4w88bfeI2vqSeGgHunFkdvlaCM8RDfcY0t2+jnesQtidRJJ/DA=="
- },
"Microsoft.SourceLink.GitHub": {
"type": "Direct",
- "requested": "[8.0.0, )",
- "resolved": "8.0.0",
- "contentHash": "G5q7OqtwIyGTkeIOAc3u2ZuV/kicQaec5EaRnc0pIeSnh9LUjj+PYQrJYBURvDt7twGl2PKA7nSN0kz1Zw5bnQ==",
+ "requested": "[10.0.201, )",
+ "resolved": "10.0.201",
+ "contentHash": "qxYAmO4ktzd9L+HMdnqWucxpu7bI9undPyACXOMqPyhaiMtbpbYL/n0ACyWIJlbyEJrXFwxiOaBOSasLtDvsCg==",
"dependencies": {
- "Microsoft.Build.Tasks.Git": "8.0.0",
- "Microsoft.SourceLink.Common": "8.0.0"
+ "Microsoft.Build.Tasks.Git": "10.0.201",
+ "Microsoft.SourceLink.Common": "10.0.201",
+ "System.IO.Hashing": "10.0.5"
}
},
"Microsoft.Build.Tasks.Git": {
"type": "Transitive",
- "resolved": "8.0.0",
- "contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
+ "resolved": "10.0.201",
+ "contentHash": "DMYBnrFZvLnBKn14VavEuuIr31CY6YY2i2L9P8DorS/Qp6ifRR8ZPLdJCFLFfjikNq8DykbYyLd/RP6lSqHcWw==",
+ "dependencies": {
+ "System.IO.Hashing": "10.0.5"
+ }
},
"Microsoft.SourceLink.Common": {
"type": "Transitive",
- "resolved": "8.0.0",
- "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
+ "resolved": "10.0.201",
+ "contentHash": "QbBYhkjgL6rCnBfDbzsAJLlsad13TlBHqYCFDIw56OO2g6ix+9RsmY8uxiQGdWwFKbZXaXyAA6jDCzFYVGCZDw=="
+ },
+ "System.Buffers": {
+ "type": "Transitive",
+ "resolved": "4.6.1",
+ "contentHash": "N8GXpmiLMtljq7gwvyS+1QvKT/W2J8sNAvx+HVg4NGmsG/H+2k/y9QI23auLJRterrzCiDH+IWAw4V/GPwsMlw=="
+ },
+ "System.IO.Hashing": {
+ "type": "Transitive",
+ "resolved": "10.0.5",
+ "contentHash": "8IBJWcCT9+e4Bmevm4T7+fQEiAh133KGiz4oiVTgJckd3Q76OFdR1falgn9lpz7+C4HJvogCDJeAa2QmvbeVtg==",
+ "dependencies": {
+ "System.Buffers": "4.6.1",
+ "System.Memory": "4.6.3"
+ }
+ },
+ "System.Memory": {
+ "type": "Transitive",
+ "resolved": "4.6.3",
+ "contentHash": "qdcDOgnFZY40+Q9876JUHnlHu7bosOHX8XISRoH94fwk6hgaeQGSgfZd8srWRZNt5bV9ZW2TljcegDNxsf+96A=="
}
},
"net8.0": {
- "Microsoft.CodeAnalysis.PublicApiAnalyzers": {
- "type": "Direct",
- "requested": "[3.3.4, )",
- "resolved": "3.3.4",
- "contentHash": "kNLTfXtXUWDHVt5iaPkkiPuyHYlMgLI6SOFT4w88bfeI2vqSeGgHunFkdvlaCM8RDfcY0t2+jnesQtidRJJ/DA=="
- },
"Microsoft.NET.ILLink.Tasks": {
"type": "Direct",
- "requested": "[8.0.4, )",
- "resolved": "8.0.4",
- "contentHash": "PZb5nfQ+U19nhnmnR9T1jw+LTmozhuG2eeuzuW5A7DqxD/UXW2ucjmNJqnqOuh8rdPzM3MQXoF8AfFCedJdCUw=="
+ "requested": "[8.0.24, )",
+ "resolved": "8.0.24",
+ "contentHash": "1gnadp//+DoGJvV4AFdzPqYPxkypaWYjYMCr7KAacV0iadsHz1nU+rrkoxBCna4FCmeKH49CisEwa7g94/MbEg=="
},
"Microsoft.SourceLink.GitHub": {
"type": "Direct",
- "requested": "[8.0.0, )",
- "resolved": "8.0.0",
- "contentHash": "G5q7OqtwIyGTkeIOAc3u2ZuV/kicQaec5EaRnc0pIeSnh9LUjj+PYQrJYBURvDt7twGl2PKA7nSN0kz1Zw5bnQ==",
+ "requested": "[10.0.201, )",
+ "resolved": "10.0.201",
+ "contentHash": "qxYAmO4ktzd9L+HMdnqWucxpu7bI9undPyACXOMqPyhaiMtbpbYL/n0ACyWIJlbyEJrXFwxiOaBOSasLtDvsCg==",
"dependencies": {
- "Microsoft.Build.Tasks.Git": "8.0.0",
- "Microsoft.SourceLink.Common": "8.0.0"
+ "Microsoft.Build.Tasks.Git": "10.0.201",
+ "Microsoft.SourceLink.Common": "10.0.201",
+ "System.IO.Hashing": "10.0.5"
}
},
"Microsoft.Build.Tasks.Git": {
"type": "Transitive",
- "resolved": "8.0.0",
- "contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
+ "resolved": "10.0.201",
+ "contentHash": "DMYBnrFZvLnBKn14VavEuuIr31CY6YY2i2L9P8DorS/Qp6ifRR8ZPLdJCFLFfjikNq8DykbYyLd/RP6lSqHcWw==",
+ "dependencies": {
+ "System.IO.Hashing": "10.0.5"
+ }
},
"Microsoft.SourceLink.Common": {
"type": "Transitive",
- "resolved": "8.0.0",
- "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
+ "resolved": "10.0.201",
+ "contentHash": "QbBYhkjgL6rCnBfDbzsAJLlsad13TlBHqYCFDIw56OO2g6ix+9RsmY8uxiQGdWwFKbZXaXyAA6jDCzFYVGCZDw=="
+ },
+ "System.IO.Hashing": {
+ "type": "Transitive",
+ "resolved": "10.0.5",
+ "contentHash": "8IBJWcCT9+e4Bmevm4T7+fQEiAh133KGiz4oiVTgJckd3Q76OFdR1falgn9lpz7+C4HJvogCDJeAa2QmvbeVtg=="
}
}
}
diff --git a/src/DistributedLock.FileSystem/packages.lock.json b/src/DistributedLock.FileSystem/packages.lock.json
index adc5221f..bdf49de5 100644
--- a/src/DistributedLock.FileSystem/packages.lock.json
+++ b/src/DistributedLock.FileSystem/packages.lock.json
@@ -19,13 +19,9 @@
},
"Microsoft.SourceLink.GitHub": {
"type": "Direct",
- "requested": "[8.0.0, )",
- "resolved": "8.0.0",
- "contentHash": "G5q7OqtwIyGTkeIOAc3u2ZuV/kicQaec5EaRnc0pIeSnh9LUjj+PYQrJYBURvDt7twGl2PKA7nSN0kz1Zw5bnQ==",
- "dependencies": {
- "Microsoft.Build.Tasks.Git": "8.0.0",
- "Microsoft.SourceLink.Common": "8.0.0"
- }
+ "requested": "[10.0.201, )",
+ "resolved": "10.0.201",
+ "contentHash": "qxYAmO4ktzd9L+HMdnqWucxpu7bI9undPyACXOMqPyhaiMtbpbYL/n0ACyWIJlbyEJrXFwxiOaBOSasLtDvsCg=="
},
"Nullable": {
"type": "Direct",
@@ -33,21 +29,11 @@
"resolved": "1.3.1",
"contentHash": "Mk4ZVDfAORTjvckQprCSehi1XgOAAlk5ez06Va/acRYEloN9t6d6zpzJRn5MEq7+RnagyFIq9r+kbWzLGd+6QA=="
},
- "Microsoft.Build.Tasks.Git": {
- "type": "Transitive",
- "resolved": "8.0.0",
- "contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
- },
"Microsoft.NETFramework.ReferenceAssemblies.net462": {
"type": "Transitive",
"resolved": "1.0.3",
"contentHash": "IzAV30z22ESCeQfxP29oVf4qEo8fBGXLXSU6oacv/9Iqe6PzgHDKCaWfwMBak7bSJQM0F5boXWoZS+kChztRIQ=="
},
- "Microsoft.SourceLink.Common": {
- "type": "Transitive",
- "resolved": "8.0.0",
- "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
- },
"System.Runtime.CompilerServices.Unsafe": {
"type": "Transitive",
"resolved": "4.5.3",
@@ -93,12 +79,13 @@
},
"Microsoft.SourceLink.GitHub": {
"type": "Direct",
- "requested": "[8.0.0, )",
- "resolved": "8.0.0",
- "contentHash": "G5q7OqtwIyGTkeIOAc3u2ZuV/kicQaec5EaRnc0pIeSnh9LUjj+PYQrJYBURvDt7twGl2PKA7nSN0kz1Zw5bnQ==",
+ "requested": "[10.0.201, )",
+ "resolved": "10.0.201",
+ "contentHash": "qxYAmO4ktzd9L+HMdnqWucxpu7bI9undPyACXOMqPyhaiMtbpbYL/n0ACyWIJlbyEJrXFwxiOaBOSasLtDvsCg==",
"dependencies": {
- "Microsoft.Build.Tasks.Git": "8.0.0",
- "Microsoft.SourceLink.Common": "8.0.0"
+ "Microsoft.Build.Tasks.Git": "10.0.201",
+ "Microsoft.SourceLink.Common": "10.0.201",
+ "System.IO.Hashing": "10.0.5"
}
},
"NETStandard.Library": {
@@ -118,8 +105,11 @@
},
"Microsoft.Build.Tasks.Git": {
"type": "Transitive",
- "resolved": "8.0.0",
- "contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
+ "resolved": "10.0.201",
+ "contentHash": "DMYBnrFZvLnBKn14VavEuuIr31CY6YY2i2L9P8DorS/Qp6ifRR8ZPLdJCFLFfjikNq8DykbYyLd/RP6lSqHcWw==",
+ "dependencies": {
+ "System.IO.Hashing": "10.0.5"
+ }
},
"Microsoft.NETCore.Platforms": {
"type": "Transitive",
@@ -128,13 +118,42 @@
},
"Microsoft.SourceLink.Common": {
"type": "Transitive",
- "resolved": "8.0.0",
- "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
+ "resolved": "10.0.201",
+ "contentHash": "QbBYhkjgL6rCnBfDbzsAJLlsad13TlBHqYCFDIw56OO2g6ix+9RsmY8uxiQGdWwFKbZXaXyAA6jDCzFYVGCZDw=="
+ },
+ "System.Buffers": {
+ "type": "Transitive",
+ "resolved": "4.6.1",
+ "contentHash": "N8GXpmiLMtljq7gwvyS+1QvKT/W2J8sNAvx+HVg4NGmsG/H+2k/y9QI23auLJRterrzCiDH+IWAw4V/GPwsMlw=="
+ },
+ "System.IO.Hashing": {
+ "type": "Transitive",
+ "resolved": "10.0.5",
+ "contentHash": "8IBJWcCT9+e4Bmevm4T7+fQEiAh133KGiz4oiVTgJckd3Q76OFdR1falgn9lpz7+C4HJvogCDJeAa2QmvbeVtg==",
+ "dependencies": {
+ "System.Buffers": "4.6.1",
+ "System.Memory": "4.6.3"
+ }
+ },
+ "System.Memory": {
+ "type": "Transitive",
+ "resolved": "4.6.3",
+ "contentHash": "qdcDOgnFZY40+Q9876JUHnlHu7bosOHX8XISRoH94fwk6hgaeQGSgfZd8srWRZNt5bV9ZW2TljcegDNxsf+96A==",
+ "dependencies": {
+ "System.Buffers": "4.6.1",
+ "System.Numerics.Vectors": "4.6.1",
+ "System.Runtime.CompilerServices.Unsafe": "6.1.2"
+ }
+ },
+ "System.Numerics.Vectors": {
+ "type": "Transitive",
+ "resolved": "4.6.1",
+ "contentHash": "sQxefTnhagrhoq2ReR0D/6K0zJcr9Hrd6kikeXsA1I8kOCboTavcUC4r7TSfpKFeE163uMuxZcyfO1mGO3EN8Q=="
},
"System.Runtime.CompilerServices.Unsafe": {
"type": "Transitive",
- "resolved": "4.5.3",
- "contentHash": "3TIsJhD1EiiT0w2CcDMN/iSSwnNnsrnbzeVHSKkaEgV85txMprmuO+Yq2AdSbeVGcg28pdNDTPK87tJhX7VFHw=="
+ "resolved": "6.1.2",
+ "contentHash": "2hBr6zdbIBTDE3EhK7NSVNdX58uTK6iHW/P/Axmm9sl1xoGSLqDvMtpecn226TNwHByFokYwJmt/aQQNlO5CRw=="
},
"System.Threading.Tasks.Extensions": {
"type": "Transitive",
@@ -169,23 +188,46 @@
},
"Microsoft.SourceLink.GitHub": {
"type": "Direct",
- "requested": "[8.0.0, )",
- "resolved": "8.0.0",
- "contentHash": "G5q7OqtwIyGTkeIOAc3u2ZuV/kicQaec5EaRnc0pIeSnh9LUjj+PYQrJYBURvDt7twGl2PKA7nSN0kz1Zw5bnQ==",
+ "requested": "[10.0.201, )",
+ "resolved": "10.0.201",
+ "contentHash": "qxYAmO4ktzd9L+HMdnqWucxpu7bI9undPyACXOMqPyhaiMtbpbYL/n0ACyWIJlbyEJrXFwxiOaBOSasLtDvsCg==",
"dependencies": {
- "Microsoft.Build.Tasks.Git": "8.0.0",
- "Microsoft.SourceLink.Common": "8.0.0"
+ "Microsoft.Build.Tasks.Git": "10.0.201",
+ "Microsoft.SourceLink.Common": "10.0.201",
+ "System.IO.Hashing": "10.0.5"
}
},
"Microsoft.Build.Tasks.Git": {
"type": "Transitive",
- "resolved": "8.0.0",
- "contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
+ "resolved": "10.0.201",
+ "contentHash": "DMYBnrFZvLnBKn14VavEuuIr31CY6YY2i2L9P8DorS/Qp6ifRR8ZPLdJCFLFfjikNq8DykbYyLd/RP6lSqHcWw==",
+ "dependencies": {
+ "System.IO.Hashing": "10.0.5"
+ }
},
"Microsoft.SourceLink.Common": {
"type": "Transitive",
- "resolved": "8.0.0",
- "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
+ "resolved": "10.0.201",
+ "contentHash": "QbBYhkjgL6rCnBfDbzsAJLlsad13TlBHqYCFDIw56OO2g6ix+9RsmY8uxiQGdWwFKbZXaXyAA6jDCzFYVGCZDw=="
+ },
+ "System.Buffers": {
+ "type": "Transitive",
+ "resolved": "4.6.1",
+ "contentHash": "N8GXpmiLMtljq7gwvyS+1QvKT/W2J8sNAvx+HVg4NGmsG/H+2k/y9QI23auLJRterrzCiDH+IWAw4V/GPwsMlw=="
+ },
+ "System.IO.Hashing": {
+ "type": "Transitive",
+ "resolved": "10.0.5",
+ "contentHash": "8IBJWcCT9+e4Bmevm4T7+fQEiAh133KGiz4oiVTgJckd3Q76OFdR1falgn9lpz7+C4HJvogCDJeAa2QmvbeVtg==",
+ "dependencies": {
+ "System.Buffers": "4.6.1",
+ "System.Memory": "4.6.3"
+ }
+ },
+ "System.Memory": {
+ "type": "Transitive",
+ "resolved": "4.6.3",
+ "contentHash": "qdcDOgnFZY40+Q9876JUHnlHu7bosOHX8XISRoH94fwk6hgaeQGSgfZd8srWRZNt5bV9ZW2TljcegDNxsf+96A=="
},
"distributedlock.core": {
"type": "Project"
diff --git a/src/DistributedLock.MongoDB/MongoDistributedLock.cs b/src/DistributedLock.MongoDB/MongoDistributedLock.cs
index 536766cd..272802d8 100644
--- a/src/DistributedLock.MongoDB/MongoDistributedLock.cs
+++ b/src/DistributedLock.MongoDB/MongoDistributedLock.cs
@@ -1,7 +1,6 @@
using Medallion.Threading.Internal;
using MongoDB.Bson;
using MongoDB.Driver;
-using System.Collections.Concurrent;
using System.Diagnostics;
namespace Medallion.Threading.MongoDB;
@@ -22,8 +21,30 @@ public sealed partial class MongoDistributedLock : IInternalDistributedLock> _collection;
+
+ // Shared read-only BsonDocument sub-expressions cached to reduce GC pressure on hot paths.
+ // BsonDocument is mutable; these instances must never be modified after initialization.
+ private static readonly BsonDocument ExpiredOrMissingExpr = new(
+ "$lte",
+ new BsonArray
+ {
+ new BsonDocument("$ifNull", new BsonArray { "$expiresAt", new BsonDateTime(EpochUtc) }),
+ "$$NOW"
+ }
+ );
+
+ private static readonly BsonDocument NewFencingTokenExpr = new(
+ "$add",
+ new BsonArray
+ {
+ new BsonDocument("$ifNull", new BsonArray { "$fencingToken", 0L }),
+ 1L
+ }
+ );
+
+ private readonly BsonDocument _newExpiresAtExpr;
///
/// The MongoDB key used to implement the lock
@@ -47,14 +68,27 @@ public MongoDistributedLock(string key, IMongoDatabase database, Action.
///
public MongoDistributedLock(string key, IMongoDatabase database, string collectionName, Action? options = null)
+ : this(key, database, collectionName, MongoDistributedSynchronizationOptionsBuilder.GetOptions(options)) { }
+
+ internal MongoDistributedLock(string key, IMongoDatabase database, string collectionName, MongoDistributedLockOptions options)
{
- this._database = database ?? throw new ArgumentNullException(nameof(database));
+ var validatedDatabase = database ?? throw new ArgumentNullException(nameof(database));
this._collectionName = collectionName ?? throw new ArgumentNullException(nameof(collectionName));
// From what I can tell, modern (and all supported) MongoDB versions have no limits on index keys or
// _id lengths other than the 16MB document limit. This is so high that providing "safe name" functionality as a fallback doesn't
// see worth it.
this.Key = key ?? throw new ArgumentNullException(nameof(key));
- this._options = MongoDistributedSynchronizationOptionsBuilder.GetOptions(options);
+ this._options = options;
+ this._collection = new(() => validatedDatabase.GetCollection(this._collectionName));
+ this._newExpiresAtExpr = new BsonDocument(
+ "$dateAdd",
+ new BsonDocument
+ {
+ { "startDate", "$$NOW" },
+ { "unit", "millisecond" },
+ { "amount", this._options.Expiry.InMilliseconds }
+ }
+ );
}
ValueTask IInternalDistributedLock.InternalTryAcquireAsync(TimeoutValue timeout, CancellationToken cancellationToken) =>
@@ -71,16 +105,16 @@ public MongoDistributedLock(string key, IMongoDatabase database, string collecti
activity?.SetTag("lock.key", this.Key);
activity?.SetTag("lock.collection", this._collectionName);
- var collection = this._database.GetCollection(this._collectionName);
-
// Use a unique token per acquisition attempt (like Redis' value token)
var lockId = Guid.NewGuid().ToString("N");
-
+
+ var collection = this._collection.Value;
+
// We avoid exception-driven contention (DuplicateKey) by using a single upsert on {_id == Key}
// and an update pipeline that only overwrites fields when the existing lock is expired.
// This is conceptually similar to Redis: SET key value NX PX .
var filter = Builders.Filter.Eq(d => d.Id, this.Key);
- var update = CreateAcquireUpdate(lockId, this._options.Expiry);
+ var update = this.CreateAcquireUpdate(lockId);
var options = new FindOneAndUpdateOptions
{
IsUpsert = true,
@@ -94,6 +128,8 @@ public MongoDistributedLock(string key, IMongoDatabase database, string collecti
// Verify we actually got the lock
if (result?.LockId == lockId)
{
+ // Fire-and-forget TTL index creation only on successful acquire to avoid
+ // unnecessary DB calls when the lock is contended.
_ = IndexInitializer.InitializeTtlIndex(collection);
activity?.SetTag("lock.acquired", true);
activity?.SetTag("lock.fencing_token", result.FencingToken);
@@ -103,49 +139,19 @@ public MongoDistributedLock(string key, IMongoDatabase database, string collecti
return null;
}
- private static UpdateDefinition CreateAcquireUpdate(string lockId, TimeoutValue expiry)
+ private UpdateDefinition CreateAcquireUpdate(string lockId)
{
- Invariant.Require(!expiry.IsInfinite);
-
- // expired := ifNull(expiresAt, epoch) <= $$NOW
- var expiredOrMissing = new BsonDocument(
- "$lte",
- new BsonArray
- {
- new BsonDocument("$ifNull", new BsonArray { "$expiresAt", new BsonDateTime(EpochUtc) }),
- "$$NOW"
- }
- );
-
- var newExpiresAt = new BsonDocument(
- "$dateAdd",
- new BsonDocument
- {
- { "startDate", "$$NOW" },
- { "unit", "millisecond" },
- { "amount", expiry.InMilliseconds }
- }
- );
-
- // Increment fencing token only when acquiring a new lock
- var newFencingToken = new BsonDocument(
- "$add",
- new BsonArray
- {
- new BsonDocument("$ifNull", new BsonArray { "$fencingToken", 0L }),
- 1L
- }
- );
-
+ // ExpiredOrMissingExpr, _newExpiresAtExpr, and NewFencingTokenExpr are pre-cached
+ // immutable BsonDocuments to reduce allocations on the busy-wait hot path.
var setStage = new BsonDocument(
"$set",
new BsonDocument
{
// Only overwrite lock fields when the previous lock is expired/missing
- { nameof(lockId), new BsonDocument("$cond", new BsonArray { expiredOrMissing, lockId, "$lockId" }) },
- { "expiresAt", new BsonDocument("$cond", new BsonArray { expiredOrMissing, newExpiresAt, "$expiresAt" }) },
- { "acquiredAt", new BsonDocument("$cond", new BsonArray { expiredOrMissing, "$$NOW", "$acquiredAt" }) },
- { "fencingToken", new BsonDocument("$cond", new BsonArray { expiredOrMissing, newFencingToken, "$fencingToken" }) }
+ { nameof(lockId), new BsonDocument("$cond", new BsonArray { ExpiredOrMissingExpr, lockId, "$lockId" }) },
+ { "expiresAt", new BsonDocument("$cond", new BsonArray { ExpiredOrMissingExpr, this._newExpiresAtExpr, "$expiresAt" }) },
+ { "acquiredAt", new BsonDocument("$cond", new BsonArray { ExpiredOrMissingExpr, "$$NOW", "$acquiredAt" }) },
+ { "fencingToken", new BsonDocument("$cond", new BsonArray { ExpiredOrMissingExpr, NewFencingTokenExpr, "$fencingToken" }) }
}
);
@@ -159,10 +165,13 @@ private static UpdateDefinition CreateAcquireUpdate(string lo
internal sealed class InnerHandle : IAsyncDisposable, LeaseMonitor.ILeaseHandle
{
private readonly MongoDistributedLock _lock;
- private readonly string _lockId;
private readonly IMongoCollection _collection;
private readonly LeaseMonitor _monitor;
-
+
+ // Cached filter and update definitions to avoid repeated allocations during renewal cycles
+ private readonly FilterDefinition _ownerFilter;
+ private readonly PipelineUpdateDefinition _renewUpdate;
+
public CancellationToken HandleLostToken => this._monitor.HandleLostToken;
TimeoutValue LeaseMonitor.ILeaseHandle.LeaseDuration => this._lock._options.Expiry;
@@ -171,8 +180,17 @@ internal sealed class InnerHandle : IAsyncDisposable, LeaseMonitor.ILeaseHandle
public InnerHandle(MongoDistributedLock @lock, string lockId, IMongoCollection collection)
{
this._lock = @lock;
- this._lockId = lockId;
this._collection = collection;
+
+ // Cache the filter that identifies this specific lock ownership
+ this._ownerFilter = Builders.Filter.Eq(d => d.Id, @lock.Key)
+ & Builders.Filter.Eq(d => d.LockId, lockId);
+
+ // Cache the renewal update pipeline (expiry is fixed for the lock's lifetime)
+ this._renewUpdate = new PipelineUpdateDefinition(
+ new[] { new BsonDocument("$set", new BsonDocument("expiresAt", @lock._newExpiresAtExpr)) }
+ );
+
// important to set this last, since the monitor constructor will read other fields of this
this._monitor = new(this);
}
@@ -185,36 +203,31 @@ public async ValueTask DisposeAsync()
private async ValueTask ReleaseLockAsync()
{
- var filter = Builders.Filter.Eq(d => d.Id, this._lock.Key) & Builders.Filter.Eq(d => d.LockId, this._lockId);
- if (SyncViaAsync.IsSynchronous)
+ try
{
- this._collection.DeleteOne(filter);
+ if (SyncViaAsync.IsSynchronous)
+ {
+ // ReSharper disable once MethodHasAsyncOverload
+ this._collection.DeleteOne(this._ownerFilter);
+ }
+ else
+ {
+ // Do not use HandleLostToken here: the monitor (and its CancellationTokenSource) is
+ // already disposed before ReleaseLockAsync is called from DisposeAsync.
+ await this._collection.DeleteOneAsync(this._ownerFilter, CancellationToken.None).ConfigureAwait(false);
+ }
}
- else
+ catch (Exception ex) when (ex is MongoException or TimeoutException or OperationCanceledException)
{
- await this._collection.DeleteOneAsync(filter).ConfigureAwait(false);
+ // Release failure is non-fatal: the TTL index will eventually clean up expired documents.
+ // Swallowing only expected network/write/cancellation failures prevents surprising callers
+ // during Dispose without hiding programming errors (e.g. ArgumentException).
}
}
async Task LeaseMonitor.ILeaseHandle.RenewOrValidateLeaseAsync(CancellationToken cancellationToken)
{
- var filter = Builders.Filter.Eq(d => d.Id, this._lock.Key) & Builders.Filter.Eq(d => d.LockId, this._lockId);
-
- // Use server time ($$NOW) for expiry to avoid client clock skew.
- var newExpiresAt = new BsonDocument(
- "$dateAdd",
- new BsonDocument
- {
- { "startDate", "$$NOW" },
- { "unit", "millisecond" },
- { "amount", this._lock._options.Expiry.InMilliseconds }
- }
- );
- var update = new PipelineUpdateDefinition(
- new[] { new BsonDocument("$set", new BsonDocument("expiresAt", newExpiresAt)) }
- );
-
- var result = await this._collection.UpdateOneAsync(filter, update, cancellationToken: cancellationToken).ConfigureAwait(false);
+ var result = await this._collection.UpdateOneAsync(this._ownerFilter, this._renewUpdate, cancellationToken: cancellationToken).ConfigureAwait(false);
return result.MatchedCount > 0 ? LeaseMonitor.LeaseState.Renewed : LeaseMonitor.LeaseState.Lost;
}
}
diff --git a/src/DistributedLock.MongoDB/MongoDistributedSynchronizationProvider.cs b/src/DistributedLock.MongoDB/MongoDistributedSynchronizationProvider.cs
index 05a00035..32a8ec67 100644
--- a/src/DistributedLock.MongoDB/MongoDistributedSynchronizationProvider.cs
+++ b/src/DistributedLock.MongoDB/MongoDistributedSynchronizationProvider.cs
@@ -9,7 +9,7 @@ public sealed class MongoDistributedSynchronizationProvider : IDistributedLockPr
{
private readonly string _collectionName;
private readonly IMongoDatabase _database;
- private readonly Action? _options;
+ private readonly MongoDistributedLockOptions _options;
///
/// Constructs a that connects to the provided
@@ -26,7 +26,7 @@ public MongoDistributedSynchronizationProvider(IMongoDatabase database, string c
{
this._database = database ?? throw new ArgumentNullException(nameof(database));
this._collectionName = collectionName ?? throw new ArgumentNullException(nameof(collectionName));
- this._options = options;
+ this._options = MongoDistributedSynchronizationOptionsBuilder.GetOptions(options);
}
///
diff --git a/src/DistributedLock.MongoDB/MongoIndexInitializer.cs b/src/DistributedLock.MongoDB/MongoIndexInitializer.cs
index 8a799fd8..021c2bba 100644
--- a/src/DistributedLock.MongoDB/MongoIndexInitializer.cs
+++ b/src/DistributedLock.MongoDB/MongoIndexInitializer.cs
@@ -1,8 +1,9 @@
-using MongoDB.Driver;
+using MongoDB.Driver;
using System.Collections.Concurrent;
namespace Medallion.Threading.MongoDB;
+// ReSharper disable once ClassWithVirtualMembersNeverInherited.Global
internal class MongoIndexInitializer
{
private const string IndexName = "expiresAt_ttl";
@@ -40,7 +41,7 @@ public Task InitializeTtlIndex(IMongoCollection collection)
private async Task CreateIndexIfNotExistsWrapperAsync(IMongoCollection collection)
{
- if (await this.CreateIndexIfNotExistsAsync(collection).ConfigureAwait(false) is { } result)
+ if (await CreateIndexIfNotExistsAsync(collection).ConfigureAwait(false) is { } result)
{
return result;
}
@@ -54,7 +55,7 @@ public Task InitializeTtlIndex(IMongoCollection collection)
// exposed for mocking
internal virtual Task DelayBeforeRetry() => Task.Delay(TimeSpan.FromMinutes(1));
- private async Task CreateIndexIfNotExistsAsync(IMongoCollection collection)
+ private static async Task CreateIndexIfNotExistsAsync(IMongoCollection collection)
{
using var activity = MongoDistributedLock.ActivitySource.StartActivity(nameof(MongoIndexInitializer) + ".CreateIndexIfNotExists");
activity?.AddTag("collection", collection.CollectionNamespace.FullName);
@@ -122,12 +123,13 @@ internal static async Task CheckIfIndexExists(IMongoCollection