Пример #1
0
        public static async Task TriggeredSequenceTask1(
            [BlobTrigger("tasks/step/{iteration}/{instanceId}")] Stream inputStream,
            [Blob("tasks/step")] Microsoft.WindowsAzure.Storage.Blob.CloudBlobDirectory directory,
            [DurableClient] IDurableClient client,
            string instanceId,
            ILogger logger)
        {
            Input input;

            using (var streamReader = new StreamReader(inputStream))
                input = JsonConvert.DeserializeObject <Input>(await streamReader.ReadToEndAsync());

            input = RunTask(input, logger, instanceId);

            if (input.Position < input.Length)
            {
                // write the blob to trigger the next task
                string content = JsonConvert.SerializeObject(input);
                var    blob    = directory.GetBlockBlobReference($"{input.Position}/{instanceId}");
                await blob.UploadTextAsync(content);
            }
            else
            {
                // notify the waiting orchestrator
                await client.RaiseEventAsync(instanceId, "completed", input);
            }
        }
Пример #2
0
 public async Task NotifyLongRunningProcessDone(
     [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "JobDone/{instanceId}")] HttpRequestMessage req,
     [DurableClient] IDurableClient client,
     string instanceId)
 {
     await client.RaiseEventAsync(instanceId, "LongRunningJobDone");
 }
Пример #3
0
        private static async Task <IActionResult> GetMethod(
            IAsyncCollector <string> console,
            IDurableClient client,
            string name,
            string target,
            DataAccess <User> userClient,
            User userCheck,
            DataAccess <Room> roomClient,
            DataAccess <Inventory> inventoryClient)
        {
            if (string.IsNullOrEmpty(target))
            {
                await console.AddAsync($"User {name} tried to get nothing.");

                return(new BadRequestObjectResult("Target is required."));
            }
            var room = (await roomClient.GetAllAsync(name))[0];

            if (room.InventoryList.Contains(target))
            {
                room.InventoryList.Remove(target);
                await roomClient.ReplaceAsync(room);

                userCheck.InventoryList.Add(target);
                await userClient.ReplaceAsync(userCheck);

                var inventory = await inventoryClient.GetAsync(name, target);

                inventory.Room = string.Empty;
                await inventoryClient.ReplaceAsync(inventory);

                await console.AddAsync($"User {name} successfully grabbed {target}.");

                if (inventory.IsTreasure)
                {
                    await console.AddAsync($"User {name} nabbed the treasure.");

                    var gameMonitor = await Global.FindJob(
                        client,
                        DateTime.UtcNow,
                        nameof(MonitorFunctions.GameMonitorWorkflow),
                        name,
                        true,
                        false);

                    if (gameMonitor != null)
                    {
                        await client.RaiseEventAsync(gameMonitor.InstanceId,
                                                     MonitorFunctions.GOTTREASURE);
                    }
                }
                return(new OkResult());
            }
            else
            {
                await console.AddAsync($"User {name} tried to get a {target} that wasn't there.");

                return(new BadRequestObjectResult("Target not found."));
            }
        }
Пример #4
0
        public static async Task <IActionResult> Finish(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "Finish/{id}")] HttpRequest req,
            string id,
            [DurableClient] IDurableClient client,
            ILogger log)
        {
            log.LogInformation("Request to close to registry {id}.", id);

            // id is required on route Finish/{id}
            if (string.IsNullOrWhiteSpace(id))
            {
                return(new BadRequestObjectResult("Id is required after Finish/ on the route."));
            }

            // confirm a workflow exists
            var instance = await client.GetStatusAsync(id);

            // not there
            if (instance == null)
            {
                return(new BadRequestObjectResult($"Unable to find workflow with id {id}"));
            }

            // not running
            if (instance.RuntimeStatus != OrchestrationRuntimeStatus.Running)
            {
                return(new BadRequestObjectResult($"Instance {id} is not active."));
            }

            // signal to close
            await client.RaiseEventAsync(id, CLOSE_TASK, true);

            return(new OkResult());
        }
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] FraudResult fraudResult,
            [DurableClient] IDurableClient client,
            ILogger log)
        {
            var entityId = new EntityId(
                nameof(FraudDetectionOrchestratorEntity),
                fraudResult.RecordId);

            var entityStateResponse = await client.ReadEntityStateAsync <FraudDetectionOrchestratorEntity>(entityId);

            if (entityStateResponse.EntityExists)
            {
                await client.RaiseEventAsync(
                    entityStateResponse.EntityState.InstanceId,
                    Constants.FraudResultCompletedEvent,
                    fraudResult.IsSuspiciousTransaction);

                return(new AcceptedResult());
            }
            else
            {
                return(new BadRequestObjectResult($"Entity {entityId} does not exist."));
            }
        }
