Example #1
0
    public override async Task <ICommandResult> HandleAsync(ICommand command, IAsyncCollector <ICommand> commandQueue, IDurableOrchestrationContext orchestrationContext, ILogger log)
    {
        if (command is null)
        {
            throw new ArgumentNullException(nameof(command));
        }

        var commandResult = command.CreateResult();

        try
        {
            if (CanHandle(command))
            {
                var containerDocument = (IContainerDocument)command.Payload;

                using var loggerFactory  = new PassthroughLoggerFactory(log);
                using var serviceManager = CreateServiceManager();

                var broadcastMessage = new BroadcastMessage()
                {
                    Action    = commandResult.CommandAction.ToString().ToLowerInvariant(),
                    Timestamp = commandResult.LastUpdatedTime.GetValueOrDefault(DateTime.UtcNow),
                    Items     = GetItems(containerDocument)
                };

                var broadcastPayload = TeamCloudSerialize.SerializeObject(broadcastMessage);

                await foreach (var hubName in ResolveHubNamesAsync(containerDocument))
                {
                    var hubContext = await serviceManager
                                     .CreateHubContextAsync(hubName, CancellationToken.None)
                                     .ConfigureAwait(false);

                    var negotiation = await hubContext
                                      .NegotiateAsync()
                                      .ConfigureAwait(false);

                    await hubContext.Clients.All
                    .SendAsync(command.CommandAction.ToString(), broadcastMessage)
                    .ConfigureAwait(false);
                }
            }
            else
            {
                throw new NotImplementedException($"Missing orchestrator command handler implementation ICommandHandler<{command.GetTypeName(prettyPrint: true)}> at {GetType()}");
            }
        }
        catch (Exception exc)
        {
            commandResult.Errors.Add(exc);
        }

        return(commandResult);

        async IAsyncEnumerable <string> ResolveHubNamesAsync(object commandResultPayload)
        {
            yield return(commandResultPayload switch
            {
                IProjectContext projectContext => projectContext.GetHubName(),
                IOrganizationContext organizationContext => organizationContext.GetHubName(),
                Organization organization => organization.GetHubName(),
                _ => throw new NotSupportedException($"Unable to resolve hub name for command result payload of type '{commandResultPayload?.GetType()}'.")
            });

            if (commandResultPayload is User user)
            {
                foreach (var membership in user.ProjectMemberships)
                {
                    var project = await projectRepository
                                  .GetAsync(user.Organization, membership.ProjectId)
                                  .ConfigureAwait(false);

                    yield return(project.GetHubName());
                }
            }
        }