vlingo-net / xoom-net-actors

Type safe Actor Model toolkit for reactive concurrency and resiliency using C# and other .NET languages.
Mozilla Public License 2.0
39 stars 18 forks source link

Dynamic Proxy generator doesn't include all the using directives #40

Closed tjaskula closed 5 years ago

tjaskula commented 5 years ago

Sometimes not enough using directives are added to the generated code so it doesn't compile. Here's one example:

using System;
using System.Collections.Generic;
using Vlingo.Actors;
using Vlingo.Common;
using Vlingo.Wire.Channel;
using System.Net.Sockets;

namespace Vlingo.Wire.Channel
{
    public class ResponseSenderChannel__Proxy : IResponseSenderChannel<Socket>
    {
        private const string AbandonRepresentation1 = "Abandon(RequestResponseContext<Socket>)";
        private const string RespondWithRepresentation2 = "RespondWith(RequestResponseContext<Socket>, IConsumerByteBuffer)";

        private readonly Actor actor;
        private readonly IMailbox mailbox;

        public ResponseSenderChannel__Proxy(Actor actor, IMailbox mailbox)
        {
            this.actor = actor;
            this.mailbox = mailbox;
        }

        public void Abandon(RequestResponseContext<Socket> context)
        {
            if(!actor.IsStopped)
            {
                Action<IResponseSenderChannel<Socket>> consumer = x => x.Abandon(context);
                if(mailbox.IsPreallocated)
                {
                    mailbox.Send(actor, consumer, null, AbandonRepresentation1);
                }
                else
                {
                    mailbox.Send(new LocalMessage<IResponseSenderChannel<Socket>>(actor, consumer, AbandonRepresentation1));
                }
            }
            else
            {
                actor.DeadLetters.FailedDelivery(new DeadLetter(actor, AbandonRepresentation1));
            }
        }
        public void RespondWith(RequestResponseContext<Socket> context, IConsumerByteBuffer buffer)
        {
            if(!actor.IsStopped)
            {
                Action<IResponseSenderChannel<Socket>> consumer = x => x.RespondWith(context, buffer);
                if(mailbox.IsPreallocated)
                {
                    mailbox.Send(actor, consumer, null, RespondWithRepresentation2);
                }
                else
                {
                    mailbox.Send(new LocalMessage<IResponseSenderChannel<Socket>>(actor, consumer, RespondWithRepresentation2));
                }
            }
            else
            {
                actor.DeadLetters.FailedDelivery(new DeadLetter(actor, RespondWithRepresentation2));
            }
        }

    }
}

It doesn't compile because IConsumerByteBuffer has no namespace using directive on the top of the file.

There are other examples as well, when I had System.Net.Sockets.Socket as proxy method parameter and using was not added

tjaskula commented 5 years ago

This is partially related to #36 but I prefered to report a new issue as it is better scoped on the specific problem.

zpbappi commented 5 years ago

you are right. This mentioned case is a bug. It is a quick fix though.

tjaskula commented 5 years ago

Do you think you can handle it @zpbappi ?

zpbappi commented 5 years ago

Yep, on it.

tjaskula commented 5 years ago

I have another variation with namespaces used as types:

vlingo-net/actors: vlingo-net/actors: Generating proxy for main: IOperationalOutboundStream
System.Net.Sockets.SocketException (48): Address already in use
   at System.Net.Sockets.Socket.UpdateStatusAfterSocketErrorAndThrowException(SocketError error, String callerName)
   at System.Net.Sockets.Socket.DoBind(EndPoint endPointSnapshot, SocketAddress socketAddress)
   at System.Net.Sockets.Socket.Bind(EndPoint localEP)
   at Vlingo.Wire.Fdx.Inbound.SocketChannelInboundReader.OpenFor(IChannelReaderConsumer consumer)
   at Vlingo.Wire.Fdx.Inbound.InboundStreamActor.Start()
vlingo-net/actors: Message#Deliver(): Exception: Address already in use for Actor: Actor[type=InboundStreamActor address=Address[Id=18, Name=OP-inbound]] sending: Start()
vlingo-net/actors [Exception]: Address already in use
vlingo-net/actors [StackTrace]:    at Vlingo.Wire.Fdx.Inbound.InboundStreamActor.Start()
   at Vlingo.Actors.LocalMessage`1.InternalDeliver(IMessage message)
vlingo-net/actors: DefaultSupervisorOverride: Failure of: Address[Id=18, Name=OP-inbound]
vlingo-net/actors [Exception]: Address already in use
vlingo-net/actors [StackTrace]:    at Vlingo.Wire.Fdx.Inbound.InboundStreamActor.Start()
   at Vlingo.Actors.LocalMessage`1.InternalDeliver(IMessage message)
Dynamically generated class source for Vlingo.Cluster.Model.Outbound.OperationalOutboundStream__Proxy did not compile because: 'Node' is a namespace but is used like a type
   at Vlingo.Common.Compiler.DynaCompiler.Compile(Input input)
vlingo-net/actors: vlingo-net/actors: Generating proxy for test: IOperationalOutboundStream
Dynamically generated class source for Vlingo.Cluster.Model.Outbound.OperationalOutboundStream__Proxy did not compile because: 'Node' is a namespace but is used like a type
   at Vlingo.Common.Compiler.DynaCompiler.Compile(Input input)
Actor proxy IOperationalOutboundStream not created for main or test: Actor proxy IOperationalOutboundStream not created because: Dynamically generated class source did not compile: Vlingo.Cluster.Model.Outbound.OperationalOutboundStream__Proxy
   at Vlingo.Actors.ActorProxy.TryGenerateCreate(Type protocol, Actor actor, IMailbox mailbox, String targetClassName)
   at Vlingo.Actors.ActorProxy.CreateFor(Type protocol, Actor actor, IMailbox mailbox)
   at Vlingo.Actors.ActorProxy.CreateFor[T](Actor actor, IMailbox mailbox)
   at Vlingo.Actors.Stage.ActorProtocolFor[T](Definition definition, Actor parent, IAddress maybeAddress, IMailbox maybeMailbox, ISupervisor maybeSupervisor, ILogger logger)