Пример #6
0
        public static async Task <bool> RunActivity(
            [ActivityTrigger] ProjectCommandNotification notification,
            [DurableClient] IDurableClient durableClient)
        {
            if (notification is null)
            {
                throw new ArgumentNullException(nameof(notification));
            }

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

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

                await durableClient
                .RaiseEventAsync(notification.PendingInstanceId, notification.ActiveCommandId.ToString())
                .ConfigureAwait(true);

                return(false); // orchestration is not active
            }

            return(true); // orchstration is active (has not reached final state)
        }
        public static async Task <IActionResult> Run(
            [HttpTrigger(
                 AuthorizationLevel.Function,
                 nameof(HttpMethod.Post),
                 Route = null)] HttpRequestMessage message,
            [DurableClient] IDurableClient client,
            ILogger logger)
        {
            var phoneNumber = await message.Content.ReadAsAsync <string>();

            var entityId       = new EntityId(nameof(NotificationOrchestratorInstanceEntity), phoneNumber);
            var instanceEntity = await client.ReadEntityStateAsync <NotificationOrchestratorInstanceEntity>(entityId);

            if (instanceEntity.EntityExists)
            {
                await client.RaiseEventAsync(
                    instanceEntity.EntityState.InstanceId,
                    EventNames.Callback,
                    true);
            }
            else
            {
                logger.LogError($"=== No instanceId found for {phoneNumber}. ===");
            }

            return(new AcceptedResult());
        }
Пример #8
0
        public static async Task ResetTimeoutAsync(this IDurableClient client, EntityId instanceId)
        {
            var status = await client.GetStatusAsync(instanceId.EntityKey);

            if (status != null && status.RuntimeStatus == OrchestrationRuntimeStatus.Running)
            {
                await client.RaiseEventAsync(instanceId.EntityKey, "TimeoutReset");
            }
            else
            {
                await client.StartNewAsync(nameof(StartTimeoutAsync), instanceId.EntityKey);
            }
        }
Пример #9
0
        public async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = "sendevent/{instanceId}/")]
            HttpRequestMessage req,
            string instanceId,
            [DurableClient] IDurableClient client,
            ILogger logger)
        {
            var approval = await req.Content.ReadAsAsync <Approval>();

            await client.RaiseEventAsync(instanceId, approval.EventName, approval.IsApproved);

            return(new AcceptedResult());
        }
        public static async Task <IActionResult> ConfirmUser(
            [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)]
            HttpRequest req,
            [Queue(Global.QUEUE)] IAsyncCollector <string> console,
            [Table(nameof(User))] CloudTable table,
            [DurableClient] IDurableClient durableClient,
            ILogger log)
        {
            log.LogInformation("ConfirmUser called.");

            string  requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            dynamic data        = JsonConvert.DeserializeObject(requestBody);
            string  name        = data?.name;

            if (string.IsNullOrWhiteSpace(name))
            {
                await console.AddAsync("An attempt to confirm a user with no name was made.");

                return(new BadRequestObjectResult("User name is required."));
            }

            var client   = table.AsClientFor <User>();
            var tempUser = new User {
                Name = name
            };
            var userCheck = await client.GetAsync(tempUser.PartitionKey, name);

            if (userCheck == null)
            {
                await console.AddAsync($"Attempt to confirm missing user {name} failed.");

                return(new BadRequestObjectResult("Username does not exist."));
            }

            log.LogInformation("User {user} is valid, searching for workflow.", name);

            var instance = await durableClient.FindJob(
                DateTime.UtcNow,
                nameof(UserConfirmationWorkflow),
                name);

            if (instance == null)
            {
                log.LogInformation("Workflow not found for user {user}.", name);
                return(new NotFoundResult());
            }
            log.LogInformation("Workflow with id {instanceId} found for user {user}.", instance.InstanceId, name);
            await durableClient.RaiseEventAsync(instance.InstanceId, APPROVAL_TASK, true);

            return(new OkResult());
        }
