Exemple #1
0
        private async Task RunRoutineAsync(RoutineEventEnvelope eventEnvelope, CancellationToken ct)
        {
            for (; ;)
            {
                var carrier = new TransitionCarrier(this, eventEnvelope);

                //var transitionInfo = await data.GetTransitionDescriptorAsync(ct);
                //if (transitionInfo.Type == TransitionType.InvokeRoutine ||
                //    transitionInfo.Type == TransitionType.ContinueRoutine)
                //{
                //    var routineDescriptor = await data.GetRoutineDescriptorAsync(ct);

                //    if (!string.IsNullOrEmpty(transitionInfo.ETag) &&
                //        transitionInfo.ETag != routineDescriptor.ETag)
                //    {
                //        // Ignore - stale duplicate message
                //        return;
                //    }
                //}

                try
                {
                    await _transitionRunner.RunAsync(carrier, ct);

                    break;
                }
                catch (ConcurrentRoutineExecutionException)
                {
                    // re-try
                    continue;
                }
            }
        }
Exemple #2
0
        private async Task ProcessEventAsync(string filePath, CancellationToken ct)
        {
#warning Need to exclusively lock the file
            var json          = File.ReadAllText(filePath);
            var eventEnvelope = JsonConvert.DeserializeObject <RoutineEventEnvelope>(
                json, CloudEventsSerialization.JsonSerializerSettings);
            json = null; // save memory

            if (eventEnvelope.EventDeliveryTime.HasValue && eventEnvelope.EventDeliveryTime > DateTimeOffset.UtcNow)
            {
                await Task.Delay(eventEnvelope.EventDeliveryTime.Value - DateTimeOffset.UtcNow);
            }

            for (; ;)
            {
                var carrier = new TransitionCarrier(this, eventEnvelope);
                var data    = carrier;

                //var transitionInfo = await data.GetTransitionDescriptorAsync(ct);
                //if (transitionInfo.Type == TransitionType.InvokeRoutine ||
                //    transitionInfo.Type == TransitionType.ContinueRoutine)
                //{
                //    var routineDescriptor = await data.GetRoutineDescriptorAsync(ct);

                //    if (!string.IsNullOrEmpty(transitionInfo.ETag) &&
                //        transitionInfo.ETag != routineDescriptor.ETag)
                //    {
                //        // Ignore - stale duplicate message
                //        return;
                //    }
                //}

                try
                {
                    await _transitionRunner.RunAsync(carrier, data, ct);

                    break;
                }
                catch (ConcurrentRoutineExecutionException)
                {
                    // re-try
                    continue;
                }
            }

            File.Delete(filePath);
        }
