Example #1
0
            public Endpoint(Lifetime bindLifetime, RdCall <TReq, TRes> call, RdId rdId, IScheduler wireScheduler) : base(call, rdId, wireScheduler)
            {
                myDef = bindLifetime.CreateNested();

                myCall.Wire.Advise(Lifetime, this);
                Lifetime.TryOnTermination(() => ResultInternal.SetIfEmpty(RdTaskResult <TRes> .Cancelled()));

                Result.AdviseOnce(Lifetime.Eternal, taskResult =>
                {
                    var potentiallyBindable = taskResult.Result;
                    if (potentiallyBindable.IsBindable())
                    {
                        potentiallyBindable.IdentifyPolymorphic(myCall.Proto.Identities, myCall.RdId.Mix(RdId.ToString()));
                        potentiallyBindable.BindPolymorphic(Lifetime, myCall, RdId.ToString());
                    }
                    else
                    {
                        myDef.Terminate();
                    }

                    Trace(RdReactiveBase.ourLogSend, "send response", taskResult);
                    myWire.Send(RdId,
                                writer =>
                    {
                        RdTaskResult <TRes> .Write(myCall.WriteResponseDelegate, myCall.SerializationContext, writer, taskResult);
                    });
                });
            }
Example #2
0
        internal Lifetime Subscribe(Lifetime outerLifetime)
        {
            var taskWireSubscriptionDefinition = outerLifetime.CreateNested();
            var externalCancellation           = outerLifetime.CreateNested();

            myCall.Wire.Advise(taskWireSubscriptionDefinition.Lifetime, this); //this lifetimeDef listen only one value
            taskWireSubscriptionDefinition.Lifetime.TryOnTermination(() => ResultInternal.SetIfEmpty(RdTaskResult <TRes> .Cancelled()));

            Result.AdviseOnce(Lifetime.Eternal, taskResult =>
            {
                try
                {
                    var potentiallyBindable = taskResult.Result;
                    if (potentiallyBindable.IsBindable())
                    {
                        if (myIsEndpoint)
                        {
                            potentiallyBindable.IdentifyPolymorphic(myCall.Proto.Identities, myCall.RdId.Mix(RdId.ToString()));
                        }

                        potentiallyBindable.BindPolymorphic(externalCancellation.Lifetime, myCall, RdId.ToString());
                    }
                    else
                    {
                        externalCancellation.Terminate();
                    }

                    if (myIsEndpoint)
                    {
                        Trace(RdReactiveBase.ourLogSend, "send response", taskResult);
                        myWire.Send(RdId,
                                    writer =>
                        {
                            RdTaskResult <TRes> .Write(myCall.WriteResponseDelegate, myCall.SerializationContext, writer, taskResult);
                        });
                    }
                    else if (taskResult.Status == RdTaskStatus.Canceled) //we need to transfer cancellation to the other side
                    {
                        Trace(RdReactiveBase.ourLogSend, "send cancellation");
                        myWire.Send(RdId, writer => { writer.Write(Unit.Instance); }); //send cancellation to the other side
                    }
                }
                finally
                {
                    taskWireSubscriptionDefinition.Terminate(); //no need to listen result or cancellation from wire
                }
            });

            return(externalCancellation.Lifetime);
        }
Example #3
0
        public override void OnWireReceived(UnsafeReader reader)
        {
            var taskId = RdId.Read(reader);
            var value  = ReadRequestDelegate(SerializationContext, reader);

            if (LogReceived.IsTraceEnabled())
            {
                LogReceived.Trace("endpoint `{0}`::({1}), taskId={2}, request = {3}", Location, RdId, taskId, value.PrintToString());
            }


            var taskLifetimeDef = myBindLifetime.CreateNested();

            //subscribe for lifetime cancellation
            new WiredLifetime(taskLifetimeDef, taskId, this, Wire);

            RdTask <TRes> rdTask;

            using (UsingDebugInfo()) //now supports only sync handlers
            {
                try
                {
                    rdTask = Handler(taskLifetimeDef.Lifetime, value);
                }
                catch (Exception e)
                {
                    rdTask = RdTask <TRes> .Faulted(e);
                }
            }



            rdTask.Result.Advise(taskLifetimeDef.Lifetime, result =>
            {
                if (LogSend.IsTraceEnabled())
                {
                    LogSend.Trace("endpoint `{0}`::({1}), taskId={2}, response = {3}", Location, RdId, taskId, result.PrintToString());
                }

                RdTaskResult <TRes> validatedResult;
                try
                {
                    if (result.Status == RdTaskStatus.Success)
                    {
                        AssertNullability(result.Result);
                    }
                    validatedResult = result;
                }
                catch (Exception e)
                {
                    LogSend.Error(e);
                    validatedResult = RdTaskResult <TRes> .Faulted(e);
                }

                Wire.Send(taskId, writer =>
                {
                    RdTaskResult <TRes> .Write(WriteResponseDelegate, SerializationContext, writer, validatedResult);
                });

                taskLifetimeDef.Terminate(); //need to terminate to unsubscribe lifetime listener - not for bindable entries
            });
        }