Пример #11
0
        public static async Task <IActionResult> ConfirmOperation(
            [HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequest req,
            [Queue(Global.QUEUE)] IAsyncCollector <string> console,
            [Table(nameof(CreditOperation))] CloudTable table,
            [DurableClient] IDurableClient durableClient,
            ILogger log)
        {
            log.LogInformation("ConfirmOperation called.");

            string  requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            dynamic data        = JsonConvert.DeserializeObject(requestBody);
            string  operation   = data?.operation;

            if (string.IsNullOrWhiteSpace(operation))
            {
                await console.AddAsync("An attempt to confirm a operation without an identifier was made.");

                return(new BadRequestObjectResult("Operation Identifier is required."));
            }

            var queryResult = await table.ExecuteAsync(TableOperation.Retrieve <CreditOperation>(operation, operation));

            var creditOperation = (CreditOperation)queryResult.Result;

            if (creditOperation == null)
            {
                await console.AddAsync($"Attempt to confirm missing operation {operation} failed.");

                return(new BadRequestObjectResult("Operation does not exist."));
            }

            creditOperation.Confirm();
            await table.ExecuteAsync(TableOperation.Replace(creditOperation));

            log.LogInformation("Operation {operation} is valid, searching for confirmation workflow.", creditOperation.Identifier);

            var instance = await durableClient.FindJob(
                DateTime.UtcNow,
                nameof(CreditConfirmationWorkflow),
                creditOperation);

            if (instance == null)
            {
                log.LogInformation("Confirmation workflow not found for operation {operation}.", creditOperation.Identifier);
                return(new NotFoundResult());
            }
            log.LogInformation("Confirmation workflow with id {instanceId} found for operation {operation}.", instance.InstanceId, creditOperation.Identifier);
            await durableClient.RaiseEventAsync(instance.InstanceId, CONFIRM_TASK, true);

            return(new OkResult());
        }
Пример #12
0
 public static async Task AcknowledgeTripViaQueueTrigger(
     [DurableClient] IDurableClient context,
     [QueueTrigger("%TripDriversQueue%", Connection = "AzureWebJobsStorage")] TripDriver info,
     ILogger log)
 {
     try
     {
         await context.RaiseEventAsync(info.TripCode, Constants.TRIP_DRIVER_ACCEPT_EVENT, info.DriverCode);
     }
     catch (Exception ex)
     {
         var error = $"AcknowledgeTripViaQueueTrigger failed: {ex.Message}";
         log.LogError(error);
     }
 }
Пример #13
0
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = "callback/{instanceId}")] HttpRequest request,
            [DurableClient] IDurableClient durableClient,
            string instanceId,
            ILogger log)
        {
            var commandResultJson = await request.ReadAsStringAsync().ConfigureAwait(false);

            var commandResult = JsonConvert.DeserializeObject <ICommandResult>(commandResultJson);

            await durableClient
            .RaiseEventAsync(instanceId, commandResult.CommandId.ToString(), commandResult)
            .ConfigureAwait(false);

            return(new OkResult());
        }
Пример #14
0
        public static async Task <IActionResult> AcknowledgeTrip([HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "tripmanagers/{code}/acknowledge/drivers/{drivercode}")] HttpRequest req,
                                                                 [DurableClient] IDurableClient context,
                                                                 string code,
                                                                 string drivercode,
                                                                 ILogger log)
        {
            try
            {
                await context.RaiseEventAsync(code, Constants.TRIP_DRIVER_ACCEPT_EVENT, drivercode);

                return((ActionResult) new OkObjectResult("Ok"));
            }
            catch (Exception ex)
            {
                var error = $"AcknowledgeTrip failed: {ex.Message}";
                log.LogError(error);
                return(new BadRequestObjectResult(error));
            }
        }