vlingo-net/actors: vlingo-net/actors: FAILED: Actor proxy IOperationalOutboundStream not created for main or test: Actor proxy IOperationalOutboundStream not created because: Dynamically generated class source did not compile: Vlingo.Cluster.Model.Outbound.OperationalOutboundStream__Proxy
vlingo-net/actors [Exception]: Actor proxy IOperationalOutboundStream not created for main or test: Actor proxy IOperationalOutboundStream not created because: Dynamically generated class source did not compile: Vlingo.Cluster.Model.Outbound.OperationalOutboundStream__Proxy
vlingo-net/actors [StackTrace]:    at Vlingo.Actors.ActorProxy.TryGenerateCreate(Type protocol, Actor actor, IMailbox mailbox, String targetClassName)
   at Vlingo.Actors.ActorProxy.CreateFor(Type protocol, Actor actor, IMailbox mailbox)
   at Vlingo.Actors.ActorProxy.CreateFor[T](Actor actor, IMailbox mailbox)
   at Vlingo.Actors.Stage.ActorProtocolFor[T](Definition definition, Actor parent, IAddress maybeAddress, IMailbox maybeMailbox, ISupervisor maybeSupervisor, ILogger logger)
vlingo-net/actors: ActorFactory: failed actor creation. This is sometimes cause by the constructor parameter types not matching the types in the Definition.parameters(). Often it is caused by a failure in the actor constructor. We have attempted to uncover the root cause here, but that may not be available in some cases.
The root cause may be: Object reference not set to an instance of an object.
See stacktrace for more information. We strongly recommend reviewing your constructor for possible failures in dependencies that it creates.
vlingo-net/actors [Exception]: Object reference not set to an instance of an object.
Actor instantiation failed because: ActorFactory failed actor creation for: Address[Id=14, Name=(none)]
   at Vlingo.Actors.Stage.CreateRawActor(Definition definition, Actor parent, IAddress maybeAddress, IMailbox maybeMailbox, ISupervisor maybeSupervisor, ILogger logger)
   at Vlingo.Actors.Stage.ActorProtocolFor[T](Definition definition, Actor parent, IAddress maybeAddress, IMailbox maybeMailbox, ISupervisor maybeSupervisor, ILogger logger)
Object reference not set to an instance of an object.
   at Vlingo.Actors.Stage.TestActorFor[T](Definition definition)
vlingo-net/actors [StackTrace]:    at Vlingo.Actors.Stage.ActorFor[T](Definition definition, Actor parent, ISupervisor maybeSupervisor, ILogger logger)

And this is the generated file:

using System;
using System.Collections.Generic;
using Vlingo.Actors;
using Vlingo.Common;
using Vlingo.Cluster.Model.Outbound;
using System.Threading.Tasks;
using Vlingo.Wire.Node;
using Vlingo.Cluster.Model.Message;
namespace Vlingo.Cluster.Model.Outbound
{
public class OperationalOutboundStream__Proxy : IOperationalOutboundStream
{
  private const string CloseRepresentation1 = "Close(Id)";
  private const string ApplicationRepresentation2 = "Application(ApplicationSays, IEnumerable<Node>)";
  private const string DirectoryRepresentation3 = "Directory(IEnumerable<Node>)";
  private const string ElectRepresentation4 = "Elect(IEnumerable<Node>)";
  private const string JoinRepresentation5 = "Join()";
  private const string LeaderRepresentation6 = "Leader()";
  private const string LeaderRepresentation7 = "Leader(Id)";
  private const string LeaveRepresentation8 = "Leave()";
  private const string OpenRepresentation9 = "Open(Id)";
  private const string PingRepresentation10 = "Ping(Id)";
  private const string PulseRepresentation11 = "Pulse(Id)";
  private const string PulseRepresentation12 = "Pulse()";
  private const string SplitRepresentation13 = "Split(Id, Id)";
  private const string VoteRepresentation14 = "Vote(Id)";
  private const string StopRepresentation15 = "Stop()";

  private readonly Actor actor;
  private readonly IMailbox mailbox;

  public OperationalOutboundStream__Proxy(Actor actor, IMailbox mailbox)
  {
    this.actor = actor;
    this.mailbox = mailbox;
  }
  public bool IsStopped => false;

  public void Close(Id id)
  {
    if(!actor.IsStopped)
    {
      Action<IOperationalOutboundStream> consumer = x => x.Close(id);
      if(mailbox.IsPreallocated)
      {
        mailbox.Send(actor, consumer, null, CloseRepresentation1);
      }
      else
      {
        mailbox.Send(new LocalMessage<IOperationalOutboundStream>(actor, consumer, CloseRepresentation1));
      }
    }
    else
    {
      actor.DeadLetters.FailedDelivery(new DeadLetter(actor, CloseRepresentation1));
    }
  }
  public Task Application(ApplicationSays says, IEnumerable<Node> unconfirmedNodes)
  {
    if(!actor.IsStopped)
    {
      Action<IOperationalOutboundStream> consumer = x => x.Application(says, unconfirmedNodes);
      if(mailbox.IsPreallocated)
      {
        mailbox.Send(actor, consumer, null, ApplicationRepresentation2);
      }
      else
      {
        mailbox.Send(new LocalMessage<IOperationalOutboundStream>(actor, consumer, ApplicationRepresentation2));
      }
    }
    else
    {
      actor.DeadLetters.FailedDelivery(new DeadLetter(actor, ApplicationRepresentation2));
    }
    return null;
  }
  public Task Directory(IEnumerable<Node> allLiveNodes)
  {
    if(!actor.IsStopped)
    {
      Action<IOperationalOutboundStream> consumer = x => x.Directory(allLiveNodes);
      if(mailbox.IsPreallocated)
      {
        mailbox.Send(actor, consumer, null, DirectoryRepresentation3);
      }
      else
      {
        mailbox.Send(new LocalMessage<IOperationalOutboundStream>(actor, consumer, DirectoryRepresentation3));
      }
    }
    else
    {
      actor.DeadLetters.FailedDelivery(new DeadLetter(actor, DirectoryRepresentation3));
    }
    return null;
  }
  public Task Elect(IEnumerable<Node> allGreaterNodes)
  {
    if(!actor.IsStopped)
    {
      Action<IOperationalOutboundStream> consumer = x => x.Elect(allGreaterNodes);
      if(mailbox.IsPreallocated)
      {
        mailbox.Send(actor, consumer, null, ElectRepresentation4);
      }
      else
      {
        mailbox.Send(new LocalMessage<IOperationalOutboundStream>(actor, consumer, ElectRepresentation4));
      }
    }
    else
    {
      actor.DeadLetters.FailedDelivery(new DeadLetter(actor, ElectRepresentation4));
    }
    return null;
  }
  public Task Join()
  {
    if(!actor.IsStopped)
    {
      Action<IOperationalOutboundStream> consumer = x => x.Join();
      if(mailbox.IsPreallocated)
      {
        mailbox.Send(actor, consumer, null, JoinRepresentation5);
      }
      else
      {
        mailbox.Send(new LocalMessage<IOperationalOutboundStream>(actor, consumer, JoinRepresentation5));
      }
    }
    else
    {
      actor.DeadLetters.FailedDelivery(new DeadLetter(actor, JoinRepresentation5));
    }
    return null;
  }
  public Task Leader()
  {
    if(!actor.IsStopped)
    {
      Action<IOperationalOutboundStream> consumer = x => x.Leader();
      if(mailbox.IsPreallocated)
      {
        mailbox.Send(actor, consumer, null, LeaderRepresentation6);
      }
      else
      {
        mailbox.Send(new LocalMessage<IOperationalOutboundStream>(actor, consumer, LeaderRepresentation6));
      }
    }
    else
    {
      actor.DeadLetters.FailedDelivery(new DeadLetter(actor, LeaderRepresentation6));
    }
    return null;
  }
  public Task Leader(Id id)
  {
    if(!actor.IsStopped)
    {
      Action<IOperationalOutboundStream> consumer = x => x.Leader(id);
      if(mailbox.IsPreallocated)
      {
        mailbox.Send(actor, consumer, null, LeaderRepresentation7);
      }
      else
      {
        mailbox.Send(new LocalMessage<IOperationalOutboundStream>(actor, consumer, LeaderRepresentation7));
      }
    }
    else
    {
      actor.DeadLetters.FailedDelivery(new DeadLetter(actor, LeaderRepresentation7));
    }
    return null;
  }
  public Task Leave()
  {
    if(!actor.IsStopped)
    {
      Action<IOperationalOutboundStream> consumer = x => x.Leave();
      if(mailbox.IsPreallocated)
      {
        mailbox.Send(actor, consumer, null, LeaveRepresentation8);
      }
      else
      {
        mailbox.Send(new LocalMessage<IOperationalOutboundStream>(actor, consumer, LeaveRepresentation8));
      }
    }
    else
    {
      actor.DeadLetters.FailedDelivery(new DeadLetter(actor, LeaveRepresentation8));
    }
    return null;
  }
  public void Open(Id id)
  {
    if(!actor.IsStopped)
    {
      Action<IOperationalOutboundStream> consumer = x => x.Open(id);
      if(mailbox.IsPreallocated)
      {
        mailbox.Send(actor, consumer, null, OpenRepresentation9);
      }
      else
      {
        mailbox.Send(new LocalMessage<IOperationalOutboundStream>(actor, consumer, OpenRepresentation9));
      }
    }
    else
    {
      actor.DeadLetters.FailedDelivery(new DeadLetter(actor, OpenRepresentation9));
    }
  }
  public Task Ping(Id targetNodeId)
  {
    if(!actor.IsStopped)
    {
      Action<IOperationalOutboundStream> consumer = x => x.Ping(targetNodeId);
      if(mailbox.IsPreallocated)
      {
        mailbox.Send(actor, consumer, null, PingRepresentation10);
      }
      else
      {
        mailbox.Send(new LocalMessage<IOperationalOutboundStream>(actor, consumer, PingRepresentation10));
      }
    }
    else
    {
      actor.DeadLetters.FailedDelivery(new DeadLetter(actor, PingRepresentation10));
    }
    return null;
  }
  public Task Pulse(Id targetNodeId)
  {
    if(!actor.IsStopped)
    {
      Action<IOperationalOutboundStream> consumer = x => x.Pulse(targetNodeId);
      if(mailbox.IsPreallocated)
      {
        mailbox.Send(actor, consumer, null, PulseRepresentation11);
      }
      else
      {
        mailbox.Send(new LocalMessage<IOperationalOutboundStream>(actor, consumer, PulseRepresentation11));
      }
    }
    else
    {
      actor.DeadLetters.FailedDelivery(new DeadLetter(actor, PulseRepresentation11));
    }
    return null;
  }
  public Task Pulse()
  {
    if(!actor.IsStopped)
    {
      Action<IOperationalOutboundStream> consumer = x => x.Pulse();
      if(mailbox.IsPreallocated)
      {
        mailbox.Send(actor, consumer, null, PulseRepresentation12);
      }
      else
      {
        mailbox.Send(new LocalMessage<IOperationalOutboundStream>(actor, consumer, PulseRepresentation12));
      }
    }
    else
    {
      actor.DeadLetters.FailedDelivery(new DeadLetter(actor, PulseRepresentation12));
    }
    return null;
  }
  public Task Split(Id targetNodeId, Id currentLeaderId)
  {
    if(!actor.IsStopped)
    {
      Action<IOperationalOutboundStream> consumer = x => x.Split(targetNodeId, currentLeaderId);
      if(mailbox.IsPreallocated)
      {
        mailbox.Send(actor, consumer, null, SplitRepresentation13);
      }
      else
      {
        mailbox.Send(new LocalMessage<IOperationalOutboundStream>(actor, consumer, SplitRepresentation13));
      }
    }
    else
    {
      actor.DeadLetters.FailedDelivery(new DeadLetter(actor, SplitRepresentation13));
    }
    return null;
  }
  public Task Vote(Id targetNodeId)
  {
    if(!actor.IsStopped)
    {
      Action<IOperationalOutboundStream> consumer = x => x.Vote(targetNodeId);
      if(mailbox.IsPreallocated)
      {
        mailbox.Send(actor, consumer, null, VoteRepresentation14);
      }
      else
      {
        mailbox.Send(new LocalMessage<IOperationalOutboundStream>(actor, consumer, VoteRepresentation14));
      }
    }
    else
    {
      actor.DeadLetters.FailedDelivery(new DeadLetter(actor, VoteRepresentation14));
    }
    return null;
  }
  public void Stop()
  {
    if(!actor.IsStopped)
    {
      Action<IOperationalOutboundStream> consumer = x => x.Stop();
      if(mailbox.IsPreallocated)
      {
        mailbox.Send(actor, consumer, null, StopRepresentation15);
      }
      else
      {
        mailbox.Send(new LocalMessage<IOperationalOutboundStream>(actor, consumer, StopRepresentation15));
      }
    }
    else
    {
      actor.DeadLetters.FailedDelivery(new DeadLetter(actor, StopRepresentation15));
    }
  }

}
}
tjaskula commented 5 years ago

