private AvailabilityResultAsyncCollector CreateAvailabilityResultAsyncCollector(AvailabilityTestResultAttribute attribute, ValueBindingContext valueBindingContext) { // A function is defined as an Availability Test iff is has a return value marked with [AvailabilityTestResult]. // If that is the case, this method will be invoked as some point to construct a collector for the return value. // Depending on the kind of the function, this will happen in different ways: // // - For .Net functions (in-proc), this method runs BEFORE function filters: // a) We will register this function as an Availability Test in the Functions registry (this is a NoOp for all, // except the very first invocation). // b) We will create new invocation state bag and register it with the Invocations registry. // c) We will instantiate a result collector and attach it to the state bag. // d) Later on, BEFORE the function body runs, the runtime execute the pre-function filter. At that point we will: // ~ Initialize an Availablity Test Scope and attach it to the invocation state bag; // ~ Link the results collector and the test scope. // e) Subsequently, AFTER the function body runs the result will be set in one of two ways: // ~ If no error: the runtime will add the return value to the result collector -> the collector will Complete the Test Scope; // ~ If error/exception: the runtime will invoke the post-function filter -> the filter will Complete the Test Scope. // // - For non-.Net functions (out-of-proc), this method runs AFTER function filters (and, potentially, even AFTER the function body has completed): // a) Registering this function as an Availability Test in the Functions registry will be a NoOp. // b) We will receive an existing invocation state bag; the Availablity Test Scope will be already set in the state bag. // c&d) We will instantiate a result collector and link it with the test scope right away; we will attach the collector to the state bag. // e) The results will be set in a simillar manner as for .Net described above. Validate.NotNull(attribute, nameof(attribute)); Validate.NotNull(valueBindingContext, nameof(valueBindingContext)); string functionName = valueBindingContext.FunctionContext.MethodName; using (_log.BeginScope(LogMonikers.Scopes.CreateForTestInvocation(functionName))) { // Register this Function as an Availability Test (NoOp for all invocations of this method, except the very first one): _availabilityTestRegistry.Functions.Register(functionName, attribute, _log); // Register this particular invocation of this function: Guid functionInstanceId = valueBindingContext.FunctionInstanceId; AvailabilityTestInvocationState invocationState = _availabilityTestRegistry.Invocations.GetOrRegister(functionInstanceId, _log); // Create the result collector: var resultCollector = new AvailabilityResultAsyncCollector(); // If the test scope is already set (out-of-proc function), then link it with the collector: bool isTestScopeInitialized = invocationState.TryGetTestScope(out AvailabilityTestScope testScope); if (isTestScopeInitialized) { resultCollector.Initialize(testScope); } // Attache the collector to the invocation state bag: invocationState.AttachResultCollector(resultCollector); // Done: return(resultCollector); } }
private Task <IAsyncCollector <bool> > CreateBoolAsyncCollector(AvailabilityTestResultAttribute attribute, ValueBindingContext valueBindingContext) { AvailabilityResultAsyncCollector resultCollector = CreateAvailabilityResultAsyncCollector(attribute, valueBindingContext); return(Task.FromResult <IAsyncCollector <bool> >(resultCollector)); }