Пример #15
0
        public static async Task Run(
            [EntityTrigger] IDurableEntityContext entityContext,
            [DurableClient] IDurableClient durableClient,
            ILogger log)
        {
            await entityContext.DispatchAsync <VotingEntity>();

            log.LogWarning($"Entity_Voting_Run#{entityContext.EntityId}: Executing {entityContext.OperationName}");

            var state = entityContext.GetState <VotingEntity>();

            if (state.Yea >= state.MinimumInFavor && !state.EventRaised)
            {
                log.LogWarning($"Entity_Voting_Run#{entityContext.EntityId}: Raising event Voting_Event_Accepted");

                await durableClient.RaiseEventAsync(entityContext.EntityKey, "Voting_Event_Accepted");

                state.EventRaised = true;

                entityContext.SetState(state);
            }
        }
Пример #16
0
        public static async Task QueueSequenceTask1(
            [QueueTrigger("sequence")] string serialized,
            [Queue("sequence")] CloudQueue queue,
            [DurableClient] IDurableClient client,
            ILogger logger)
        {
            Input input = JsonConvert.DeserializeObject <Input>(serialized);

            input = RunTask(input, logger, input.InstanceId);

            if (input.Position < input.Length)
            {
                // write to the queue to trigger the next task
                string content = JsonConvert.SerializeObject(input);
                await queue.AddMessageAsync(new CloudQueueMessage(content));
            }
            else
            {
                // notify the waiting orchestrator
                await client.RaiseEventAsync(input.InstanceId, "completed", input);
            }
        }
Пример #17
0
        public static async Task <IActionResult> RespondToAppointment(
            [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "appointments/{appointmentId}")] HttpRequest request,
            string appointmentId,
            [DurableClient] IDurableClient durableClient,
            ILogger log)
        {
            var status = Enum.Parse <AppointmentStatusEnum>(await request.ReadAsStringAsync());

            if (status == AppointmentStatusEnum.Pending)
            {
                return(new BadRequestResult());
            }

            // Transforming client's response into an Event
            var response = new AppointmentResponse
            {
                NickName   = request.Headers[NickNameHeaderName],
                IsAccepted = (status == AppointmentStatusEnum.Accepted)
            };
            await durableClient.RaiseEventAsync(appointmentId, nameof(RespondToAppointment), response);

            return(new OkResult());
        }
        public static async Task <HttpResponseMessage> TriggerHttpApprovalProcessor(
            [HttpTrigger(AuthorizationLevel.Anonymous, methods: "get", Route = "approval")] HttpRequestMessage req,
            [DurableClient] IDurableClient orchestrationClient, ILogger logger)
        {
            logger.LogInformation($"Received an Approval Respose");
            string instanceId = req.RequestUri.ParseQueryString().GetValues("instanceid")[0];
            string response   = req.RequestUri.ParseQueryString().GetValues("response")[0];

            bool isApproved = false;

            var status = await orchestrationClient.GetStatusAsync(instanceId);

            logger.LogInformation($"Orchestration status: {status}");

            if (status != null && (status.RuntimeStatus == OrchestrationRuntimeStatus.Running || status.RuntimeStatus == OrchestrationRuntimeStatus.Pending))
            {
                if (response.ToLower() == "approved")
                {
                    isApproved = true;
                }

                await orchestrationClient.RaiseEventAsync(instanceId, "ReceiveApprovalResponse", isApproved);

                return(new HttpResponseMessage(HttpStatusCode.OK)
                {
                    Content = new StringContent(isApproved ? "APPROVED!" : "REJECTED!")
                });
            }
            else
            {
                return(new HttpResponseMessage(HttpStatusCode.BadRequest)
                {
                    Content = new StringContent("OOPS!")
                });
            }
        }
        public static async Task <IActionResult> ConfirmEmail(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "ConfirmEmail/{id}")] HttpRequest request,
            [DurableClient] IDurableClient client,
            [Table("EmailConfirmations", EmailConfirmationTableEntity.PartitionKeyValue, "{id}")] EmailConfirmationTableEntity tableEntity,
            ILogger log)
        {
            if (tableEntity is null)
            {
                return(new BadRequestObjectResult("Invalid request."));
            }
            else if (tableEntity.Result != "Sent")
            {
                return(new OkObjectResult("The email is already confirmed."));
            }

            string result = request.Query["result"]; // This is just an extra parameter.

            //--> Send confirmation external event to this orchestration.
            await client.RaiseEventAsync(tableEntity.OrchestrationId, _eventName, result);

            log.LogInformation("RaiseEvent called to confirm email.");

            return(new OkObjectResult("Email confirmed."));
        }