Moving using Vlingo.Wire.Node; inside the namespace fixes the problem. Maybe we should consider using directives inside the namespace @zpbappi ?

tjaskula commented 5 years ago

Here's another variation:

Dynamically generated class source for Vlingo.Cluster.Model.Attribute.AttributesAgent__Proxy did not compile because: The type or namespace name 'T' could not be found (are you missing a using directive or an assembly reference?)
   at Vlingo.Common.Compiler.DynaCompiler.Compile(Input input)
vlingo-net/actors: vlingo-net/actors: Generating proxy for test: IAttributesAgent
Dynamically generated class source for Vlingo.Cluster.Model.Attribute.AttributesAgent__Proxy did not compile because: The type or namespace name 'T' could not be found (are you missing a using directive or an assembly reference?)
   at Vlingo.Common.Compiler.DynaCompiler.Compile(Input input)
vlingo-net/actors: vlingo-net/actors: Generating proxy for main: IAttributesAgent
Dynamically generated class source for Vlingo.Cluster.Model.Attribute.AttributesAgent__Proxy did not compile because: The type or namespace name 'T' could not be found (are you missing a using directive or an assembly reference?)
   at Vlingo.Common.Compiler.DynaCompiler.Compile(Input input)
vlingo-net/actors: vlingo-net/actors: Generating proxy for test: IAttributesAgent
Dynamically generated class source for Vlingo.Cluster.Model.Attribute.AttributesAgent__Proxy did not compile because: The type or namespace name 'T' could not be found (are you missing a using directive or an assembly reference?)
   at Vlingo.Common.Compiler.DynaCompiler.Compile(Input input)
Actor instantiation failed because: ActorFactory failed actor creation for: Address[Id=19, Name=attributes-agent]
   at Vlingo.Actors.Stage.CreateRawActor(Definition definition, Actor parent, IAddress maybeAddress, IMailbox maybeMailbox, ISupervisor maybeSupervisor, ILogger logger)
   at Vlingo.Actors.Stage.ActorProtocolFor[T](Definition definition, Actor parent, IAddress maybeAddress, IMailbox maybeMailbox, ISupervisor maybeSupervisor, ILogger logger)
vlingo-net/actors: ActorFactory: failed actor creation. This is sometimes cause by the constructor parameter types not matching the types in the Definition.parameters(). Often it is caused by a failure in the actor constructor. We have attempted to uncover the root cause here, but that may not be available in some cases.
The root cause may be: Actor proxy IAttributesAgent not created for main or test: Actor proxy IAttributesAgent not created because: Dynamically generated class source did not compile: Vlingo.Cluster.Model.Attribute.AttributesAgent__Proxy
See stacktrace for more information. We strongly recommend reviewing your constructor for possible failures in dependencies that it creates.
vlingo-net/actors [Exception]: Actor proxy IAttributesAgent not created for main or test: Actor proxy IAttributesAgent not created because: Dynamically generated class source did not compile: Vlingo.Cluster.Model.Attribute.AttributesAgent__Proxy
vlingo-net/actors [StackTrace]:    at Vlingo.Actors.ActorProxy.TryGenerateCreate(Type protocol, Actor actor, IMailbox mailbox, String targetClassName)
   at Vlingo.Actors.ActorProxy.CreateFor(Type protocol, Actor actor, IMailbox mailbox)
   at Vlingo.Actors.ActorProxy.CreateFor[T](Actor actor, IMailbox mailbox)
   at Vlingo.Cluster.Model.Attribute.AttributesAgentActor..ctor(Node node, IClusterApplication application, IOperationalOutboundStream outbound, IConfiguration configuration, IConfirmationInterest confirmationInterest) in /Users/tjaskula/Documents/GitHub/vlingo-net-cluster/src/Vlingo.Cluster/Model/Attribute/AttributesAgentActor.cs:line 48

