// Called by the Durable client binding infrastructure
        public DurabilityProvider GetDurabilityProvider(DurableClientAttribute attribute)
        {
            // TODO: Much of this logic should go into the base class
            if (string.IsNullOrEmpty(attribute.ConnectionName) &&
                string.IsNullOrEmpty(attribute.TaskHub))
            {
                return(this.GetDurabilityProvider());
            }

            lock (this.clientProviders)
            {
                string key = GetDurabilityProviderKey(attribute);
                if (this.clientProviders.TryGetValue(key, out DurabilityProvider clientProvider))
                {
                    return(clientProvider);
                }

                SqlDurabilityOptions        clientOptions = this.GetSqlOptions(attribute);
                IOrchestrationServiceClient serviceClient =
                    new SqlOrchestrationService(clientOptions.GetOrchestrationServiceSettings(
                                                    this.extensionOptions,
                                                    this.connectionStringResolver));
                clientProvider = new SqlDurabilityProvider(
                    this.GetOrchestrationService(),
                    clientOptions,
                    serviceClient);

                this.clientProviders.Add(key, clientProvider);
                return(clientProvider);
            }
        }
Example #2
0
        public async Task ScaleRecommendation_PendingActivities(int activityCount, int expectedRecommendation)
        {
            // Block the activity dispatch loop so that we can queue activities without running them
            this.testService.OrchestrationServiceMock.Setup(
                svc => svc.LockNextTaskActivityWorkItem(
                    It.IsAny <TimeSpan>(),
                    It.IsAny <CancellationToken>()))
            .Returns(() => Task.Delay(100).ContinueWith(t => default(TaskActivityWorkItem)));

            // We can influence the recommended replica count by modifying concurrency settings
            this.testService.OrchestrationServiceOptions.MaxConcurrentActivities = 3;
            await this.testService.StartWorkerAsync();

            SqlOrchestrationService orchestrationService = this.testService.OrchestrationServiceMock.Object;

            // Initial scale recommendation should be zero
            int recommendation = await orchestrationService.GetRecommendedReplicaCountAsync();

            Assert.Equal(0, recommendation);

            TestInstance <string> instance = await this.testService.RunOrchestration <string[], string>(
                null,
                orchestrationName : "OrchestrationWithActivityFanOut",
                implementation : (ctx, _) =>
            {
                return(Task.WhenAll(Enumerable.Range(0, activityCount).Select(i => ctx.ScheduleTask <string>("ToString", "", i)).ToArray()));
            },
                activities : new[] {
Example #3
0
 public SqlDurabilityProvider(
     SqlOrchestrationService service,
     SqlDurabilityOptions durabilityOptions)
     : base(Name, service, service, durabilityOptions.ConnectionStringName)
 {
     this.service           = service ?? throw new ArgumentNullException(nameof(service));
     this.durabilityOptions = durabilityOptions;
 }
        // Called by the Durable trigger binding infrastructure
        public DurabilityProvider GetDurabilityProvider()
        {
            if (this.defaultProvider == null)
            {
                SqlDurabilityOptions    sqlProviderOptions = this.GetDefaultSqlOptions();
                SqlOrchestrationService service            = this.GetOrchestrationService();
                this.defaultProvider = new SqlDurabilityProvider(service, sqlProviderOptions);
            }

            return(this.defaultProvider);
        }
Example #5
0
        public async Task ScaleRecommendation_PendingOrchestrationStarts()
        {
            // Block the orchestration dispatch loop so that we can queue orchestrations without running them
            this.testService.OrchestrationServiceMock.Setup(
                svc => svc.LockNextTaskOrchestrationWorkItemAsync(
                    It.IsAny <TimeSpan>(),
                    It.IsAny <CancellationToken>()))
            .Returns(() => Task.Delay(100).ContinueWith(t => default(TaskOrchestrationWorkItem)));

            // We can influence the recommended replica count by modifying concurrency settings
            this.testService.OrchestrationServiceOptions.MaxActiveOrchestrations = 1;
            await this.testService.StartWorkerAsync();

            SqlOrchestrationService orchestrationService = this.testService.OrchestrationServiceMock.Object;

            // Initial scale recommendation should be zero
            int recommendation = await orchestrationService.GetRecommendedReplicaCountAsync();

            Assert.Equal(0, recommendation);

            for (int i = 1; i <= 10; i++)
            {
                // Schedule an orchestration (it won't run, see above)
                await this.testService.RunOrchestration(
                    null as string,
                    $"EmptyOrchestration{i:00}",
                    implementation : (ctx, input) => Task.FromResult(input));

                // Scale recommendation increments with every new scheduled orchestration.
                // We pass in the previous recommendation to generate a log statement about the change.
                recommendation = await orchestrationService.GetRecommendedReplicaCountAsync(recommendation);

                Assert.Equal(i, recommendation);
            }

            // Validate the logs
            IReadOnlyList <LogEntry> recommendationChangeLogs = this.GetRecommendationChangeLogs();

            Assert.Equal(10, recommendationChangeLogs.Count);

            for (int i = 0; i < recommendationChangeLogs.Count; i++)
            {
                LogEntry log = recommendationChangeLogs[i];
                LogAssert.FieldEquals(log, "CurrentCount", i);
                LogAssert.FieldEquals(log, "RecommendedCount", i + 1);
            }
        }
Example #6
0
 public SqlScaleMonitor(SqlOrchestrationService service, string taskHubName)
 {
     this.service    = service ?? throw new ArgumentNullException(nameof(service));
     this.Descriptor = new ScaleMonitorDescriptor($"DurableTask-SqlServer:{taskHubName ?? "default"}");
 }
 public static async Task InitializeDatabaseAsync()
 {
     var options = new SqlOrchestrationServiceSettings(GetDefaultConnectionString());
     var service = new SqlOrchestrationService(options);
     await service.CreateIfNotExistsAsync();
 }