Пример #20
0
        public static async Task <IActionResult> PostOrchestration(
            // Using /a/p/i route prefix, to let Functions Host distinguish api methods from statics
            [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "a/p/i/orchestrations('{instanceId}')/{action?}")] HttpRequest req,
            string instanceId,
            string action,
            [DurableClient(TaskHub = "%DFM_HUB_NAME%")] IDurableClient durableClient)
        {
            // Checking that the call is authenticated properly
            try
            {
                Globals.ValidateIdentity(req.HttpContext.User, req.Headers);
            }
            catch (UnauthorizedAccessException ex)
            {
                return(new OkObjectResult(ex.Message)
                {
                    StatusCode = 401
                });
            }

            string bodyString = await req.ReadAsStringAsync();

            switch (action)
            {
            case "purge":
                await durableClient.PurgeInstanceHistoryAsync(instanceId);

                break;

            case "rewind":
                await durableClient.RewindAsync(instanceId, bodyString);

                break;

            case "terminate":
                await durableClient.TerminateAsync(instanceId, bodyString);

                break;

            case "raise-event":
                dynamic bodyObject = JObject.Parse(bodyString);
                string  eventName  = bodyObject.name;
                JObject eventData  = bodyObject.data;

                await durableClient.RaiseEventAsync(instanceId, eventName, eventData);

                break;

            case "set-custom-status":

                string connectionString = Environment.GetEnvironmentVariable(EnvVariableNames.AzureWebJobsStorage);
                string hubName          = Environment.GetEnvironmentVariable(EnvVariableNames.DFM_HUB_NAME);

                // Updating the table directly, as there is no other known way
                var tableClient = CloudStorageAccount.Parse(connectionString).CreateCloudTableClient();
                var table       = tableClient.GetTableReference($"{hubName}Instances");

                var orcEntity = (await table.ExecuteAsync(TableOperation.Retrieve(instanceId, string.Empty))).Result as DynamicTableEntity;

                if (string.IsNullOrEmpty(bodyString))
                {
                    orcEntity.Properties.Remove("CustomStatus");
                }
                else
                {
                    // Ensuring that it is at least a valid JSON
                    string customStatus = JObject.Parse(bodyString).ToString();
                    orcEntity.Properties["CustomStatus"] = new EntityProperty(customStatus);
                }

                await table.ExecuteAsync(TableOperation.Replace(orcEntity));

                break;

            default:
                return(new NotFoundResult());
            }

            return(new OkResult());
        }
        public static async Task <IActionResult> DfmPostOrchestrationFunction(
            [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = Globals.ApiRoutePrefix + "/orchestrations('{instanceId}')/{action?}")] HttpRequest req,
            string instanceId,
            string action,
            [DurableClient(TaskHub = Globals.TaskHubRouteParamName)] IDurableClient durableClient,
            ILogger log)
        {
            // Checking that the call is authenticated properly
            try
            {
                await Auth.ValidateIdentityAsync(req.HttpContext.User, req.Headers, durableClient.TaskHubName);
            }
            catch (Exception ex)
            {
                log.LogError(ex, "Failed to authenticate request");
                return(new UnauthorizedResult());
            }

            // Checking that we're not in ReadOnly mode
            if (DfmEndpoint.Settings.Mode == DfmMode.ReadOnly)
            {
                log.LogError("Endpoint is in ReadOnly mode");
                return(new StatusCodeResult(403));
            }

            string bodyString = await req.ReadAsStringAsync();

            switch (action)
            {
            case "purge":
                await durableClient.PurgeInstanceHistoryAsync(instanceId);

                break;

            case "rewind":
                await durableClient.RewindAsync(instanceId, bodyString);

                break;

            case "terminate":
                await durableClient.TerminateAsync(instanceId, bodyString);

                break;

            case "raise-event":

                dynamic bodyObject = JObject.Parse(bodyString);
                string  eventName  = bodyObject.name;
                JObject eventData  = bodyObject.data;

                var match = ExpandedOrchestrationStatus.EntityIdRegex.Match(instanceId);
                // if this looks like an Entity
                if (match.Success)
                {
                    // then sending signal
                    var entityId = new EntityId(match.Groups[1].Value, match.Groups[2].Value);

                    await durableClient.SignalEntityAsync(entityId, eventName, eventData);
                }
                else
                {
                    // otherwise raising event
                    await durableClient.RaiseEventAsync(instanceId, eventName, eventData);
                }

                break;

            case "set-custom-status":

                // Updating the table directly, as there is no other known way
                var table = TableClient.GetTableClient().GetTableReference($"{durableClient.TaskHubName}Instances");

                var orcEntity = (await table.ExecuteAsync(TableOperation.Retrieve(instanceId, string.Empty))).Result as DynamicTableEntity;

                if (string.IsNullOrEmpty(bodyString))
                {
                    orcEntity.Properties.Remove("CustomStatus");
                }
                else
                {
                    // Ensuring that it is at least a valid JSON
                    string customStatus = JObject.Parse(bodyString).ToString();
                    orcEntity.Properties["CustomStatus"] = new EntityProperty(customStatus);
                }

                await table.ExecuteAsync(TableOperation.Replace(orcEntity));

                break;

            case "restart":
                bool restartWithNewInstanceId = ((dynamic)JObject.Parse(bodyString)).restartWithNewInstanceId;

                await durableClient.RestartAsync(instanceId, restartWithNewInstanceId);

                break;

            default:
                return(new NotFoundResult());
            }

            return(new OkResult());
        }