And this is because it doesn't add generic type parameters to methods like public void Add(string attributeSetName, string attributeName, T value) instead of public void Add<T>(string attributeSetName, string attributeName, T value)

the original generated file:

using System;
using System.Collections.Generic;
using Vlingo.Actors;
using Vlingo.Common;
using Vlingo.Cluster.Model.Attribute;
using Vlingo.Wire.Node;
using Vlingo.Wire.Message;
namespace Vlingo.Cluster.Model.Attribute
{
public class AttributesAgent__Proxy : IAttributesAgent
{
  private const string AddRepresentation1 = "Add(string, string, T)";
  private const string ReplaceRepresentation2 = "Replace(string, string, T)";
  private const string RemoveRepresentation3 = "Remove(string, string)";
  private const string RemoveAllRepresentation4 = "RemoveAll(string)";
  private const string SynchronizeRepresentation5 = "Synchronize(Node)";
  private const string HandleInboundStreamMessageRepresentation6 = "HandleInboundStreamMessage(AddressType, RawMessage)";
  private const string IntervalSignalRepresentation7 = "IntervalSignal(IScheduled<object>, object)";
  private const string StopRepresentation8 = "Stop()";

  private readonly Actor actor;
  private readonly IMailbox mailbox;

  public AttributesAgent__Proxy(Actor actor, IMailbox mailbox)
  {
    this.actor = actor;
    this.mailbox = mailbox;
  }
  public bool IsStopped => false;

  public void Add(string attributeSetName, string attributeName, T value)
  {
    if(!actor.IsStopped)
    {
      Action<IAttributesAgent> consumer = x => x.Add(attributeSetName, attributeName, value);
      if(mailbox.IsPreallocated)
      {
        mailbox.Send(actor, consumer, null, AddRepresentation1);
      }
      else
      {
        mailbox.Send(new LocalMessage<IAttributesAgent>(actor, consumer, AddRepresentation1));
      }
    }
    else
    {
      actor.DeadLetters.FailedDelivery(new DeadLetter(actor, AddRepresentation1));
    }
  }
  public void Replace(string attributeSetName, string attributeName, T value)
  {
    if(!actor.IsStopped)
    {
      Action<IAttributesAgent> consumer = x => x.Replace(attributeSetName, attributeName, value);
      if(mailbox.IsPreallocated)
      {
        mailbox.Send(actor, consumer, null, ReplaceRepresentation2);
      }
      else
      {
        mailbox.Send(new LocalMessage<IAttributesAgent>(actor, consumer, ReplaceRepresentation2));
      }
    }
    else
    {
      actor.DeadLetters.FailedDelivery(new DeadLetter(actor, ReplaceRepresentation2));
    }
  }
  public void Remove(string attributeSetName, string attributeName)
  {
    if(!actor.IsStopped)
    {
      Action<IAttributesAgent> consumer = x => x.Remove(attributeSetName, attributeName);
      if(mailbox.IsPreallocated)
      {
        mailbox.Send(actor, consumer, null, RemoveRepresentation3);
      }
      else
      {
        mailbox.Send(new LocalMessage<IAttributesAgent>(actor, consumer, RemoveRepresentation3));
      }
    }
    else
    {
      actor.DeadLetters.FailedDelivery(new DeadLetter(actor, RemoveRepresentation3));
    }
  }
  public void RemoveAll(string attributeSetName)
  {
    if(!actor.IsStopped)
    {
      Action<IAttributesAgent> consumer = x => x.RemoveAll(attributeSetName);
      if(mailbox.IsPreallocated)
      {
        mailbox.Send(actor, consumer, null, RemoveAllRepresentation4);
      }
      else
      {
        mailbox.Send(new LocalMessage<IAttributesAgent>(actor, consumer, RemoveAllRepresentation4));
      }
    }
    else
    {
      actor.DeadLetters.FailedDelivery(new DeadLetter(actor, RemoveAllRepresentation4));
    }
  }
  public void Synchronize(Node node)
  {
    if(!actor.IsStopped)
    {
      Action<IAttributesAgent> consumer = x => x.Synchronize(node);
      if(mailbox.IsPreallocated)
      {
        mailbox.Send(actor, consumer, null, SynchronizeRepresentation5);
      }
      else
      {
        mailbox.Send(new LocalMessage<IAttributesAgent>(actor, consumer, SynchronizeRepresentation5));
      }
    }
    else
    {
      actor.DeadLetters.FailedDelivery(new DeadLetter(actor, SynchronizeRepresentation5));
    }
  }
  public void HandleInboundStreamMessage(AddressType addressType, RawMessage message)
  {
    if(!actor.IsStopped)
    {
      Action<IAttributesAgent> consumer = x => x.HandleInboundStreamMessage(addressType, message);
      if(mailbox.IsPreallocated)
      {
        mailbox.Send(actor, consumer, null, HandleInboundStreamMessageRepresentation6);
      }
      else
      {
        mailbox.Send(new LocalMessage<IAttributesAgent>(actor, consumer, HandleInboundStreamMessageRepresentation6));
      }
    }
    else
    {
      actor.DeadLetters.FailedDelivery(new DeadLetter(actor, HandleInboundStreamMessageRepresentation6));
    }
  }
  public void IntervalSignal(IScheduled<object> scheduled, object data)
  {
    if(!actor.IsStopped)
    {
      Action<IAttributesAgent> consumer = x => x.IntervalSignal(scheduled, data);
      if(mailbox.IsPreallocated)
      {
        mailbox.Send(actor, consumer, null, IntervalSignalRepresentation7);
      }
      else
      {
        mailbox.Send(new LocalMessage<IAttributesAgent>(actor, consumer, IntervalSignalRepresentation7));
      }
    }
    else
    {
      actor.DeadLetters.FailedDelivery(new DeadLetter(actor, IntervalSignalRepresentation7));
    }
  }
  public void Stop()
  {
    if(!actor.IsStopped)
    {
      Action<IAttributesAgent> consumer = x => x.Stop();
      if(mailbox.IsPreallocated)
      {
        mailbox.Send(actor, consumer, null, StopRepresentation8);
      }
      else
      {
        mailbox.Send(new LocalMessage<IAttributesAgent>(actor, consumer, StopRepresentation8));
      }
    }
    else
    {
      actor.DeadLetters.FailedDelivery(new DeadLetter(actor, StopRepresentation8));
    }
  }

}
}
tjaskula commented 5 years ago

