{"action":"created","issue":{"url":"https://api.github.com/repos/Azure/azure-functions-durable-extension/issues/378","repository_url":"https://api.github.com/repos/Azure/azure-functions-durable-extension","labels_url":"https://api.github.com/repos/Azure/azure-functions-durable-extension/issues/378/labels{/name}","comments_url":"https://api.github.com/repos/Azure/azure-functions-durable-extension/issues/378/comments","events_url":"https://api.github.com/repos/Azure/azure-functions-durable-extension/issues/378/events","html_url":"https://github.com/Azure/azure-functions-durable-extension/issues/378","id":337939972,"node_id":"MDU6SXNzdWUzMzc5Mzk5NzI=","number":378,"title":"[Enhancement] Enhance external event usecases to support classic scenarios","user":{"login":"SimonLuckenuik","id":13141534,"node_id":"MDQ6VXNlcjEzMTQxNTM0","avatar_url":"https://avatars3.githubusercontent.com/u/13141534?v=4","gravatar_id":"","url":"https://api.github.com/users/SimonLuckenuik","html_url":"https://github.com/SimonLuckenuik","followers_url":"https://api.github.com/users/SimonLuckenuik/followers","following_url":"https://api.github.com/users/SimonLuckenuik/following{/other_user}","gists_url":"https://api.github.com/users/SimonLuckenuik/gists{/gist_id}","starred_url":"https://api.github.com/users/SimonLuckenuik/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/SimonLuckenuik/subscriptions","organizations_url":"https://api.github.com/users/SimonLuckenuik/orgs","repos_url":"https://api.github.com/users/SimonLuckenuik/repos","events_url":"https://api.github.com/users/SimonLuckenuik/events{/privacy}","received_events_url":"https://api.github.com/users/SimonLuckenuik/received_events","type":"User","site_admin":false},"labels":[{"id":919818708,"node_id":"MDU6TGFiZWw5MTk4MTg3MDg=","url":"https://api.github.com/repos/Azure/azure-functions-durable-extension/labels/needs-investigation","name":"needs-investigation","color":"d662bf","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":1,"created_at":"2018-07-03T15:05:10Z","updated_at":"2018-08-04T22:49:21Z","closed_at":null,"author_association":"NONE","body":"As explained in the warning [here](https://docs.microsoft.com/en-us/azure/azure-functions/durable-functions-external-events#send-events): _\"If there is no orchestration instance with the specified instance ID or if the instance is not waiting on the specified event name, the event message is discarded.\"_\r\n\r\nConsidering that limitation:\r\n1) It becomes impossible to handle orchestrations with variable (undefined) number of events (because a new event could be received between two WaitForExternalEvent calls)\r\n2) Unless ordering is possible with the trigger mechanism that raised the external events, all expected events need to be WaitForExternalEvent at the very beginning to make sure that none will be discarded.\r\n\r\nSuggestions:\r\nA) Considering that Events are **the** way to interact with an executing orchestration, I would suggest to enhance the event behavior to be more flexible. Currently, with these limitations, I cannot for example notify an orchestration each time a message is received on a queue, unless I know upfront the number of messages that will be received.\r\nB) Maybe adding a new concept like an Orchestration Queue would be acceptable?\r\n\r\nTo display how easy it is to lose and event, consider the following code, only first event will be processed. I guess if the orchestration is not executed right away, I would probably lose the first event as well.\r\n\r\nVersions:\r\n- Microsoft.Azure.WebJobs.Extensions.DurableTask: 1.5.0\r\n- Microsoft.NET.Sdk.Functions: 1.0.14\r\n\r\n```\r\nusing System.Collections.Generic;\r\nusing System.Linq;\r\nusing System;\r\nusing System.Net;\r\nusing System.Net.Http;\r\nusing System.Threading.Tasks;\r\nusing Microsoft.Azure.WebJobs;\r\nusing Microsoft.Azure.WebJobs.Extensions.Http;\r\nusing Microsoft.Azure.WebJobs.Host;\r\nusing Microsoft.Extensions.Logging;\r\n\r\nnamespace FunctionAppStartAndEvent\r\n{\r\n    public static class OrchestratorFunction\r\n    {\r\n        [FunctionName(nameof(OrchestratorFunction))]\r\n        public static async Task<DateTime> Run([OrchestrationTrigger] DurableOrchestrationContextBase context, ILogger logger)\r\n        {\r\n            var eventCount = 0;\r\n            do\r\n            {\r\n                var newEvent = await context.WaitForExternalEvent<MyEvent>(nameof(MyEvent));\r\n                if(!context.IsReplaying) logger.LogInformation($\"** Event {eventCount} received. Message: {newEvent.Message}\");\r\n                if (newEvent.Message == \"stop\")\r\n                {\r\n                    break;\r\n                }\r\n                await context.CallActivityAsync<string>(nameof(LogActivityFunction), newEvent.Message);\r\n            } while (true);\r\n            return context.CurrentUtcDateTime;\r\n        }\r\n    }\r\n\r\n    public static class LogActivityFunction\r\n    {\r\n        [FunctionName(nameof(LogActivityFunction))]\r\n        public static string Run([ActivityTrigger] string message, ILogger logger)\r\n        {\r\n            logger.LogInformation($\"** ACTIVITY: {message}\");\r\n            return $\"Step {message}!\";\r\n        }\r\n    }\r\n\r\n    public class MyEvent\r\n    {\r\n        public string Message { get; set; }\r\n    }\r\n\r\n    public static class StartWorkflow\r\n    {\r\n        [FunctionName(nameof(StartWorkflow))]\r\n        public static async Task<HttpResponseMessage> Run(\r\n            [HttpTrigger(AuthorizationLevel.Anonymous, \"get\", Route = \"StartWorkflow\")]HttpRequestMessage req, \r\n            [OrchestrationClient] DurableOrchestrationClient starter,\r\n            ILogger logger)\r\n        {\r\n            var instanceId = $\"{DateTime.UtcNow:O}_{Guid.NewGuid():N}\";\r\n            logger.LogInformation(\"** Starting workflow\");\r\n            logger.LogInformation($\"** Instance Id: {instanceId}\");\r\n            await starter.StartNewAsync(nameof(OrchestratorFunction), instanceId, DateTime.UtcNow);\r\n\r\n            logger.LogInformation(\"** Raising Events\");\r\n            for (int i = 0; i < 10; i++)\r\n            {\r\n                await starter.RaiseEventAsync(instanceId, nameof(MyEvent), new MyEvent\r\n                {\r\n                    Message = $\"EVENT {i}\"\r\n                });\r\n            }\r\n\r\n            await starter.RaiseEventAsync(instanceId, nameof(MyEvent), new MyEvent\r\n            {\r\n                Message = \"stop\"\r\n            });\r\n\r\n            return starter.CreateCheckStatusResponse(req, instanceId);\r\n        }\r\n    }\r\n}\r\n```\r\n"},"comment":{"url":"https://api.github.com/repos/Azure/azure-functions-durable-extension/issues/comments/410482733","html_url":"https://github.com/Azure/azure-functions-durable-extension/issues/378#issuecomment-410482733","issue_url":"https://api.github.com/repos/Azure/azure-functions-durable-extension/issues/378","id":410482733,"node_id":"MDEyOklzc3VlQ29tbWVudDQxMDQ4MjczMw==","user":{"login":"cgillum","id":2704139,"node_id":"MDQ6VXNlcjI3MDQxMzk=","avatar_url":"https://avatars2.githubusercontent.com/u/2704139?v=4","gravatar_id":"","url":"https://api.github.com/users/cgillum","html_url":"https://github.com/cgillum","followers_url":"https://api.github.com/users/cgillum/followers","following_url":"https://api.github.com/users/cgillum/following{/other_user}","gists_url":"https://api.github.com/users/cgillum/gists{/gist_id}","starred_url":"https://api.github.com/users/cgillum/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cgillum/subscriptions","organizations_url":"https://api.github.com/users/cgillum/orgs","repos_url":"https://api.github.com/users/cgillum/repos","events_url":"https://api.github.com/users/cgillum/events{/privacy}","received_events_url":"https://api.github.com/users/cgillum/received_events","type":"User","site_admin":false},"created_at":"2018-08-04T22:49:21Z","updated_at":"2018-08-04T22:49:21Z","author_association":"COLLABORATOR","body":"I took a look and confirmed that this does NOT work correctly today due to some race conditions in our message processing logic. We definitely want to make this scenario work."}}
{"actor":{"display_login":"cgillum"}}