Пример #22
0
        public static async Task <IActionResult> RunTrigger(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = "callback/{instanceId}/{eventName}")] HttpRequest httpRequest,
            [DurableClient] IDurableClient durableClient,
            string instanceId,
            string eventName,
            ILogger log)
        {
            if (httpRequest is null)
            {
                throw new ArgumentNullException(nameof(httpRequest));
            }

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

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

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

            ICommandResult commandResult;

            try
            {
                using var reader = new StreamReader(httpRequest.Body);

                var requestBody = await reader
                                  .ReadToEndAsync()
                                  .ConfigureAwait(false);

                commandResult = JsonConvert.DeserializeObject <ICommandResult>(requestBody);
            }
            catch (Exception exc)
            {
                log.LogError(exc, $"Callback '{instanceId}' ({eventName}) - Failed to deserialize callback payload");

                return(new BadRequestResult());
            }

            try
            {
                var status = await durableClient
                             .GetStatusAsync(instanceId)
                             .ConfigureAwait(false);

                if (status?.RuntimeStatus.IsFinal() ?? true)
                {
                    // the orchestration does not exist or reached
                    // a final state - raising an external event
                    // doesn't make sense, but we need to response
                    // with an status code that indicates that
                    // another retry doesn't make sense.
                    // status code 410 (Gone) looks like a perfect fit

                    return(new StatusCodeResult((int)HttpStatusCode.Gone));
                }
                else
                {
                    await durableClient
                    .RaiseEventAsync(instanceId, eventName, commandResult)
                    .ConfigureAwait(false);
                }
            }
            catch (Exception exc)
            {
                log.LogError(exc, $"Callback '{instanceId}' ({eventName}) - Failed to raise event with payload {JsonConvert.SerializeObject(commandResult)}.");

                throw; // re-throw exception to return an internal server error
            }

            return(new OkResult());
        }
Пример #23
0
        private static async Task <IActionResult> GetMethod(
            IAsyncCollector <string> console,
            IDurableClient client,
            string name,
            string target)
        {
            if (string.IsNullOrEmpty(target))
            {
                await console.AddAsync($"User {name} tried to get nothing.");

                return(new BadRequestObjectResult("Target is required."));
            }
            var room = await name.GetEntityForUserOrThrow <Room>(client);

            if (room.InventoryList.Contains(target))
            {
                // room loses inventory
                await client.SignalEntityAsync <IRoomOperations>(
                    name.AsEntityIdFor <Room>(),
                    operation => operation.RemoveInventory(target));

                // user gains inventory
                await client.SignalEntityAsync <IUserOperations>(
                    name.AsEntityIdFor <User>(),
                    operation => operation.AddInventory(target));

                // inventory moves to user
                await client.SignalEntityAsync <IInventoryOperations>(
                    name.AsEntityIdFor <Inventory>(target),
                    operation => operation.SetUser());

                var list = await name.GetEntityForUserOrThrow <InventoryList>(client);

                var inventoryList = await list.DeserializeListForUserWithClient(name, client);

                var inventory = inventoryList.Where(i => i.Name == target)
                                .Select(i => i).First();

                await console.AddAsync($"User {name} successfully grabbed {target}.");

                if (inventory.IsTreasure)
                {
                    await console.AddAsync($"User {name} nabbed the treasure.");

                    var gameMonitor = await Global.FindJob(
                        client,
                        DateTime.UtcNow,
                        nameof(MonitorFunctions.GameMonitorWorkflow),
                        name,
                        true,
                        false);

                    if (gameMonitor != null)
                    {
                        await client.RaiseEventAsync(gameMonitor.InstanceId,
                                                     MonitorFunctions.GOTTREASURE);
                    }
                }
                return(new OkResult());
            }
            else
            {
                await console.AddAsync($"User {name} tried to get a {target} that wasn't there.");

                return(new BadRequestObjectResult("Target not found."));
            }
        }
Пример #24
0
        public static async System.Threading.Tasks.Task <HttpResponseMessage> RunAsync(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequestMessage req,
            [DurableClient] IDurableClient starter,
            ILogger log)
#endif
        {
            var     inputToFunction   = JToken.ReadFrom(new JsonTextReader(new StreamReader(await req.Content.ReadAsStreamAsync())));
            dynamic eventGridSoleItem = (inputToFunction as JArray)?.SingleOrDefault();

            if (eventGridSoleItem == null)
            {
                return(req.CreateCompatibleResponse(HttpStatusCode.BadRequest, @"Expecting only one item in the Event Grid message"));
            }

            if (eventGridSoleItem.eventType == @"Microsoft.EventGrid.SubscriptionValidationEvent")
            {
                log.LogTrace(@"Event Grid Validation event received.");
                return(req.CreateCompatibleResponse(HttpStatusCode.OK, $"{{ \"validationResponse\" : \"{((dynamic)inputToFunction)[0].data.validationCode}\" }}"));
            }

            CustomerBlobAttributes newCustomerFile = Helpers.ParseEventGridPayload(eventGridSoleItem, log);

            if (newCustomerFile == null)
            {   // The request either wasn't valid (filename couldn't be parsed) or not applicable (put in to a folder other than /inbound)
                return(req.CreateCompatibleResponse(HttpStatusCode.NoContent));
            }

            string customerName = newCustomerFile.CustomerName, name = newCustomerFile.Filename;

            starter.Log(log, $@"Processing new file. customer: {customerName}, filename: {name}");

            // get the prefix for the name so we can check for others in the same container with in the customer blob storage account
            var prefix = newCustomerFile.BatchPrefix;

            var instanceForPrefix = await starter.GetStatusAsync(prefix);

            if (instanceForPrefix == null)
            {
                starter.Log(log, $@"New instance needed for prefix '{prefix}'. Starting...");
                var retval = await starter.StartNewAsync(@"EnsureAllFiles", prefix, eventGridSoleItem);

                starter.Log(log, $@"Started. {retval}");
            }
            else
            {
                starter.Log(log, $@"Instance already waiting. Current status: {instanceForPrefix.RuntimeStatus}. Firing 'newfile' event...");

                if (instanceForPrefix.RuntimeStatus != OrchestrationRuntimeStatus.Running)
                {
                    await starter.TerminateAsync(prefix, @"bounce");

                    var retval = await starter.StartNewAsync(@"EnsureAllFiles", prefix, eventGridSoleItem);

                    starter.Log(log, $@"Restarted listener for {prefix}. {retval}");
                }
                else
                {
                    await starter.RaiseEventAsync(prefix, @"newfile", newCustomerFile.Filename);
                }
            }


            return(starter.CreateCheckStatusResponse(req, prefix));
        }