Another variation:

vlingo-net/actors: vlingo-net/actors: Generating proxy for main: IClusterSnapshot
Dynamically generated class source for Vlingo.Cluster.Model.ClusterSnapshot__Proxy did not compile because: The type 'Action<>' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Runtime, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.
   at Vlingo.Common.Compiler.DynaCompiler.Compile(Input input)
vlingo-net/actors: vlingo-net/actors: Generating proxy for test: IClusterSnapshot
Dynamically generated class source for Vlingo.Cluster.Model.ClusterSnapshot__Proxy did not compile because: The type 'Action<>' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Runtime, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.
   at Vlingo.Common.Compiler.DynaCompiler.Compile(Input input)
Dynamically generated class source for Vlingo.Cluster.Model.ClusterSnapshot__Proxy did not compile because: The type 'Action<>' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Runtime, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.
   at Vlingo.Common.Compiler.DynaCompiler.Compile(Input input)
System.Net.Sockets.SocketException (48): Address already in use
   at System.Net.Sockets.Socket.UpdateStatusAfterSocketErrorAndThrowException(SocketError error, String callerName)
   at System.Net.Sockets.Socket.DoBind(EndPoint endPointSnapshot, SocketAddress socketAddress)
   at System.Net.Sockets.Socket.Bind(EndPoint localEP)
   at Vlingo.Wire.Fdx.Inbound.SocketChannelInboundReader.OpenFor(IChannelReaderConsumer consumer)
   at Vlingo.Wire.Fdx.Inbound.InboundStreamActor.Start()
System.Net.Sockets.SocketException (48): Address already in use
   at System.Net.Sockets.Socket.UpdateStatusAfterSocketErrorAndThrowException(SocketError error, String callerName)
   at System.Net.Sockets.Socket.DoBind(EndPoint endPointSnapshot, SocketAddress socketAddress)
   at System.Net.Sockets.Socket.Bind(EndPoint localEP)
   at Vlingo.Wire.Fdx.Inbound.SocketChannelInboundReader.OpenFor(IChannelReaderConsumer consumer)
   at Vlingo.Wire.Fdx.Inbound.InboundStreamActor.Start()
vlingo-net/actors: vlingo-net/actors: Generating proxy for main: IClusterSnapshot
Dynamically generated class source for Vlingo.Cluster.Model.ClusterSnapshot__Proxy did not compile because: The type 'Action<>' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Runtime, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.
   at Vlingo.Common.Compiler.DynaCompiler.Compile(Input input)
Actor instantiation failed because: ActorFactory failed actor creation for: Address[Id=14, Name=(none)]
   at Vlingo.Actors.Stage.CreateRawActor(Definition definition, Actor parent, IAddress maybeAddress, IMailbox maybeMailbox, ISupervisor maybeSupervisor, ILogger logger)
   at Vlingo.Actors.Stage.ActorProtocolFor[T](Definition definition, Actor parent, IAddress maybeAddress, IMailbox maybeMailbox, ISupervisor maybeSupervisor, ILogger logger)
vlingo-net/actors: Inbound stream listening: for 'OP'
Object reference not set to an instance of an object.
   at Vlingo.Actors.Stage.TestActorFor[T](Definition definition)
vlingo-net/actors: SocketChannelInboundReader: OPENING PORT: 37371

and the generated file:

using System;
using System.Collections.Generic;
using Vlingo.Actors;
using Vlingo.Common;
using Vlingo.Cluster.Model;
namespace Vlingo.Cluster.Model
{
public class ClusterSnapshot__Proxy : IClusterSnapshot
{
  private const string QuorumAchievedRepresentation1 = "QuorumAchieved()";
  private const string QuorumLostRepresentation2 = "QuorumLost()";

  private readonly Actor actor;
  private readonly IMailbox mailbox;

  public ClusterSnapshot__Proxy(Actor actor, IMailbox mailbox)
  {
    this.actor = actor;
    this.mailbox = mailbox;
  }

  public void QuorumAchieved()
  {
    if(!actor.IsStopped)
    {
      Action<IClusterSnapshot> consumer = x => x.QuorumAchieved();
      if(mailbox.IsPreallocated)
      {
        mailbox.Send(actor, consumer, null, QuorumAchievedRepresentation1);
      }
      else
      {
        mailbox.Send(new LocalMessage<IClusterSnapshot>(actor, consumer, QuorumAchievedRepresentation1));
      }
    }
    else
    {
      actor.DeadLetters.FailedDelivery(new DeadLetter(actor, QuorumAchievedRepresentation1));
    }
  }
  public void QuorumLost()
  {
    if(!actor.IsStopped)
    {
      Action<IClusterSnapshot> consumer = x => x.QuorumLost();
      if(mailbox.IsPreallocated)
      {
        mailbox.Send(actor, consumer, null, QuorumLostRepresentation2);
      }
      else
      {
        mailbox.Send(new LocalMessage<IClusterSnapshot>(actor, consumer, QuorumLostRepresentation2));
      }
    }
    else
    {
      actor.DeadLetters.FailedDelivery(new DeadLetter(actor, QuorumLostRepresentation2));
    }
  }

}
}

This one is strange because once the file added to the code it compiles.

tjaskula commented 5 years ago

@zpbappi I've tried to upgrade Vlingo-net-wire to latest actor but this change https://github.com/vlingo-net/vlingo-net-actors/commit/e76297674a5e8217944425cec5996f9dc92140a3 seems to break and I have the following exception:

vlingo-net/actors: vlingo-net/actors: Generating proxy for main: IScheduled`1
Dynamically generated class source for Vlingo.Common.Scheduled__Proxy did not compile because: The type or namespace name 'Actors' does not exist in the namespace 'Vlingo' (are you missing an assembly reference?)
   at Vlingo.Common.Compiler.DynaCompiler.Compile(Input input)
vlingo-net/actors: vlingo-net/actors: Generating proxy for test: IScheduled`1
Dynamically generated class source for Vlingo.Common.Scheduled__Proxy did not compile because: The type or namespace name 'Actors' does not exist in the namespace 'Vlingo' (are you missing an assembly reference?)
   at Vlingo.Common.Compiler.DynaCompiler.Compile(Input input)
Actor instantiation failed because: ActorFactory failed actor creation for: Address[Id=15, Name=(none)]
vlingo-net/actors: ActorFactory: failed actor creation. This is sometimes cause by the constructor parameter types not matching the types in the Definition.parameters(). Often it is caused by a failure in the actor constructor. We have attempted to uncover the root cause here, but that may not be available in some cases.
The root cause may be: Object reference not set to an instance of an object.
See stacktrace for more information. We strongly recommend reviewing your constructor for possible failures in dependencies that it creates.
vlingo-net/actors [Exception]: Object reference not set to an instance of an object.
   at Vlingo.Actors.Stage.CreateRawActor(Definition definition, Actor parent, IAddress maybeAddress, IMailbox maybeMailbox, ISupervisor maybeSupervisor, ILogger logger)
   at Vlingo.Actors.Stage.ActorProtocolFor[T](Definition definition, Actor parent, IAddress maybeAddress, IMailbox maybeMailbox, ISupervisor maybeSupervisor, ILogger logger)
Actor instantiation failed because: ActorFactory failed actor creation for: Address[Id=14, Name=(none)]
   at Vlingo.Actors.Stage.CreateRawActor(Definition definition, Actor parent, IAddress maybeAddress, IMailbox maybeMailbox, ISupervisor maybeSupervisor, ILogger logger)
   at Vlingo.Actors.Stage.ActorProtocolFor[T](Definition definition, Actor parent, IAddress maybeAddress, IMailbox maybeMailbox, ISupervisor maybeSupervisor, ILogger logger)
vlingo-net/actors [StackTrace]:    at Vlingo.Actors.TestKit.TestEnvironment..ctor()
   at Vlingo.Actors.Actor..ctor()
   at Vlingo.Wire.Channel.SocketChannelSelectionProcessorActor..ctor(IRequestChannelConsumerProvider provider, String name, Int32 maxBufferPoolSize, Int32 messageBufferSize, Int64 probeInterval) in /Users/tjaskula/Documents/GitHub/vlingo-net-wire/src/Vlingo.Wire/Channel/SocketChannelSelectionProcessorActor.cs:line 33
vlingo-net/actors: Actor instantiation failed because: ActorFactory failed actor creation for: Address[Id=15, Name=(none)]

This happens on the following line :

Stage.Scheduler.Schedule(SelfAs<IScheduled<object>>(),
                null, TimeSpan.FromMilliseconds(100), TimeSpan.FromMilliseconds(probeInterval));
VaughnVernon commented 5 years ago

It may be a proxy generator but, not generating the correct code for some generic. Note that IScheduled recently was given a generic parameter.

zpbappi commented 5 years ago

@tjaskula looking into it. @VaughnVernon it does look like a proxy generator issue.

VaughnVernon commented 5 years ago

@zpbappi The proxy generator in Java was recently improved a bit to get around a few of these issues. If you haven't diff'd it lately you may want to check on what changed.

zpbappi commented 5 years ago

@VaughnVernon proxy generator is the one file that is completely different from Java version, because of the difference between java and c# code generation. I have seen the changes and will implement them in c# as well.

zpbappi commented 5 years ago

@tjaskula I am looking at your last reported stack trace. I have run a few tests, it does generate a valid source for generic interfaces (IScheduled<T>). The thing is, it generates based on a concrete type. We may need to change that, as I see it would become a problem soon. However, the stack trace you have provided (the last one), looks like the Scheduled_Proxy was generated in Vlingo.Common. That is problem as Common does not have any reference to the Actors. The way we go around this problem in Actors, is by creating that proxy class inside the Actors project. I am not sure if that can be achieved in Wire or should we even do it every project. Can you write a very simple and minimal test in Wire and push it so that it fails? I will try to fix that.

VaughnVernon commented 5 years ago

Yeah, didn't realize that was the problem. All common proxies should be copied/cached in vlingo-actors.

VaughnVernon commented 5 years ago

As long as it's in the Java classpath. For .net you may have to put it in the Common namespace.

https://github.com/vlingo/vlingo-actors/blob/master/src/main/java/io/vlingo/actors/Scheduled__Proxy.java

tjaskula commented 5 years ago

@zpbappi @VaughnVernon the proxy file is already in actor. It stopped working when this change was made on actors https://github.com/vlingo-net/vlingo-net-actors/commit/e76297674a5e8217944425cec5996f9dc92140a3. Nowadays, every proxy has to be copied manually to the related sources. It doesn't work on dynamic compilation as it works on java side.

