Example #1
0
        private ProgressReportingTask <TResult, TProgress> GetAsynchronousResponseWithProgress <TResult, TProgress>(AsyncResults taskCompletionSource, CancellationToken cancellationToken)
        {
            ProgressReportingTask <TResult, TProgress> progressReportingTask = new ProgressReportingTask <TResult, TProgress>(
                progress =>
            {
                object obj;
                while (taskCompletionSource.TryTake(out obj, (int)TimeSpan.FromMinutes(2).TotalMilliseconds, cancellationToken))
                {
                    progress.MakeProgress((TProgress)obj);
                    if (obj is TProgress)
                    {
                        progress.MakeProgress((TProgress)obj);
                    }
                    else if (obj is TResult)
                    {
                        return((TResult)obj);
                    }
                    else
                    {
                        throw new ArgumentException("Cannot process result type of " + taskCompletionSource.GetConsumingEnumerable(cancellationToken).First().GetType());
                    }
                }
                throw new AbandonedMutexException("We did not receive of reply from the server after 2 minutes for transaction " + taskCompletionSource.Id);
            }, cancellationToken, TaskCreationOptions.None);

            progressReportingTask.Start(BackgroundTaskScheduler.OnBackground());
            Task tt = progressReportingTask;

            tt.OnCancelled(
                canceled =>
            {
                Trace.WriteLine("Got some more cancels");
            }, UITaskScheduler.InvokeAsync());                             // bug here - not being called on cancel
            return(progressReportingTask);
        }
        public async Task When_Child_Task_Is_Queued(JobContinuationOptions hangfireOptions)
        {
            // Arrange
            var parentId                = Guid.NewGuid().ToString();
            var backgroundJobClient     = new Mock <IBackgroundJobClient>();
            var backgroundTaskExecutor  = new HangfireBackgroundTaskScheduleProvider(backgroundJobClient.Object, new NullLogger <HangfireBackgroundTaskScheduleProvider>());
            var backgroundTaskScheduler = new BackgroundTaskScheduler(Enumerable.Empty <IBackgroundTaskPreprocessor>(), backgroundTaskExecutor, new NullLogger <BackgroundTaskScheduler>());

            backgroundJobClient.Setup(c => c.Create(It.IsAny <Job>(), It.Is <EnqueuedState>(s => s.Queue == EnqueuedState.DefaultQueue)))
            .Returns(parentId).Verifiable();
            backgroundJobClient.Setup(c => c.Create(It.IsAny <Job>(), It.Is <AwaitingState>(s => s.ParentId == parentId && s.Options == hangfireOptions)))
            .Verifiable();

            // Act
            var parentTask = backgroundTaskScheduler.Enqueue(new ParentTask());
            var childTask  = parentTask.ContinueWith(new ChildTask(),
                                                     hangfireOptions == JobContinuationOptions.OnlyOnSucceededState
                    ? BackgroundTaskContinuationOptions.OnlyOnSucceededState
                    : BackgroundTaskContinuationOptions.OnAnyFinishedState);
            await backgroundTaskScheduler.RunNowAsync();

            // Assert
            parentTask.Should().NotBeNull();
            childTask.Should().NotBeNull();
            backgroundJobClient.Verify(c => c.Create(It.IsAny <Job>(), It.Is <EnqueuedState>(s => s.Queue == EnqueuedState.DefaultQueue)));
            backgroundJobClient.Verify(c => c.Create(It.IsAny <Job>(), It.Is <AwaitingState>(s => s.ParentId == parentId && s.Options == hangfireOptions)));
        }
Example #3
0
        /// <summary>
        /// Start running the connector. It first does an initial push for data since the provided checkpoint, and then starts the background job cadence.
        /// </summary>
        /// <param name="cancellationToken">The task cancelation token.</param>
        /// <returns>The running task</returns>
        public async Task RunAsync(CancellationToken cancellationToken = default(CancellationToken))
        {
            log.Info("Put on your seat-belt, starting the polling connector run.");

            log.Info($"Doing an initial poll with the checkpoint: {this.checkpoint.GetValue()}.");
            this.pusher.Push(this.db);
            if (this.config?.ScanInterval.TotalMilliseconds > 0)
            {
                var scheduler = new BackgroundTaskScheduler(this.config.ScanInterval);
                await scheduler.StartAsync(() => this.pusher.Push(this.db), cancellationToken);
            }
        }
Example #4
0
        public static async Task InitializeDatabase(IUnityContainer container)
        {
            var dataAccess = container.Resolve <IDataAccess>(Resources.DataAccessObjectName);

            await BackgroundTaskScheduler.QueueBackgroundWorkItem(async ct =>
            {
                if (DatabaseState.New == await dataAccess.OpenOrCreateDatabaseAsync())
                {
                    await PopulateDatabase(container, dataAccess);
                }
            });
        }
Example #5
0
 private Task <TResult> GetAsynchronousResponse <TResult>(AsyncResults taskCompletionSource, CancellationToken cancellationToken)
 {
     return(TaskFactoryHelper <TResult> .StartNew(
                () =>
     {
         object obj;
         while (!(taskCompletionSource.TryTake(out obj, (int)TimeSpan.FromMinutes(2).TotalMilliseconds, cancellationToken)))
         {
             if (obj is TResult)
             {
                 return (TResult)obj;
             }
         }
         throw new AbandonedMutexException("We did not receive of reply from the server after 2 minutes for transaction " + taskCompletionSource.Id);
     }, BackgroundTaskScheduler.OnBackground(), cancellationToken));
 }
Example #6
0
        public async Task TestBackgroundTaskScheduler()
        {
            var scheduler = new BackgroundTaskScheduler(TimeSpan.FromSeconds(1));
            var canceller = new CancellationTokenSource();

            int  occurences = 0;
            Task run        = scheduler.StartAsync(() => occurences++, canceller.Token);

            await Task.Delay(TimeSpan.FromSeconds(0.5));

            Assert.AreEqual(0, occurences);

            await Task.Delay(TimeSpan.FromSeconds(5));

            Assert.AreEqual(5, occurences);

            canceller.Cancel();
            await Task.Delay(TimeSpan.FromSeconds(2));

            Assert.AreEqual(5, occurences);
        }
Example #7
0
        private async Task UpdateAsync(IEnumerable <ShellContext> previousShells, IEnumerable <ShellContext> runningShells, CancellationToken stoppingToken)
        {
            var referenceTime = DateTime.UtcNow;

            await GetShellsToUpdate(previousShells, runningShells).ForEachAsync(async shell =>
            {
                var tenant = shell.Settings.Name;

                if (stoppingToken.IsCancellationRequested)
                {
                    return;
                }

                _httpContextAccessor.HttpContext = shell.CreateHttpContext();

                var shellScope = await _shellHost.GetScopeAsync(shell.Settings);

                if (shellScope.ShellContext.Pipeline == null)
                {
                    return;
                }

                await shellScope.UsingAsync(async scope =>
                {
                    var tasks = scope.ServiceProvider.GetServices <IBackgroundTask>();

                    CleanSchedulers(tenant, tasks);

                    if (!tasks.Any())
                    {
                        return;
                    }

                    var settingsProvider = scope.ServiceProvider.GetService <IBackgroundTaskSettingsProvider>();

                    _changeTokens[tenant] = settingsProvider?.ChangeToken ?? NullChangeToken.Singleton;

                    foreach (var task in tasks)
                    {
                        var taskName = task.GetTaskName();

                        if (!_schedulers.TryGetValue(tenant + taskName, out var scheduler))
                        {
                            _schedulers[tenant + taskName] = scheduler = new BackgroundTaskScheduler(tenant, taskName, referenceTime);
                        }

                        if (!scheduler.Released && scheduler.Updated)
                        {
                            continue;
                        }

                        BackgroundTaskSettings settings = null;

                        try
                        {
                            if (settingsProvider != null)
                            {
                                settings = await settingsProvider.GetSettingsAsync(task);
                            }
                        }

                        catch (Exception e)
                        {
                            Logger.LogError(e, "Error while updating settings of background task '{TaskName}' on tenant '{TenantName}'.", taskName, tenant);
                        }

                        settings = settings ?? task.GetDefaultSettings();

                        if (scheduler.Released || !scheduler.Settings.Schedule.Equals(settings.Schedule))
                        {
                            scheduler.ReferenceTime = referenceTime;
                        }

                        scheduler.Settings = settings;
                        scheduler.Released = false;
                        scheduler.Updated  = true;
                    }
                });
            });
        }
