public static async Task <bool> ProjectCommandSerializationActivity(
            [ActivityTrigger] ProjectCommandNotification notification,
            [DurableClient] IDurableClient durableClient)
        {
            if (notification is null)
            {
                throw new ArgumentNullException(nameof(notification));
            }

            if (durableClient is null)
            {
                throw new ArgumentNullException(nameof(durableClient));
            }

            var status = await durableClient
                         .GetStatusAsync(notification.CorrelationId.ToString())
                         .ConfigureAwait(false);

            if (!status.IsFinalRuntimeStatus())
            {
                _ = await durableClient
                    .StartNewAsync(nameof(ProjectCommandMonitoring.ProjectCommandMonitoringOrchestrator), notification)
                    .ConfigureAwait(false);

                return(true); // command monitoring started
            }

            return(false); // no command monitoring started
        }
        public static async Task <bool> ProjectCommandMonitoringActivity(
            [ActivityTrigger] ProjectCommandNotification notification,
            [DurableClient] IDurableClient durableClient)
        {
            if (notification is null)
            {
                throw new ArgumentNullException(nameof(notification));
            }

            var status = await durableClient
                         .GetStatusAsync(notification.CorrelationId.ToString())
                         .ConfigureAwait(false);

            if (status?.IsFinalRuntimeStatus() ?? true)
            {
                // no status available or final status reached

                await durableClient
                .RaiseEventAsync(notification.InstanceId, notification.CorrelationId.ToString())
                .ConfigureAwait(true);

                return(false); // orchestration is not active
            }
            else
            {
                // orchestation has not reached final state

                return(true); // orchstration is active
            }
        }
        public static async Task ProjectCommandSerializationOrchestrator(
            [OrchestrationTrigger] IDurableOrchestrationContext context,
            ILogger log)
        {
            if (context is null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            var command = context.GetInput <ICommand>();

            if (command.ProjectId.HasValue)
            {
                var commandEntityId     = new EntityId(nameof(ProjectCommandSerializationEntity), command.ProjectId.ToString());
                var commandDependencyId = default(string);

                using (await context.LockAsync(commandEntityId).ConfigureAwait(true))
                {
                    // register the new command is a critical section and needs a lock
                    // if there's an dependency it's guid is returned; otherwise null

                    commandDependencyId = await context
                                          .CallEntityAsync <string>(commandEntityId, null, command)
                                          .ConfigureAwait(true);
                }

                if (Guid.TryParse(commandDependencyId, out var correlationId))
                {
                    var notification = new ProjectCommandNotification()
                    {
                        InstanceId    = context.InstanceId,
                        CorrelationId = correlationId
                    };

                    var waitForExternalEvent = await context
                                               .CallActivityAsync <bool>(nameof(ProjectCommandSerializationActivity), notification)
                                               .ConfigureAwait(true);

                    if (waitForExternalEvent)
                    {
                        context
                        .CreateReplaySafeLogger(log)
                        .LogWarning($"{notification.InstanceId} - Waiting for command {notification.CorrelationId}");

                        await context
                        .WaitForExternalEvent(notification.CorrelationId.ToString())
                        .ConfigureAwait(true);

                        context
                        .CreateReplaySafeLogger(log)
                        .LogWarning($"{notification.InstanceId} - Resuming");
                    }
                }
            }
        }