public void StatisticsHistoryFilter_ActsBefore_RetryFilter()
        {
            var statisticsHistoryFilter = new StatisticsHistoryAttribute();
            var retryFilter             = new AutomaticRetryAttribute();

            Assert.True(statisticsHistoryFilter.Order > retryFilter.Order);
        }
        public void StatisticsHistoryFilter_ActsBefore_RetryFilter()
        {
            var statisticsHistoryFilter = new StatisticsHistoryAttribute();
            var retryFilter = new AutomaticRetryAttribute();

            Assert.True(statisticsHistoryFilter.Order > retryFilter.Order);
        }
Пример #3
0
        public void OnStateElection_DoesNotChangeState_IfRetryAttemptsIsSetToZero()
        {
            var filter = new AutomaticRetryAttribute { Attempts = 0 };
            filter.OnStateElection(_context.Object);

            Assert.Same(_failedState, _context.Object.CandidateState);
        }
Пример #4
0
        public void OnStateElection_DoesNotChangeState_IfRetryAttemptsIsSetToZero()
        {
            var filter = new AutomaticRetryAttribute {
                Attempts = 0
            };

            filter.OnStateElection(_context.Object);

            Assert.Same(_failedState, _context.Object.CandidateState);
        }
Пример #5
0
        public void DelaysInSeconds_SetsValueCorrectly()
        {
            var filter = new AutomaticRetryAttribute {
                DelaysInSeconds = new[] { 5, 8 }
            };

            Assert.Equal(2, filter.DelaysInSeconds.Length);
            Assert.Equal(5, filter.DelaysInSeconds[0]);
            Assert.Equal(8, filter.DelaysInSeconds[1]);
        }
Пример #6
0
        public void OnStateElection_ChangesStateToDeleted_IfRetryAttemptsNumberIsZeroAndOnAttemptsExceedIsSetToDelete()
        {
            _connection.Setup(x => x.GetJobParameter(JobId, "RetryCount")).Returns("0");
            var filter = new AutomaticRetryAttribute {
                Attempts = 0, OnAttemptsExceeded = AttemptsExceededAction.Delete
            };

            filter.OnStateElection(_context.Object);

            Assert.IsType <DeletedState>(_context.Object.CandidateState);
        }
Пример #7
0
        public void OnStateElection_UsesDelaysInSeconds_WhenBothDelaysInSecondsAndDelayInSecondsByAttemptFuncAreSpecified()
        {
            var filter = new AutomaticRetryAttribute
            {
                DelayInSecondsByAttemptFunc = attempt => 1,
                DelaysInSeconds             = new[] { 0 }
            };

            filter.OnStateElection(_context.Object);

            Assert.IsType <EnqueuedState>(_context.Object.CandidateState);
        }
Пример #8
0
        public void DelayInSecondsByAttemptFunc_ReturnCorrectValue_WhenCustomFunctionIsSet()
        {
            var filter = new AutomaticRetryAttribute {
                DelayInSecondsByAttemptFunc = attempt => (int)attempt % 3
            };

            Assert.Equal(1, filter.DelayInSecondsByAttemptFunc(1));
            Assert.Equal(2, filter.DelayInSecondsByAttemptFunc(2));
            Assert.Equal(0, filter.DelayInSecondsByAttemptFunc(3));
            Assert.Equal(1, filter.DelayInSecondsByAttemptFunc(4));
            Assert.Equal(2, filter.DelayInSecondsByAttemptFunc(5));
            Assert.Equal(1, filter.DelayInSecondsByAttemptFunc(100));
        }
Пример #9
0
        public void OnStateElection_ChangeStateToEnqueued_IfDelayIsZero()
        {
            var filter = new AutomaticRetryAttribute
            {
                Attempts        = 1,
                DelaysInSeconds = new[] { 0 }
            };

            filter.OnStateElection(_context.Object);

            Assert.IsType <EnqueuedState>(_context.Object.CandidateState);
            Assert.NotNull(_context.Object.CandidateState.Reason);
            Assert.Contains("1 of 1", _context.Object.CandidateState.Reason);

            _connection.Verify(x => x.SetJobParameter(JobId, "RetryCount", "1"));
        }
Пример #10
0
        public void OnStateElection_ThrowsAnException_WhenDelayInSecondsByAttemptFuncThrowsAnException()
        {
            var exception = new Exception();

            var filter = new AutomaticRetryAttribute
            {
                DelayInSecondsByAttemptFunc = attempt =>
                {
                    throw exception;
                }
            };

            var thrownExcetption = Assert.Throws <Exception>(() => filter.OnStateElection(_context.Object));

            Assert.Equal(exception, thrownExcetption);
        }
Пример #11
0
        public void Ctor_SetsPositiveRetryAttemptsNumber_ByDefault()
        {
            var filter = new AutomaticRetryAttribute();

            Assert.Equal(10, filter.Attempts);
        }
Пример #12
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            var env = new Env();

            ConfigureRateLimiting(services);

            if (env.IsDevelopment)
            {
                DotEnv.Config(true, ".env.development");
            }

            services.AddSingleton <CdsServiceClientWrapper, CdsServiceClientWrapper>();
            services.AddTransient <IOrganizationService>(sp => sp.GetService <CdsServiceClientWrapper>().CdsServiceClient?.Clone());
            services.AddTransient <IOrganizationServiceAdapter, OrganizationServiceAdapter>();

            services.AddTransient <ICrmService, CrmService>();

            services.AddScoped <IStore, Store>();
            services.AddScoped <DbConfiguration, DbConfiguration>();

            services.AddSingleton <IMetricService, MetricService>();
            services.AddSingleton <INotificationClientAdapter, NotificationClientAdapter>();
            services.AddSingleton <IGeocodeClientAdapter, GeocodeClientAdapter>();
            services.AddSingleton <ICandidateAccessTokenService, CandidateAccessTokenService>();
            services.AddSingleton <ICandidateMagicLinkTokenService, CandidateMagicLinkTokenService>();
            services.AddSingleton <INotifyService, NotifyService>();
            services.AddSingleton <IClientManager, ClientManager>();
            services.AddSingleton <IHangfireService, HangfireService>();
            services.AddSingleton <IRedisService, RedisService>();
            services.AddSingleton <IPerformContextAdapter, PerformContextAdapter>();
            services.AddSingleton <ICallbackBookingService, CallbackBookingService>();
            services.AddSingleton <IEnv>(env);

            var connectionString = DbConfiguration.DatabaseConnectionString(env);

            services.AddDbContext <GetIntoTeachingDbContext>(b => DbConfiguration.ConfigPostgres(connectionString, b));

            services.AddAuthentication("ApiClientHandler")
            .AddScheme <ApiClientSchemaOptions, ApiClientHandler>("ApiClientHandler", op => { });

            services.AddControllers(o =>
            {
                o.ModelBinderProviders.Insert(0, new TrimStringModelBinderProvider());
            })
            .AddFluentValidation(c =>
            {
                c.RegisterValidatorsFromAssemblyContaining <Startup>();
            })
            .AddJsonOptions(o =>
            {
                o.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
                o.JsonSerializerOptions.Converters.Add(new TrimStringJsonConverter());
                o.JsonSerializerOptions.Converters.Add(new EmptyStringToNullJsonConverter());
            });

            services.Configure <KestrelServerOptions>(options =>
            {
                // Workaround for https://github.com/dotnet/aspnetcore/issues/8302
                // caused by Prometheus.HttpMetrics.HttpRequestDurationMiddleware
                options.AllowSynchronousIO = true;
            });

            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc(
                    "v1",
                    new OpenApiInfo
                {
                    Title       = "Get into Teaching API - V1",
                    Version     = "v1",
                    Description = @"
Provides a RESTful API for integrating with the Get into Teaching CRM.

The Get into Teaching (GIT) API sits in front of the GIT CRM, which uses the [Microsoft Dynamics365](https://docs.microsoft.com/en-us/dynamics365/) platform (the [Customer Engagement](https://docs.microsoft.com/en-us/dynamics365/customerengagement/on-premises/developer/overview) module is used for storing Candidate information and the [Marketing](https://docs.microsoft.com/en-us/dynamics365/marketing/developer/using-events-api) module for managing Events).

The GIT API aims to provide:

* Simple, task-based RESTful APIs.
* Message queueing (while the GIT CRM is offline for updates).
* Validation to ensure consistency across services writing to the GIT CRM.
                        ",
                    License     = new OpenApiLicense
                    {
                        Name = "MIT License",
                        Url  = new Uri("https://opensource.org/licenses/MIT"),
                    },
                });

                c.AddSecurityDefinition("apiKey", new OpenApiSecurityScheme
                {
                    Type = SecuritySchemeType.ApiKey,
                    Name = "Authorization",
                    In   = ParameterLocation.Header,
                });

                c.OperationFilter <AuthOperationFilter>();
                c.EnableAnnotations();
                c.AddFluentValidationRules();
            });

            services.AddHangfire((provider, config) =>
            {
                var automaticRetry = new AutomaticRetryAttribute
                {
                    Attempts           = JobConfiguration.Attempts(env),
                    DelaysInSeconds    = new[] { JobConfiguration.RetryIntervalInSeconds(env) },
                    OnAttemptsExceeded = AttemptsExceededAction.Delete,
                };

                config
                .SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
                .UseSimpleAssemblyNameTypeSerializer()
                .UseRecommendedSerializerSettings()
                .UseFilter(automaticRetry);

                if (env.IsTest)
                {
                    config.UseMemoryStorage().WithJobExpirationTimeout(JobConfiguration.ExpirationTimeout);
                }
                else
                {
                    config.UsePostgreSqlStorage(DbConfiguration.HangfireConnectionString(env));
                }
            });
        }
Пример #13
0
        public void OnStateElection_ChangesStateToDeleted_IfRetryAttemptsNumberExceededAndOnAttemptsExceededIsSetToDelete()
        {
            _connection.Setup(x => x.GetJobParameter(JobId, "RetryCount")).Returns("1");
            var filter = new AutomaticRetryAttribute { Attempts = 1, OnAttemptsExceeded = AttemptsExceededAction.Delete };

            filter.OnStateElection(_context.Object);

            Assert.IsType<DeletedState>(_context.Object.CandidateState);
        }
Пример #14
0
 public void Ctor_SetsOnAttemptsExceededAction_ByDefault()
 {
     var filter = new AutomaticRetryAttribute();
     Assert.Equal(AttemptsExceededAction.Fail, filter.OnAttemptsExceeded);
 }
Пример #15
0
        public void Ctor_DelayByAttemptIsNotNull_ByDefault()
        {
            var filter = new AutomaticRetryAttribute();

            Assert.NotNull(filter.DelayInSecondsByAttemptFunc);
        }
Пример #16
0
        public void Ctor_SetsOnAttemptsExceededAction_ByDefault()
        {
            var filter = new AutomaticRetryAttribute();

            Assert.Equal(AttemptsExceededAction.Fail, filter.OnAttemptsExceeded);
        }
Пример #17
0
 public void Ctor_SetsPositiveRetryAttemptsNumber_ByDefault()
 {
     var filter = new AutomaticRetryAttribute();
     Assert.Equal(10, filter.Attempts);
 }
Пример #18
0
 /// <summary>
 /// Initialises a new instance of the <see cref="TaskAutomaticRetryJobFilter" /> class.
 /// </summary>
 /// <param name="defaultAutomaticRetryAttribute">The default registered <see cref="AutomaticRetryAttribute" /> that
 /// will be applied.</param>
 public TaskAutomaticRetryJobFilter(AutomaticRetryAttribute defaultAutomaticRetryAttribute)
 {
     this._defaultAutomaticRetryAttribute = defaultAutomaticRetryAttribute;
 }