Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Actor builder and updates #51

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open

Actor builder and updates #51

wants to merge 2 commits into from

Conversation

BrandonArp
Copy link
Member

Just a preview. I need to add the GraphiteSink back in with Akka actors. I might also pull out the updates from the ActorBuilder stuff.

@BrandonArp
Copy link
Member Author

The GraphiteSink was updated and the updated dependencies are in a separate PR. Please take a look at #52 before this.

@BrandonArp BrandonArp force-pushed the actor_builder branch 3 times, most recently from 0788e13 to bbcee86 Compare January 9, 2017 18:32
@BrandonArp
Copy link
Member Author

Rebased off the updated dependencies. There are a few minor changes in here that are unrelated: minor refactor of emitter creation, changing to Java-based futures in Status actor.

*
* @author Brandon Arp (brandon dot arp at inscopemetrics dot com)
*/
public class NonJoiningClusterJoiner extends UntypedActor {
Copy link
Member

Choose a reason for hiding this comment

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

Final?

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh you and your final classes.

* @param builder Builder to create the Props from
* @return a new {@link Props}
*/
private static Props props(final Builder builder) {
Copy link
Member

Choose a reason for hiding this comment

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

Builder is unused and the method is private

Copy link
Member Author

Choose a reason for hiding this comment

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

The builder references the static method as the constructor for the Props. It looks similar to our other actors (except for the private part). I could make the props method public, but I'm not sure what that would really achieve.

Copy link
Member

Choose a reason for hiding this comment

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

I guess my confusion here is that the builder argument is unused and since it's static it can't be overwritten. This is also not the standard builder pattern so it's not invoked reflectively. Still a little confused here.

Copy link
Member Author

Choose a reason for hiding this comment

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

The Builder still references this method just like the constructor in the other Builders. The base builder takes a Function<Builder, Props>. Hence the need to have that signature.

* Public constructor.
*/
public NonJoiningClusterJoiner() {
LOGGER.info()
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't this go in the actor startup routine, not the ctor?

Copy link
Member Author

Choose a reason for hiding this comment

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

Eh, I could put it on the onStart. I've tended toward the constuctor, though.

Copy link
Member

Choose a reason for hiding this comment

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

Truth in advertising. It doesn't "start" on construction.

.log();
}

@Override
Copy link
Member

Choose a reason for hiding this comment

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

Inherit doc

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed.

super(NonJoiningClusterJoiner::props);
}

@Override
Copy link
Member

Choose a reason for hiding this comment

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

Same.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed.

.thenApply(CAST_MAPPER);
stateFuture.whenComplete(
(statusResponse, throwable) -> {
final boolean healthy = _cluster.readView().self().status() == MemberStatus.up() && !_quarantined;
Copy link
Member

Choose a reason for hiding this comment

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

Objects.equal instead of ==

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed

try {
final Class<?> clazz = Class.forName(type);
final Class<? extends Builder<? extends Props>> builder = getBuilderForClass(clazz);
final Builder<? extends Props> value = _mapper.readValue(treeNode.toString(), builder);
Copy link
Member

Choose a reason for hiding this comment

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

You should be able to avoid the toString here

Copy link
Member Author

Choose a reason for hiding this comment

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

I think I found a suitable alternative. Docs indicate that it should be more efficient.

@Override
public Props deserialize(final JsonParser p, final DeserializationContext ctxt) throws IOException {
final TreeNode treeNode = p.readValueAsTree();
final String type = ((TextNode) treeNode.get("type")).textValue();
Copy link
Member

Choose a reason for hiding this comment

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

This seems like a bit of reinvention. Type mapping is already supported by Jackson, I know we haven't used it, but I think so far we've avoided this level of generality. For example we have a getClass helper from config which we then use to deserialize but we never fetch the builder by hand. Could we just do something like that here?

Copy link
Member Author

Choose a reason for hiding this comment

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

I tried, but I couldn't pull it off. This was the best I was able to do. Everything else got.... interestingly broken. It had to do with the return type all being Props, but the deserializer not being a subclass of Props and the fact that each Props will have a different constructor. I don't think Jackson was setup to do that.

Copy link
Member

Choose a reason for hiding this comment

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

Hrm. Ok.

The use case seems to me be a combination of 1) Polymorphism; different builder types as determined by a field; 2) The use of a builder. In the first we've either done explicit type request via a TypeReference or annotation based binding via a type field.

Props is final so you can't wrap it or extend it in order to annotate it.

http://doc.akka.io/japi/akka/2.4.0/akka/actor/Props.html

The problem seems to be that we're storing any Props here for the _clusterJoinerActor which is not type-complete (I'm guess not just any actor can be a "joiner actor").

For example, if the Props were wrapped with NonJoiningClusterJoiner and we used that type here (or more correctly an interface of that type) then we would be just to a manageable polymorphic deserialization problem (e.g. annotate the subclasses of that interface). Using Props directly corners us in many ways, and doesn't help describe what is actually required here.

Happy to discuss.

@BrandonArp BrandonArp force-pushed the actor_builder branch 2 times, most recently from 4bb2285 to ac364ff Compare January 31, 2017 07:16
@@ -429,6 +455,8 @@ public Builder setDatabaseConfigurations(final Map<String, DatabaseConfiguration
private RebalanceConfiguration _rebalanceConfiguration;
@NotNull
private String _clusterHostSuffix = "";
@NotNull
private Props _clusterJoinActor = new NonJoiningClusterJoiner.Builder().build();
Copy link
Member

Choose a reason for hiding this comment

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

This isn't actually an actor. Do we want it to be? In the past we've done that through Guice, but as this is configuration I am inclined to say it's Props, but the name should probably reflect that.

Copy link
Member Author

@BrandonArp BrandonArp Jan 31, 2017

Choose a reason for hiding this comment

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

At the end of the day it becomes an actor. I don't want the people configuring the service to have to know that they're actually building a Props that will get created into an actor. As far as they know, they want to configure an actor.

Also, the class that you give it in the config is an actor. It's just the actor builder that need to build a Props to create the actor.

@BrandonArp
Copy link
Member Author

I've addressed most of the concerns. The implementation doesn't feel quite right still, but the semantics of the config file match what I want. It feels like there is still something to do for the declared type on the config classes, or perhaps in the way it polymorphically deserialize (or, rather, the way it doesn't use the built-in Jackson polymorphic deserialization).

@BrandonArp BrandonArp force-pushed the actor_builder branch 2 times, most recently from 1837c08 to 3cc4086 Compare February 1, 2017 08:55
@BrandonArp BrandonArp force-pushed the actor_builder branch 2 times, most recently from e8a63f4 to b420e27 Compare February 22, 2017 09:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants