Skip to content
This repository has been archived by the owner on Apr 6, 2020. It is now read-only.

Sync node branch #425

Merged
merged 84 commits into from
Sep 25, 2018
Merged

Sync node branch #425

merged 84 commits into from
Sep 25, 2018

Conversation

aboimpinto
Copy link
Contributor

several traces added in order to help finding the issue of disconnection of the peer.

IContainer dependency in MessageHandlerProxy removed and Strategy pattern is in place.

aboimpinto and others added 30 commits July 10, 2018 02:13
…terface but it's not anymore, threfore should not carry the prefix "I" that identify the interfaces.
Black listed peers try to connect test
…ge of the method RandomInt.

* Small clean up on the UtCrypto
more tests will be added soon!
* Fix an inverted if logic. The code only enter in the While loop if the cancellation was requested and should be the other way around.
Copy link
Collaborator

@osmirnov osmirnov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the goal for these changes? I am a strong beliver MVP should be based on the current code version instead of introduction a new project and making code to fit MVP. I suggest not to merge it into development but split it separate PRs that helps to run MVP with NeoSharp.Application.

containerBuilder.Register(typeof(IMessageHandler<>), messageHandlerTypes);
containerBuilder.RegisterInstanceCreator<IMessageHandler<Message>>(c =>
new MessageHandlerProxy(c, messageHandlerTypes, c.Resolve<ILogger<MessageHandlerProxy>>()));
containerBuilder.RegisterCollection(typeof(IMessageHandler<>), messageHandlerTypes);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the point in double registration?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For sure is not need... maybe was because of the MessageHandlerProxy registration that I left there.

this class will have his own interface and don't need to share the IMessageHandler or even the new IMessageHandler.