Exemple #3
0
        private async void RunMessageInBackground(Message message)
        {
            if (message.DeliverAt.HasValue && message.DeliverAt > DateTime.UtcNow)
            {
                await Task.Delay(message.DeliverAt.Value - DateTime.UtcNow);
            }
            else
            {
                await Task.Yield();
            }

            var ct = CancellationToken.None;

            for (; ;)
            {
                var carrier = new TransitionCarrier(this, message);
                var data    = carrier;
                carrier.Initialize();

                //var transitionInfo = await data.GetTransitionDescriptorAsync(ct);
                //if (transitionInfo.Type == TransitionType.InvokeRoutine ||
                //    transitionInfo.Type == TransitionType.ContinueRoutine)
                //{
                //    var routineDescriptor = await data.GetRoutineDescriptorAsync(ct);

                //    if (!string.IsNullOrEmpty(transitionInfo.ETag) &&
                //        transitionInfo.ETag != routineDescriptor.ETag)
                //    {
                //        // Ignore - stale duplicate message
                //        return;
                //    }
                //}

                try
                {
                    await _transitionRunner.RunAsync(carrier, data, ct);

                    break;
                }
                catch (ConcurrentRoutineExecutionException)
                {
                    // re-try
                    continue;
                }
            }
        }
        private async void RunMessageInBackground(Message message)
        {
            if (message.DeliverAt.HasValue && message.DeliverAt > DateTime.UtcNow)
            {
                await Task.Delay(message.DeliverAt.Value - DateTime.UtcNow);
            }
            else
            {
                await Task.Yield();
            }

            var ct = CancellationToken.None;

            if (message.IsEvent)
            {
                var serviceId = Serializer.Deserialize <ServiceId>(message[nameof(ServiceId)]);
                var eventId   = Serializer.Deserialize <EventId>(message[nameof(EventId)]);
                var eventDesc = new EventDescriptor {
                    EventId = eventId, ServiceId = serviceId
                };
                var subscribers = DataStore.GetEventSubscribers(eventDesc);

                foreach (var subscriber in subscribers)
                {
                    var routineId = Interlocked.Increment(ref DataStore.RoutineCounter);

                    var routineRecord = new RoutineStateRecord
                    {
                        ETag       = DateTime.UtcNow.Ticks.ToString("X16"),
                        Id         = routineId.ToString(),
                        Completion = new TaskCompletionSource <string>()
                    };

                    lock (DataStore.Routines)
                    {
                        DataStore.Routines.Add(routineRecord.Id, routineRecord);
                    }

                    var transitionDescriptor = new TransitionDescriptor
                    {
                        Type = TransitionType.InvokeRoutine,
                        ETag = routineRecord.ETag
                    };

                    var routineDescriptor = new RoutineDescriptor
                    {
                        MethodId  = subscriber.MethodId,
                        IntentId  = _numericIdGenerator.NewId(),
                        RoutineId = routineRecord.Id,
                        ETag      = routineRecord.ETag
                    };

                    var invokeRoutineMessage = new Message
                    {
                        //["IntentId"] = _serializer.Serialize(intent.Id),
                        [nameof(TransitionDescriptor)] = Serializer.SerializeToString(transitionDescriptor),
                        [nameof(ServiceId)]            = Serializer.SerializeToString(subscriber.ServiceId),
                        [nameof(RoutineDescriptor)]    = Serializer.SerializeToString(routineDescriptor),
                        ["Parameters"] = message["Parameters"]
                    };

                    DataStore.ScheduleMessage(invokeRoutineMessage);
                }
            }
            else
            {
                for (; ;)
                {
                    var carrier = new TransitionCarrier(this, message);
                    carrier.Initialize();

                    //var transitionInfo = await data.GetTransitionDescriptorAsync(ct);
                    //if (transitionInfo.Type == TransitionType.InvokeRoutine ||
                    //    transitionInfo.Type == TransitionType.ContinueRoutine)
                    //{
                    //    var routineDescriptor = await data.GetRoutineDescriptorAsync(ct);

                    //    if (!string.IsNullOrEmpty(transitionInfo.ETag) &&
                    //        transitionInfo.ETag != routineDescriptor.ETag)
                    //    {
                    //        // Ignore - stale duplicate message
                    //        return;
                    //    }
                    //}

                    try
                    {
                        await _transitionRunner.RunAsync(carrier, ct);

                        break;
                    }
                    catch (ConcurrentRoutineExecutionException)
                    {
                        // re-try
                        continue;
                    }
                }
            }
        }
Exemple #5
0
        public async Task ProcessMessageAsync(
            CloudQueueMessage message,
            FunctionExecutionContext context,
            DateTimeOffset messageReceiveTime,
            ILogger logger,
            CancellationToken ct)
        {
            _functionToQueueMap.TryGetValue(context.FunctionName, out var queue);
            _currentFunction.Value = new ExecutingFuncionInfo
            {
                FunctionName = context.FunctionName,
                Queue        = queue
            };

            try
            {
#warning Keep message invisible while transitioning

                var eventEnvelope = JsonConvert.DeserializeObject <RoutineEventEnvelope>(
                    message.AsString, CloudEventsSerialization.JsonSerializerSettings);
                // Free memory
                message.SetMessageContent((string)null);
                message.SetMessageContent((byte[])null);

                var transitionCarrier = new AzureStorageTransitionCarrier(
                    eventEnvelope, _routinesTable, _servicesTable, _defaultSerializer);

                var concurrentExecutionDetected = false;
                try
                {
                    await _transitionRunner.RunAsync(transitionCarrier, ct);
                }
                catch (ConcurrentTransitionException)
                {
                    concurrentExecutionDetected = true;
                }

                if (concurrentExecutionDetected)
                {
                    var transitionInfo = await transitionCarrier.GetTransitionDescriptorAsync(ct);

                    if (transitionInfo.Type != TransitionType.InvokeRoutine)
                    {
#warning Host has a setting of max re-tries. Re-enqueue another message? Delay also?
                        throw new Exception("re-try");

                        //// Re-try message by resetting its invisibility time.
                        //await transitionsQueue.UpdateMessageAsync(
                        //    message, TimeSpan.Zero, MessageUpdateFields.Visibility, ct);
                        //continue;
                    }
                    // If there are 2 or more messages that try to invoke the routine
                    // for the first time, accept the first message and drop the rest.
                }

                //await transitionsQueue.DeleteMessageAsync(message.Id, message.PopReceipt, ct);
            }
            finally
            {
                _currentFunction.Value = default;
            }
        }