public BlobQueueTriggerExecutor(IBlobCausalityReader causalityReader, BlobTriggerSource blobTriggerSource, IBlobWrittenWatcher blobWrittenWatcher, ILogger <BlobListener> logger) { _causalityReader = causalityReader; _blobTriggerSource = blobTriggerSource; _blobWrittenWatcher = blobWrittenWatcher; _registrations = new ConcurrentDictionary <string, BlobQueueRegistration>(); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); }
public SharedBlobQueueListenerFactory( QueueServiceClient hostQueueServiceClient, SharedQueueWatcher sharedQueueWatcher, QueueClient hostBlobTriggerQueue, BlobsOptions blobsOptions, IWebJobsExceptionHandler exceptionHandler, ILoggerFactory loggerFactory, IBlobWrittenWatcher blobWrittenWatcher, FunctionDescriptor functionDescriptor, BlobTriggerSource blobTriggerSource) { _hostQueueServiceClient = hostQueueServiceClient ?? throw new ArgumentNullException(nameof(hostQueueServiceClient)); _sharedQueueWatcher = sharedQueueWatcher ?? throw new ArgumentNullException(nameof(sharedQueueWatcher)); _hostBlobTriggerQueue = hostBlobTriggerQueue ?? throw new ArgumentNullException(nameof(hostBlobTriggerQueue)); _blobsOptions = blobsOptions ?? throw new ArgumentNullException(nameof(blobsOptions)); _exceptionHandler = exceptionHandler ?? throw new ArgumentNullException(nameof(exceptionHandler)); _loggerFactory = loggerFactory; _blobWrittenWatcher = blobWrittenWatcher; _functionDescriptor = functionDescriptor; _blobTriggerSource = blobTriggerSource; }
public BlobTriggerBinding(ParameterInfo parameter, BlobServiceClient hostBlobServiceClient, QueueServiceClient hostQueueServiceClient, BlobServiceClient dataBlobServiceClient, QueueServiceClient dataQueueServiceClient, IBlobPathSource path, BlobTriggerSource blobTriggerSource, IHostIdProvider hostIdProvider, BlobsOptions blobsOptions, IWebJobsExceptionHandler exceptionHandler, IContextSetter <IBlobWrittenWatcher> blobWrittenWatcherSetter, BlobTriggerQueueWriterFactory blobTriggerQueueWriterFactory, ISharedContextProvider sharedContextProvider, IHostSingletonManager singletonManager, ILoggerFactory loggerFactory, ConcurrencyManager concurrencyManager) { _parameter = parameter ?? throw new ArgumentNullException(nameof(parameter)); _hostBlobServiceClient = hostBlobServiceClient ?? throw new ArgumentNullException(nameof(hostBlobServiceClient)); _hostQueueServiceClient = hostQueueServiceClient ?? throw new ArgumentNullException(nameof(hostQueueServiceClient)); _dataBlobServiceClient = dataBlobServiceClient ?? throw new ArgumentNullException(nameof(dataBlobServiceClient)); _dataQueueServiceClient = dataQueueServiceClient ?? throw new ArgumentNullException(nameof(dataQueueServiceClient)); _accountName = _dataBlobServiceClient.AccountName; _path = path ?? throw new ArgumentNullException(nameof(path)); _blobTriggerSource = blobTriggerSource; _hostIdProvider = hostIdProvider ?? throw new ArgumentNullException(nameof(hostIdProvider)); _blobsOptions = blobsOptions ?? throw new ArgumentNullException(nameof(blobsOptions)); _exceptionHandler = exceptionHandler ?? throw new ArgumentNullException(nameof(exceptionHandler)); _blobWrittenWatcherSetter = blobWrittenWatcherSetter ?? throw new ArgumentNullException(nameof(blobWrittenWatcherSetter)); _blobTriggerQueueWriterFactory = blobTriggerQueueWriterFactory ?? throw new ArgumentNullException(nameof(blobTriggerQueueWriterFactory)); _sharedContextProvider = sharedContextProvider ?? throw new ArgumentNullException(nameof(sharedContextProvider)); _singletonManager = singletonManager ?? throw new ArgumentNullException(nameof(singletonManager)); _concurrencyManager = concurrencyManager ?? throw new ArgumentNullException(nameof(concurrencyManager)); _loggerFactory = loggerFactory; _converter = CreateConverter(_dataBlobServiceClient); _bindingDataContract = CreateBindingDataContract(path); }
public BlobListenerFactory(IHostIdProvider hostIdProvider, BlobsOptions blobsOptions, IWebJobsExceptionHandler exceptionHandler, IContextSetter <IBlobWrittenWatcher> blobWrittenWatcherSetter, BlobTriggerQueueWriterFactory blobTriggerQueueWriterFactory, ISharedContextProvider sharedContextProvider, ILoggerFactory loggerFactory, FunctionDescriptor functionDescriptor, BlobServiceClient hostBlobServiceClient, QueueServiceClient hostQueueServiceClient, BlobServiceClient dataBlobServiceClient, QueueServiceClient dataQueueServiceClient, BlobContainerClient container, IBlobPathSource input, BlobTriggerSource triggerKind, ITriggeredFunctionExecutor executor, IHostSingletonManager singletonManager, ConcurrencyManager concurrencyManager) { _hostIdProvider = hostIdProvider ?? throw new ArgumentNullException(nameof(hostIdProvider)); _blobTriggerQueueWriterFactory = blobTriggerQueueWriterFactory ?? throw new ArgumentNullException(nameof(blobTriggerQueueWriterFactory)); _blobsOptions = blobsOptions ?? throw new ArgumentNullException(nameof(blobsOptions)); _exceptionHandler = exceptionHandler ?? throw new ArgumentNullException(nameof(exceptionHandler)); _blobWrittenWatcherSetter = blobWrittenWatcherSetter ?? throw new ArgumentNullException(nameof(blobWrittenWatcherSetter)); _sharedContextProvider = sharedContextProvider ?? throw new ArgumentNullException(nameof(sharedContextProvider)); _functionDescriptor = functionDescriptor ?? throw new ArgumentNullException(nameof(functionDescriptor)); _loggerFactory = loggerFactory; _hostBlobServiceClient = hostBlobServiceClient ?? throw new ArgumentNullException(nameof(hostBlobServiceClient)); _hostQueueServiceClient = hostQueueServiceClient ?? throw new ArgumentNullException(nameof(hostQueueServiceClient)); _dataBlobServiceClient = dataBlobServiceClient ?? throw new ArgumentNullException(nameof(dataBlobServiceClient)); _dataQueueServiceClient = dataQueueServiceClient ?? throw new ArgumentNullException(nameof(dataQueueServiceClient)); _container = container ?? throw new ArgumentNullException(nameof(container)); _input = input ?? throw new ArgumentNullException(nameof(input)); _blobTriggerSource = triggerKind; _executor = executor ?? throw new ArgumentNullException(nameof(executor)); _singletonManager = singletonManager ?? throw new ArgumentNullException(nameof(singletonManager)); _concurrencyManager = concurrencyManager ?? throw new ArgumentNullException(nameof(concurrencyManager)); }
public static void BlobMessageEnqueued(ILogger <BlobListener> logger, string functionName, string blobName, string queueMessageId, string queueName, string pollId, BlobTriggerSource triggerSource) => _blobMessageEnqueued(logger, blobName, functionName, queueMessageId, queueName, pollId, triggerSource, null);
public static void BlobAlreadyProcessed(ILogger <BlobListener> logger, string functionName, string blobName, string eTag, string pollId, BlobTriggerSource triggerSource) => _blobAlreadyProcessed(logger, blobName, functionName, eTag, pollId, triggerSource, null);
public static void BlobHasNoETag(ILogger <BlobListener> logger, string functionName, string blobName, string pollId, BlobTriggerSource triggerSource) => _blobHasNoETag(logger, blobName, functionName, pollId, triggerSource, null);
public static void BlobDoesNotMatchPattern(ILogger <BlobListener> logger, string functionName, string blobName, string pattern, string pollId, BlobTriggerSource triggerSource) => _blobDoesNotMatchPattern(logger, blobName, functionName, pattern, pollId, triggerSource, null);
public async Task <FunctionResult> ExecuteAsync(BlobTriggerExecutorContext context, CancellationToken cancellationToken) { BlobBaseClient value = context.Blob.BlobClient; BlobTriggerSource triggerSource = context.TriggerSource; string pollId = context.PollId; // Avoid unnecessary network calls for non-matches. First, check to see if the blob matches this trigger. IReadOnlyDictionary <string, object> bindingData = _input.CreateBindingData(value.ToBlobPath()); if (bindingData == null) { string pattern = new BlobPath(_input.ContainerNamePattern, _input.BlobNamePattern).ToString(); Logger.BlobDoesNotMatchPattern(_logger, _functionDescriptor.LogName, value.Name, pattern, pollId, triggerSource); // Blob is not a match for this trigger. return(new FunctionResult(true)); } // Next, check to see if the blob currently exists (and, if so, what the current ETag is). BlobProperties blobProperties = await value.FetchPropertiesOrNullIfNotExistAsync(cancellationToken).ConfigureAwait(false); string possibleETag = null; if (blobProperties != null) { possibleETag = blobProperties.ETag.ToString(); } if (possibleETag == null) { Logger.BlobHasNoETag(_logger, _functionDescriptor.LogName, value.Name, pollId, triggerSource); // If the blob doesn't exist and have an ETag, don't trigger on it. return(new FunctionResult(true)); } var receiptBlob = _receiptManager.CreateReference(_hostId, _functionDescriptor.Id, value.BlobContainerName, value.Name, possibleETag); // Check for the completed receipt. If it's already there, noop. BlobReceipt unleasedReceipt = await _receiptManager.TryReadAsync(receiptBlob, cancellationToken).ConfigureAwait(false); if (unleasedReceipt != null && unleasedReceipt.IsCompleted) { Logger.BlobAlreadyProcessed(_logger, _functionDescriptor.LogName, value.Name, possibleETag, pollId, triggerSource); return(new FunctionResult(true)); } else if (unleasedReceipt == null) { // Try to create (if not exists) an incomplete receipt. if (!await _receiptManager.TryCreateAsync(receiptBlob, cancellationToken).ConfigureAwait(false)) { // Someone else just created the receipt; wait to try to trigger until later. // Alternatively, we could just ignore the return result and see who wins the race to acquire the // lease. return(new FunctionResult(false)); } } string leaseId = await _receiptManager.TryAcquireLeaseAsync(receiptBlob, cancellationToken).ConfigureAwait(false); if (leaseId == null) { // If someone else owns the lease and just took over this receipt or deleted it; // wait to try to trigger until later. return(new FunctionResult(false)); } try { // Check again for the completed receipt. If it's already there, noop. BlobReceipt receipt = await _receiptManager.TryReadAsync(receiptBlob, cancellationToken).ConfigureAwait(false); Debug.Assert(receipt != null); // We have a (30 second) lease on the blob; it should never disappear on us. if (receipt.IsCompleted) { Logger.BlobAlreadyProcessed(_logger, _functionDescriptor.LogName, value.Name, possibleETag, pollId, triggerSource); await _receiptManager.ReleaseLeaseAsync(receiptBlob, leaseId, cancellationToken).ConfigureAwait(false); return(new FunctionResult(true)); } // We've successfully acquired a lease to enqueue the message for this blob trigger. Enqueue the message, // complete the receipt and release the lease. // Enqueue a message: function ID + blob path + ETag BlobTriggerMessage message = new BlobTriggerMessage { FunctionId = _functionDescriptor.Id, BlobType = blobProperties.BlobType, ContainerName = value.BlobContainerName, BlobName = value.Name, ETag = possibleETag }; var(queueName, messageId) = await _queueWriter.EnqueueAsync(message, cancellationToken).ConfigureAwait(false); Logger.BlobMessageEnqueued(_logger, _functionDescriptor.LogName, value.Name, messageId, queueName, pollId, triggerSource); // Complete the receipt await _receiptManager.MarkCompletedAsync(receiptBlob, leaseId, cancellationToken).ConfigureAwait(false); return(new FunctionResult(true)); } finally { await _receiptManager.ReleaseLeaseAsync(receiptBlob, leaseId, cancellationToken).ConfigureAwait(false); } }
public BlobQueueTriggerExecutor(BlobTriggerSource blobTriggerSource, IBlobWrittenWatcher blobWrittenWatcher, ILogger <BlobListener> logger) : this(BlobCausalityReader.Instance, blobTriggerSource, blobWrittenWatcher, logger) { }