Пример #25
0
        private static async Task <IActionResult> KillMethod(
            IAsyncCollector <string> console,
            IDurableClient client,
            string name,
            string target,
            string with,
            User userCheck)
        {
            if (string.IsNullOrEmpty(target))
            {
                await console.AddAsync($"User {name} tried to kill nothing.");

                return(new BadRequestObjectResult("Target is required."));
            }
            if (string.IsNullOrEmpty(with))
            {
                await console.AddAsync($"User {name} tried to kill {target} with no weapon.");

                return(new BadRequestObjectResult("With is required."));
            }
            if (!userCheck.InventoryList.Contains(with))
            {
                await console.AddAsync($"User {name} tried to use a non-existing {with}.");

                return(new BadRequestObjectResult($"User doesn't have {with}"));
            }
            var monster = await name.GetEntityForUserOrThrow <Monster>(client);

            if (!monster.IsAlive)
            {
                await console.AddAsync($"User {name} tried to kill an already dead {target}.");

                return(new BadRequestObjectResult($"{target} is already dead."));
            }

            var monsterInventory = monster.InventoryList[0];
            var inventoryNames   = await name.GetEntityForUserOrThrow <InventoryList>(client);

            var room = await name.GetEntityForUserOrThrow <Room>(client);

            // monster dies
            await client.SignalEntityAsync <IMonsterOperations>(
                name.AsEntityIdFor <Monster>(),
                operation => operation.Kill());

            // monster drops inventory, inventory => room
            await client.SignalEntityAsync <IInventoryOperations>(
                name.AsEntityIdFor <Inventory>(monsterInventory),
                operation => operation.SetRoom(room.Name));

            // add inventory to room
            await client.SignalEntityAsync <IRoomOperations>(
                name.AsEntityIdFor <Room>(),
                operation => operation.AddInventory(monsterInventory));

            await console.AddAsync($"User {name} valiantly killed {target} with {with}.");

            await console.AddAsync($"User {name} notices {target} dropped a {monsterInventory}.");

            var gameMonitor = await Global.FindJob(
                client,
                DateTime.UtcNow,
                nameof(MonitorFunctions.GameMonitorWorkflow),
                name,
                true,
                false);

            if (gameMonitor != null)
            {
                await client.RaiseEventAsync(gameMonitor.InstanceId,
                                             MonitorFunctions.KILLMONSTER);
            }
            return(new OkResult());
        }
Пример #26
0
        private static async Task <IActionResult> KillMethod(
            IAsyncCollector <string> console,
            IDurableClient client,
            string name,
            string target,
            string with,
            User userCheck,
            DataAccess <Monster> monsterClient,
            DataAccess <Room> roomClient,
            DataAccess <Inventory> inventoryClient)
        {
            if (string.IsNullOrEmpty(target))
            {
                await console.AddAsync($"User {name} tried to kill nothing.");

                return(new BadRequestObjectResult("Target is required."));
            }
            if (string.IsNullOrEmpty(with))
            {
                await console.AddAsync($"User {name} tried to kill {target} with no weapon.");

                return(new BadRequestObjectResult("With is required."));
            }
            if (!userCheck.InventoryList.Contains(with))
            {
                await console.AddAsync($"User {name} tried to use a non-existing {with}.");

                return(new BadRequestObjectResult($"User doesn't have {with}"));
            }
            var monster = await monsterClient.GetAsync(name, target);

            if (monster == null)
            {
                await console.AddAsync($"User {name} tried to kill a ghost named {target}.");

                return(new BadRequestObjectResult($"{target} not found."));
            }
            if (!monster.IsAlive)
            {
                await console.AddAsync($"User {name} tried to kill an already dead {target}.");

                return(new BadRequestObjectResult($"{target} is already dead."));
            }
            var monsterInventory = monster.InventoryList[0];

            monster.InventoryList.Remove(monsterInventory);
            monster.IsAlive = false;
            await monsterClient.ReplaceAsync(monster);

            var room = (await roomClient.GetAllAsync(name))[0];

            room.InventoryList.Add(monsterInventory);
            await roomClient.ReplaceAsync(room);

            var inventory = await inventoryClient.GetAsync(name, monsterInventory);

            inventory.Monster = string.Empty;
            inventory.Room    = room.Name;
            await inventoryClient.ReplaceAsync(inventory);

            await console.AddAsync($"User {name} valiantly killed {target} with {with}.");

            await console.AddAsync($"User {name} notices {target} dropped a {monsterInventory}.");

            var gameMonitor = await Global.FindJob(
                client,
                DateTime.UtcNow,
                nameof(MonitorFunctions.GameMonitorWorkflow),
                name,
                true,
                false);

            if (gameMonitor != null)
            {
                await client.RaiseEventAsync(gameMonitor.InstanceId,
                                             MonitorFunctions.KILLMONSTER);
            }
            return(new OkResult());
        }