containerBuilder.RegisterCollection(typeof(IMessageHandler<>), messageHandlerTypes);
containerBuilder.RegisterCollection(typeof(IMessageHandler), new[]
{
typeof(VersionMessageHandler),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now we need to remember to add it here. In previous version all handlers were discoverable based on message type.

Copy link
Contributor Author

@aboimpinto aboimpinto Sep 20, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That can be done too ... and add to this list
This solution was to make it work with the direct injection of the list. Now we can refactor this in order to get this list any way we want where the last discovery feature can be implemented.

{
Task Handle(TMessage message, IPeer sender);
}

public interface IMessageHandler
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not type safe version.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What you mean "not type safe"? we don't need the message type.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean the handler can accept a message with any Message type. We do need message type because the first thing we do inside Handle method is casting to the right type

Copy link
Contributor Author

@aboimpinto aboimpinto Sep 20, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for sure we can find a solution for that .. using the IContainer inside this class was not right where there is patterns that solve this without using containers.

Would be nice to discuss a better solution about this where we don't use the IContainer, where er don't create the class already with the constructor and where we don't use know patterns like Strategy.

I will create a issue to remember this when we refactor this.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not a fan to pass IContainer as a dependency and it is the very last resort for me but, as you can see, we either do it and benefit from strongly typed code or we don't and have weakly typed code. My preference is the former. That being said, I would recommend reverting this change (untyped IMessageHandler interface) until we have a full identical solution. I prefer not to replace the working code with partial one backed by the issue.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to tell you the working code is not working .. that why was the change!!!

I'm glad that you aren't a fan of patterns ... then we can discuss that.
This PR is to fix something that wasn't working and wasn't against the code guidelines promoted by @gubanotorious indicating that we need to use known patterns as much we can.


return handleMessageTask.ContinueWith(t =>
var isHandled = false;
foreach (var handler in this._messageHandlers)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We cannot iterate through all message handler for every incoming message. It will be, for sure, a bottleneck.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

of course not .. will be a linq query similar of what we had that, from all the MessageHadlers will return the only one that satisfy the condition.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is still iterating even being hidden in LINQ

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we were already doing the same ... we where receiving a list and doing that ... this is just a clean way without using Reflection to create the objects.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What we are doing is we ask DI container to create the type safe version (that has Handle method with the first argument of actual Message type) of a message handler per message.

What this change introduces is it ask DI container to create the type unsafe version (that has Handle method with the first argument of generic Message type) of a message handler as singleton (single message handler will handle all compatible messages while the app is running) and, in addition, it searches per message through message handler instances to discover who first will be able to handle the message.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think Simple Injector allow that we can have Type Safe list injected in the constructor. I could not find a constructive example, just the documentation on their website

https://simpleinjector.readthedocs.io/en/latest/advanced.html?highlight=Collection

I will create a Issue requesting that this could be refactor and how.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue #427 added

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made a small refactor on the Handle method where the Foreach is removed.

I'm not a fan of the if statement
if (messageHandler == null)
{
this._logger.LogError($"could not find the handler for the message type {message.GetType()}");
return;
}
but I think that for now, until this method is not stable we can live with this. The LINQ query should return Single() because all the possible Messages should have a MessageHandler, if not, the developer didn't made is work well.

src/NeoSharp.Core/Network/Server.cs Show resolved Hide resolved
@@ -125,7 +125,8 @@ public bool ChangeProtocol(VersionPayload version)
public void Disconnect()
{
Dispose();
_logger.LogInformation("The peer was disconnected");
_logger.LogInformation($"The peer {this.EndPoint.Host}:{this.EndPoint.Port} was disconnected");
this._stream.Dispose();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The stream has to be disposed already in Dispose method call.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right!!! Still trying here... and learning a little bit about this.

the problem is this: after the peer is been disconnected I could not find a way to connected it again ... I try to dispose everything in order to call again Socket.Connect I got always a message saying: "the current socket is connected." (or something like this.

this will be clean up

@aboimpinto
Copy link
Contributor Author

MVP project will be removed. I thought to add it because would be nice to debug the Sync problem that we have and have a MVP / Feasibility project that works would help debug.

{
const string handleMethodName = nameof(IMessageHandler<Message>.Handle);
const BindingFlags bindingFlags = BindingFlags.FlattenHierarchy | BindingFlags.Instance | BindingFlags.Public;
var messageHandler = this._messageHandlers.SingleOrDefault(x => x.CanHandle(message));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I said before, this change alters the behavior we introduced before (message handlers per message vs singletons).
I am not a fan to pass IContainer as a dependency and it is the very last resort for me but, as you can see, in this case we need to have dynamic routing based on message type and to create message handlers on demand. I suggest to keep it in this was way to avoid possible side effects in message handlers. At present, any message handler can be disposed after a message is handled. My recommendation is reverting these changes (untyped message handlers, message handlers as singletons, iteration trough all message handlers for every message) until we have a full identical solution. I prefer not to replace the working code with partial one backed by the issue.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to remember that this code was not working and no one was understanding due the fact that was not fowling the standards.
Thanks for you opinion. It is important for us to move foward but this code was not fowling the code guidelines defined by @gubanotorious where we should use code patterns. This code was weak, using Reflection with a lot of loops to create the MesssageHandler and MessageInvokers. Now it's just have one loop and you prefer the old code.

I'm sure we can improve this code in the refactor phase. For now the code is working with no bugs.

@aboimpinto aboimpinto closed this Sep 24, 2018
@aboimpinto aboimpinto reopened this Sep 24, 2018
@codecov
Copy link

codecov bot commented Sep 24, 2018

Codecov Report

Merging #425 into development will decrease coverage by 0.59%.
The diff coverage is 17.25%.

Impacted file tree graph

@@              Coverage Diff               @@
##           development     #425     +/-   ##
==============================================
- Coverage        54.63%   54.03%   -0.6%     
==============================================
  Files              297      296      -1     
  Lines            12238    12238             
==============================================
- Hits              6686     6613     -73     
- Misses            5552     5625     +73
Impacted Files Coverage Δ
src/NeoSharp.Core/Models/BlockBase.cs 0% <ø> (ø) ⬆️
src/NeoSharp.Core/Models/MinerTransaction.cs 100% <ø> (ø) ⬆️
src/NeoSharp.Core/Models/ClaimTransaction.cs 100% <ø> (ø) ⬆️
src/NeoSharp.Core/Models/InvocationTransaction.cs 80.55% <ø> (ø) ⬆️
src/NeoSharp.Core/Models/Witness.cs 27.5% <ø> (+3.58%) ⬆️
src/NeoSharp.Core/Models/IssueTransaction.cs 100% <ø> (ø) ⬆️
src/NeoSharp.Core/Models/Transaction.cs 100% <ø> (ø) ⬆️
src/NeoSharp.Core/Models/PublishTransaction.cs 100% <ø> (ø) ⬆️
src/NeoSharp.Core/Models/ContractTransaction.cs 100% <ø> (ø) ⬆️
src/NeoSharp.Core/Models/RegisterTransaction.cs 100% <ø> (ø) ⬆️
... and 33 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 2bb7763...2975a70. Read the comment docs.

@osmirnov osmirnov merged commit d97733d into CityOfZion:development Sep 25, 2018
@aboimpinto aboimpinto deleted the SyncNodeBranch branch September 25, 2018 23:53
@aboimpinto
Copy link
Contributor Author

thank!!!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants