diff --git a/.editorconfig b/.editorconfig index e2f0c4ea8..ee08af36d 100644 --- a/.editorconfig +++ b/.editorconfig @@ -10,6 +10,9 @@ dotnet_analyzer_diagnostic.severity = error # Namespace does not match folder structure - Ideally this should be enabled but it seems to have issues with root level files so disabling for now dotnet_diagnostic.IDE0130.severity = none +# CA1805: Do not initialize unnecessarily - It's better to be explicit when initializing vars to ensure correct value is used +dotnet_diagnostic.CA1805.severity = none + # Documentation related errors, remove once they are fixed dotnet_diagnostic.CS1591.severity = none dotnet_diagnostic.CS1573.severity = none diff --git a/src/TriggerBinding/SqlTableChangeMonitor.cs b/src/TriggerBinding/SqlTableChangeMonitor.cs index d684b5d6c..eee1a77bb 100644 --- a/src/TriggerBinding/SqlTableChangeMonitor.cs +++ b/src/TriggerBinding/SqlTableChangeMonitor.cs @@ -47,22 +47,22 @@ internal sealed class SqlTableChangeMonitor : IDisposable private readonly ITriggeredFunctionExecutor _executor; private readonly ILogger _logger; - private readonly CancellationTokenSource _cancellationTokenSourceCheckForChanges; - private readonly CancellationTokenSource _cancellationTokenSourceRenewLeases; - private CancellationTokenSource _cancellationTokenSourceExecutor; + private readonly CancellationTokenSource _cancellationTokenSourceCheckForChanges = new CancellationTokenSource(); + private readonly CancellationTokenSource _cancellationTokenSourceRenewLeases = new CancellationTokenSource(); + private CancellationTokenSource _cancellationTokenSourceExecutor = new CancellationTokenSource(); // The semaphore gets used by lease-renewal loop to ensure that '_state' stays set to 'ProcessingChanges' while // the leases are being renewed. The change-consumption loop requires to wait for the semaphore before modifying // the value of '_state' back to 'CheckingForChanges'. Since the field '_rows' is only updated if the value of // '_state' is set to 'CheckingForChanges', this guarantees that '_rows' will stay same while it is being // iterated over inside the lease-renewal loop. - private readonly SemaphoreSlim _rowsLock; + private readonly SemaphoreSlim _rowsLock = new SemaphoreSlim(1, 1); private readonly IDictionary _telemetryProps; - private IReadOnlyList> _rows; - private int _leaseRenewalCount; - private State _state; + private IReadOnlyList> _rows = new List>(); + private int _leaseRenewalCount = 0; + private State _state = State.CheckingForChanges; /// /// Initializes a new instance of the > class. @@ -89,41 +89,23 @@ public SqlTableChangeMonitor( ILogger logger, IDictionary telemetryProps) { - _ = !string.IsNullOrEmpty(connectionString) ? true : throw new ArgumentNullException(nameof(connectionString)); - _ = !string.IsNullOrEmpty(userTable.FullName) ? true : throw new ArgumentNullException(nameof(userTable)); - _ = !string.IsNullOrEmpty(userFunctionId) ? true : throw new ArgumentNullException(nameof(userFunctionId)); - _ = !string.IsNullOrEmpty(leasesTableName) ? true : throw new ArgumentNullException(nameof(leasesTableName)); - _ = userTableColumns ?? throw new ArgumentNullException(nameof(userTableColumns)); - _ = primaryKeyColumns ?? throw new ArgumentNullException(nameof(primaryKeyColumns)); - _ = executor ?? throw new ArgumentNullException(nameof(executor)); - _ = logger ?? throw new ArgumentNullException(nameof(logger)); - - this._connectionString = connectionString; + this._connectionString = !string.IsNullOrEmpty(connectionString) ? connectionString : throw new ArgumentNullException(nameof(connectionString)); + this._userTable = !string.IsNullOrEmpty(userTable?.FullName) ? userTable : throw new ArgumentNullException(nameof(userTable)); + this._userFunctionId = !string.IsNullOrEmpty(userFunctionId) ? userFunctionId : throw new ArgumentNullException(nameof(userFunctionId)); + this._leasesTableName = !string.IsNullOrEmpty(leasesTableName) ? leasesTableName : throw new ArgumentNullException(nameof(leasesTableName)); + this._userTableColumns = userTableColumns ?? throw new ArgumentNullException(nameof(userTableColumns)); + this._primaryKeyColumns = primaryKeyColumns ?? throw new ArgumentNullException(nameof(primaryKeyColumns)); + this._executor = executor ?? throw new ArgumentNullException(nameof(executor)); + this._logger = logger ?? throw new ArgumentNullException(nameof(logger)); + this._userTableId = userTableId; - this._userTable = userTable; - this._userFunctionId = userFunctionId; - this._leasesTableName = leasesTableName; - this._userTableColumns = userTableColumns; - this._primaryKeyColumns = primaryKeyColumns; // Prep search-conditions that will be used besides WHERE clause to match table rows. this._rowMatchConditions = Enumerable.Range(0, BatchSize) .Select(rowIndex => string.Join(" AND ", this._primaryKeyColumns.Select((col, colIndex) => $"{col.AsBracketQuotedString()} = @{rowIndex}_{colIndex}"))) .ToList(); - this._executor = executor; - this._logger = logger; - - this._cancellationTokenSourceCheckForChanges = new CancellationTokenSource(); - this._cancellationTokenSourceRenewLeases = new CancellationTokenSource(); - this._cancellationTokenSourceExecutor = new CancellationTokenSource(); - - this._telemetryProps = telemetryProps; - - this._rowsLock = new SemaphoreSlim(1, 1); - this._rows = new List>(); - this._leaseRenewalCount = 0; - this._state = State.CheckingForChanges; + this._telemetryProps = telemetryProps ?? new Dictionary(); #pragma warning disable CS4014 // Queue the below tasks and exit. Do not wait for their completion. _ = Task.Run(() => diff --git a/src/TriggerBinding/SqlTriggerBindingProvider.cs b/src/TriggerBinding/SqlTriggerBindingProvider.cs index 2fc6644ca..b35ed3f01 100644 --- a/src/TriggerBinding/SqlTriggerBindingProvider.cs +++ b/src/TriggerBinding/SqlTriggerBindingProvider.cs @@ -33,8 +33,7 @@ public SqlTriggerBindingProvider(IConfiguration configuration, IHostIdProvider h this._configuration = configuration ?? throw new ArgumentNullException(nameof(configuration)); this._hostIdProvider = hostIdProvider ?? throw new ArgumentNullException(nameof(hostIdProvider)); - _ = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory)); - this._logger = loggerFactory.CreateLogger(LogCategories.CreateTriggerCategory("Sql")); + this._logger = loggerFactory?.CreateLogger(LogCategories.CreateTriggerCategory("Sql")) ?? throw new ArgumentNullException(nameof(loggerFactory)); } /// diff --git a/src/TriggerBinding/SqlTriggerListener.cs b/src/TriggerBinding/SqlTriggerListener.cs index 5523ffc69..377aba054 100644 --- a/src/TriggerBinding/SqlTriggerListener.cs +++ b/src/TriggerBinding/SqlTriggerListener.cs @@ -38,7 +38,7 @@ internal sealed class SqlTriggerListener : IListener private readonly IDictionary _telemetryProps = new Dictionary(); private SqlTableChangeMonitor _changeMonitor; - private int _listenerState; + private int _listenerState = ListenerNotStarted; /// /// Initializes a new instance of the class. @@ -50,18 +50,11 @@ internal sealed class SqlTriggerListener : IListener /// Facilitates logging of messages public SqlTriggerListener(string connectionString, string tableName, string userFunctionId, ITriggeredFunctionExecutor executor, ILogger logger) { - _ = !string.IsNullOrEmpty(connectionString) ? true : throw new ArgumentNullException(nameof(connectionString)); - _ = !string.IsNullOrEmpty(tableName) ? true : throw new ArgumentNullException(nameof(tableName)); - _ = !string.IsNullOrEmpty(userFunctionId) ? true : throw new ArgumentNullException(nameof(userFunctionId)); - _ = executor ?? throw new ArgumentNullException(nameof(executor)); - _ = logger ?? throw new ArgumentNullException(nameof(logger)); - - this._connectionString = connectionString; - this._userTable = new SqlObject(tableName); - this._userFunctionId = userFunctionId; - this._executor = executor; - this._logger = logger; - this._listenerState = ListenerNotStarted; + this._connectionString = !string.IsNullOrEmpty(connectionString) ? connectionString : throw new ArgumentNullException(nameof(connectionString)); + this._userTable = !string.IsNullOrEmpty(tableName) ? new SqlObject(tableName) : throw new ArgumentNullException(nameof(tableName)); + this._userFunctionId = !string.IsNullOrEmpty(userFunctionId) ? userFunctionId : throw new ArgumentNullException(nameof(userFunctionId)); + this._executor = executor ?? throw new ArgumentNullException(nameof(executor)); + this._logger = logger ?? throw new ArgumentNullException(nameof(logger)); } public void Cancel()