Beispiel #1
0
        public Task <ActiveRoutineInfo> ScheduleRoutineAsync(
            ExecuteRoutineIntent intent, CancellationToken ct)
        {
#warning Need to send message first, then create routine record.

            var routineId = Interlocked.Increment(ref _dataStore.RoutineCounter);

            var routineRecord = new RoutineStateRecord
            {
                ETag         = DateTime.UtcNow.Ticks.ToString("X16"),
                Id           = routineId.ToString(),
                Completion   = new TaskCompletionSource <string>(),
                Continuation = intent.Continuation == null ? null : _serializer.SerializeToString(intent.Continuation)
            };

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

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

            var routineDescriptor = new RoutineDescriptor
            {
                MethodId  = intent.MethodId,
                IntentId  = intent.Id,
                RoutineId = routineRecord.Id,
                ETag      = routineRecord.ETag
            };

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

            _dataStore.ScheduleMessage(message);

            var info = new ActiveRoutineInfo
            {
                RoutineId = routineRecord.Id
            };

            return(Task.FromResult(info));
        }
Beispiel #2
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;

            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;
                    }
                }
            }
        }