internal void ExecuteKeepAliveQueryIfRequired() { var now = TimestampHelper.GetTimestamp(); if (TimestampHelper.Elapsed(now, Interlocked.Read(ref _lastHeartbeat)) >= _interval) { lock (_syncRoot) { if (!FetchedAt.HasValue) { return; } if (_requeued || _removedFromQueue) { return; } try { _storage.UseConnection(null, connection => { FetchedAt = connection.ExecuteScalar <DateTime?>( $"update JQ set FetchedAt = getutcdate() output INSERTED.FetchedAt from [{_storage.SchemaName}].JobQueue JQ with ({GetTableHints()}) where Queue = @queue and Id = @id and FetchedAt = @fetchedAt", new { queue = Queue, id = Id, fetchedAt = FetchedAt }, commandTimeout: _storage.CommandTimeout); }); if (!FetchedAt.HasValue) { _logger.Warn( $"Background job identifier '{JobId}' was fetched by another worker, will not execute keep alive."); } _logger.Trace($"Keep-alive query for message {Id} sent"); Interlocked.Exchange(ref _lastHeartbeat, now); } catch (Exception ex) { _logger.DebugException($"Unable to execute keep-alive query for message {Id}", ex); } } } }
public SqlServerTimeoutJob( [NotNull] SqlServerStorage storage, long id, [NotNull] string jobId, [NotNull] string queue, [NotNull] DateTime?fetchedAt) { if (storage == null) { throw new ArgumentNullException(nameof(storage)); } if (jobId == null) { throw new ArgumentNullException(nameof(jobId)); } if (queue == null) { throw new ArgumentNullException(nameof(queue)); } if (fetchedAt == null) { throw new ArgumentNullException(nameof(fetchedAt)); } _storage = storage; Id = id; JobId = jobId; Queue = queue; FetchedAt = fetchedAt.Value; if (storage.SlidingInvisibilityTimeout.HasValue) { _lastHeartbeat = TimestampHelper.GetTimestamp(); _interval = TimeSpan.FromSeconds(storage.SlidingInvisibilityTimeout.Value.TotalSeconds / 5); storage.HeartbeatProcess.Track(this); } }