예제 #1
0
        public async Task BeforeDisposeAsync()
        {
            foreach (var callback in _beforeDispose)
            {
                await callback(this);
            }

            if (_deferredSignals.Any())
            {
                var signal = ShellContext.ServiceProvider.GetRequiredService <ISignal>();

                foreach (var key in _deferredSignals)
                {
                    await signal.SignalTokenAsync(key);
                }
            }

            if (_deferredTasks.Any())
            {
                var shellHost = ShellContext.ServiceProvider.GetRequiredService <IShellHost>();

                foreach (var task in _deferredTasks)
                {
                    ShellScope scope;

                    // Create a new scope (maybe based on a new shell) for each task.
                    try
                    {
                        // May fail if a shell was released before being disabled.
                        scope = await shellHost.GetScopeAsync(ShellContext.Settings);
                    }
                    catch
                    {
                        // Fallback to a scope based on the current shell that is not yet disposed.
                        scope = new ShellScope(ShellContext);
                    }

                    using (scope)
                    {
                        scope.StartAsyncFlow();

                        var logger = scope.ServiceProvider.GetService <ILogger <ShellScope> >();

                        try
                        {
                            await task(scope);
                        }
                        catch (Exception e)
                        {
                            logger?.LogError(e,
                                             "Error while processing deferred task '{TaskName}' on tenant '{TenantName}'.",
                                             task.GetType().FullName, ShellContext.Settings.Name);
                        }

                        await scope.BeforeDisposeAsync();

                        await scope.DisposeAsync();
                    }
                }
            }
        }
예제 #2
0
 /// <summary>
 /// Adds an handler task to be invoked if an exception is thrown while executing in this shell scope.
 /// </summary>
 public static ShellScope AddExceptionHandler(this ShellScope scope, Func <ShellScope, Exception, Task> handler)
 {
     scope?.ExceptionHandler(handler);
     return(scope);
 }
예제 #3
0
 /// <summary>
 /// Adds a Task to be executed in a new scope once this shell scope has been disposed.
 /// </summary>
 public static ShellScope AddDeferredTask(this ShellScope scope, Func <ShellScope, Task> task)
 {
     scope?.DeferredTask(task);
     return(scope);
 }
예제 #4
0
 /// <summary>
 /// Adds a Signal (if not already present) to be sent just before this shell scope will be disposed.
 /// </summary>
 public static ShellScope AddDeferredSignal(this ShellScope scope, string key)
 {
     scope?.DeferredSignal(key);
     return(scope);
 }
예제 #5
0
 /// <summary>
 /// Registers a delegate task to be invoked before this shell scope will be disposed.
 /// </summary>
 public static ShellScope RegisterBeforeDispose(this ShellScope scope, Func <ShellScope, Task> callback)
 {
     scope?.BeforeDispose(callback);
     return(scope);
 }
예제 #6
0
        internal async Task BeforeDisposeAsync()
        {
            foreach (var callback in _beforeDispose)
            {
                await callback(this);
            }

            if (_serviceScopeOnly)
            {
                return;
            }

            if (_deferredSignals.Any())
            {
                var signal = ShellContext.ServiceProvider.GetRequiredService <ISignal>();
                foreach (var key in _deferredSignals)
                {
                    await signal.SignalTokenAsync(key);
                }
            }

            if (_deferredTasks.Any())
            {
                var shellHost = ShellContext.ServiceProvider.GetRequiredService <IShellHost>();

                foreach (var task in _deferredTasks)
                {
                    // Create a new scope (maybe based on a new shell) for each task.
                    ShellScope scope;
                    try
                    {
                        // May fail if a shell was released before being disabled.
                        scope = await shellHost.GetScopeAsync(ShellContext.Settings);
                    }
                    catch
                    {
                        // Fallback to a scope based on the current shell that is not yet disposed.
                        scope = new ShellScope(ShellContext);
                    }

                    // Use 'UsingAsync' in place of 'UsingServiceScopeAsync()' to allow a deferred task to
                    // trigger another one, but still prevent the shell to be activated in a deferred task.
                    await scope.UsingAsync(async scope =>
                    {
                        var logger = scope.ServiceProvider.GetService <ILogger <ShellScope> >();

                        try
                        {
                            await task(scope);
                        }
                        catch (Exception e)
                        {
                            logger?.LogError(e,
                                             "Error while processing deferred task '{TaskName}' on tenant '{TenantName}'.",
                                             task.GetType().FullName, ShellContext.Settings.Name);

                            await scope.HandleExceptionAsync(e);
                        }
                    },
                                           activateShell : false);
                }
            }
        }