Example #8
0
        private static async Task PopulateDatabase(IUnityContainer container, IDataAccess dataAccess)
        {
            await BackgroundTaskScheduler.QueueBackgroundWorkItem(async ct =>
            {
                var i           = 0;
                var artistTable = container.Resolve <ArtistTable>();
                var genreTable  = container.Resolve <GenreTable>();
                var albumTable  = container.Resolve <AlbumTable>();

                var dirName = Path.GetDirectoryName(Uri.UnescapeDataString(new UriBuilder(Assembly.GetExecutingAssembly().CodeBase).Path));
                if (dirName != null)
                {
                    var dataFilePath = Path.Combine(dirName, Resources.DataFile);
                    var lines        = File.ReadAllLines(dataFilePath);
                    var lineCount    = lines.Length - 1;

                    foreach (var line in lines.Skip(1))
                    {
                        // album name, artist name, genre name, year
                        // album name might have quotes
                        string album;
                        string artist;
                        string genre;
                        int year;

                        var parts = line.Split('"');
                        if (parts.Length > 1)
                        {
                            album  = parts[1];
                            parts  = parts[2].Split(',');
                            artist = parts[1];
                            genre  = parts[2];
                            year   = int.Parse(parts[3]);
                        }
                        else
                        {
                            parts  = line.Split(',');
                            album  = parts[0];
                            artist = parts[1];
                            genre  = parts[2];
                            year   = int.Parse(parts[3]);
                        }

                        var artistId     = i;
                        var genreId      = i;
                        var parameters   = new List <SQLiteParameter>();
                        var artistResult = await dataAccess.ExecuteSqlWithParametersAsync(artistTable.GetInsertSql(new Artist(i, artist), ref parameters), parameters);
                        if (artistResult <= 0)
                        {
                            // the artist already exists
                            artistId     = await GetExistingId(artistTable, artist, dataAccess);
                            artistResult = artistId > 0 ? 1 : artistId;
                        }

                        parameters.Clear();

                        var genreResult = await dataAccess.ExecuteSqlWithParametersAsync(genreTable.GetInsertSql(new Genre(i, genre), ref parameters), parameters);
                        if (genreResult <= 0)
                        {
                            // the genre already exists
                            genreId     = await GetExistingId(genreTable, genre, dataAccess);
                            genreResult = genreId > 0 ? 1 : genreId;
                        }

                        parameters.Clear();

                        var albumResult = await dataAccess.ExecuteSqlWithParametersAsync(albumTable.GetInsertSql(new Album(i, artistId, genreId, album, year), ref parameters), parameters);
                        if (albumResult <= 0)
                        {
                            // the album already exists
                            throw new SQLiteException(Resources.AlbumExistsExceptionMessage);
                        }

                        i++;

                        if (artistResult + genreResult + albumResult != 3)
                        {
                            throw new SQLiteException(Resources.ErrorAddingItemMessage);
                        }
                    }

                    if (i != lineCount)
                    {
                        throw new SQLiteException($"Error adding data to database. There were {lineCount} items, but only {i} were added.");
                    }
                }
            });
        }
Example #9
0
        /// <summary>
        /// Provides a synchronous wait version of a server request and callback.
        /// If the caller thread is UI thread, it executes asynchronously.
        /// If the caller thread is not UI thread, it blocks the caller thread.
        /// </summary>
        /// <typeparam name="T">The type expected via callback.</typeparam>
        /// <typeparam name="TResponse"></typeparam>
        /// <typeparam name="TRequest"></typeparam>
        /// <param name="request"></param>
        /// <param name="svcGatewayMethod"></param>
        /// <param name="timeout">The time to wait before giving up on the service response.</param>
        /// <returns></returns>
        /// <remarks>Note that this does not currently support progress reporting. If the service provides progress
        /// reports this will need to be amended.</remarks>
        protected TResponse ServerRequest <TResponse, TRequest>(TRequest request, SvcGatewayDelegate <TRequest, TResponse> svcGatewayMethod, TimeSpan timeout)
            where TResponse : ServiceResponse
            where TRequest : ICommonRequest
        {
            AsyncResults asyncResults = AddToResponseQueue(request.RequestID);

            TimeSpan defaultTimeout = TimeSpan.FromMinutes(2);

            if (defaultTimeout < timeout)
            {
                timeout = defaultTimeout;
            }
            if (UIThreadSingleton.IsCreated && UIThreadSingleton.IsCallFromUIThread)
            {
                Task <TResponse> callCompleted = TaskFactoryHelper <TResponse> .StartNew(
                    () => ExecServerRequest(request, svcGatewayMethod, timeout, asyncResults), BackgroundTaskScheduler.OnBackground());

                while (!callCompleted.IsFinishedRunning())
                {
                    Application.DoEvents();
                }

                if (callCompleted.Status != TaskStatus.RanToCompletion)
                {
                    if (callCompleted.Exception != null)
                    {
                        AggregateException aggregateException = callCompleted.Exception.Flatten();
                        if (aggregateException.InnerException != null)
                        {
                            throw aggregateException.InnerException;
                        }
                    }
                }
                return(callCompleted.Result);
            }
            else
            {
                return(ExecServerRequest(request, svcGatewayMethod, timeout, asyncResults));
            }
        }