@zpbappi if you want to reproduce, just pull the sources of wire and try to upgrade to the latest versions of actors and common. Some unit tests will fail on proxy generations.

VaughnVernon commented 5 years ago

The IScheduled<T> change was my guess, but I thought it was a code generation issue. Just changing the parameter from object to T shouldn't cause a problem, should it?

tjaskula commented 5 years ago

@zpbappi I've updated wire to new vlingo-net-common 4.5 and vlingo-net-actors 3.2 after the changes to the PR #45

I have still proxy generation problems. There are 2. The first one is when I try SelfAs<IScheduled<object>>() the following exception is as follows:

System.ArgumentException: Actor proxy IScheduled`1 not created for main or test: Actor proxy IScheduled`1 not created because: Dynamically generated class source did not compile: Vlingo.Common.Scheduled__Proxy<T> ---> System.ArgumentException: Actor proxy IScheduled`1 not created because: Dynamically generated class source did not compile: Vlingo.Common.Scheduled__Proxy<T> ---> System.ArgumentException: Dynamically generated class source did not compile: Vlingo.Common.Scheduled__Proxy<T>
  at at Vlingo.Common.Compiler.DynaCompiler.Compile(Input input)
  at at Vlingo.Actors.ActorProxy.TryGenerateCreate(Type protocol, Actor actor, IMailbox mailbox, ProxyGenerator generator, String targetClassName, String lookupTypeName)
  --- End of inner exception stack trace ---
  at at Vlingo.Actors.ActorProxy.TryGenerateCreate(Type protocol, Actor actor, IMailbox mailbox, ProxyGenerator generator, String targetClassName, String lookupTypeName)
  at at Vlingo.Actors.ActorProxy.TryGenerateCreate(Type protocol, Actor actor, IMailbox mailbox, String targetClassName, String lookupTypeName)
  --- End of inner exception stack trace ---
  at at Vlingo.Actors.ActorProxy.TryGenerateCreate(Type protocol, Actor actor, IMailbox mailbox, String targetClassName, String lookupTypeName)
  at at Vlingo.Actors.ActorProxy.CreateFor(Type protocol, Actor actor, IMailbox mailbox)
  at at Vlingo.Actors.ActorProxy.CreateFor[T](Actor actor, IMailbox mailbox)
  at at Vlingo.Actors.Stage.ActorProxyFor[T](Actor actor, IMailbox mailbox)
  at at Vlingo.Actors.Actor.SelfAs[T]()
  at Vlingo.Wire.Fdx.Inbound.InboundStreamActor.Start() in /Users/tjaskula/Documents/GitHub/vlingo-net-wire/src/Vlingo.Wire/Fdx/Inbound/InboundStreamActor.cs:71
  at at Vlingo.Actors.LifeCycle.<>c.<SendStart>b__23_0(IStartable x)
  at at Vlingo.Actors.LocalMessage`1.InternalDeliver(IMessage message)

The Vlingo.Actors has this Scheduled_Proxy https://github.com/vlingo-net/vlingo-net-actors/blob/master/src/Vlingo.Actors/Scheduled__Proxy.cs inside Vlingo.Actors namespace. However, from Vlingo.Wire the request to generate the proxy is done for Vlingo.Common because the namespace of the IScheduled<T> interface is in Vlingo.Common. The generated generated-sources/Vlingo.Common/Scheduled__Proxy is in Vlingo.Common namespace.

Questions:

tjaskula commented 5 years ago

@zpbappi @VaughnVernon writing the comment above I've just realized that likewise the change here https://github.com/vlingo-net/vlingo-net-actors/commit/e76297674a5e8217944425cec5996f9dc92140a3. the generic proxy generation now behaves differently.

Because the other things happened as well. The concrete generated proxy shouldn't be generic IMO. The generated proxy should be Scheduled__Proxy: IScheduled<SOMECONCRETETYPE> and not Scheduled<T>: Scheduled<T>

Because I have other proxies breaking as well, when before we had ResponseSenderChannel__Proxy : IResponseSenderChannel<Socket> and now I have ResponseSenderChannel__Proxy<T> : IResponseSenderChannel<T>

What do you think ?

zpbappi commented 5 years ago

@tjaskula I think __Proxy classes should be generic, and that's the change is implementing. Here is a very simple reason- if you want to create a proxy for IScheduled<int> somewhere and another proxy for IScheduled<string> somewhere else, what would be the proxy class?

tjaskula commented 5 years ago

Fair enough. However there is an issue either with looking up or instantiating such proxies

tjaskula commented 5 years ago

@zpbappi I've replaced inside Vlingo.Wire the old non generic ResponseSenderChannel__Proxy : IResponseSenderChannel<Socket> with ResponseSenderChannel__Proxy<T> : IResponseSenderChannel<T> and it seems that this is working.

The only problem I have is with Scheduled__Proxy:

vlingo-net/actors: vlingo-net/actors: Generating proxy for main: IScheduled`1
Dynamically generated class source for Vlingo.Common.Scheduled__Proxy<T> did not compile because: The type or namespace name 'Actors' does not exist in the namespace 'Vlingo' (are you missing an assembly reference?)

This might be the issue of looking up the proxy in different namespace than the generated Scheduled__Proxy<T> : IScheduled<T> which is in Vlingo.Actors namespace.

zpbappi commented 5 years ago

@tjaskula Creating proxy manually will always work. However, we can't keep doing that. I am on to that problem and trying to fix it with the latest version of Actors (0.3.2) in Wire. Seems like I will need some time to investigate.

tjaskula commented 5 years ago

I'll do that on my side as well.

tjaskula commented 5 years ago

I'm closing this issue because problems described here were fixed by the following PRs: