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

Enabling event bus delivery options for communication between Server … #349

Merged
merged 8 commits into from
Dec 4, 2017

Conversation

tomaszmichalak
Copy link
Member


I hereby agree to the terms of the Knot.x Contributor License Agreement.

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
…and RepositoryConnectors/Knots; ServiceKnot and ServiceAdatpers; ActionKnot and ActionAdapters.
// hidden
}

public static AdapterProxy createProxy(Vertx vertx, Optional<DeliveryOptions> deliveryOptions, String address) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure how this fits into the architecture of this area of Knot.x but consuming an Optional as a parameter seems a bit strange. How about overloading the method to either accept the DeliveryOptions or not?

public static AdapterProxy createProxy(Vertx vertx, String address, DeliveryOptions deliveryOptions)
//...
public static AdapterProxy createProxy(Vertx vertx, String address)

The caller either has the delivery options or not. If they don't, with the current API, they need to pass an empty optional here.

I can see this pattern in more places and I'm wondering what the benefits of using an Optional this way are.

Copy link
Member Author

Choose a reason for hiding this comment

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

@toniedzwiedz Please check what is the expected behavior in this case. We have a configuration that has a getter:
Optional<DeliveryOptions> get()
It means that we expect DeliveryOptions may be not defined. Based on this value we want to create a factory method that uses two different methods with API (with and without DeliveryOptions). I don't know what is best in this situation...

@@ -31,5 +32,9 @@ static AdapterProxy createProxy(Vertx vertx, String address) {
return new AdapterProxyVertxEBProxy(vertx, address);
}

static AdapterProxy createProxyWithOptions(Vertx vertx, String address, DeliveryOptions deliveryOptions) {
Copy link
Contributor

Choose a reason for hiding this comment

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

why you added the new createProxy method ? can it be just one createProxy() method consuming deliveryOptions ?
I see that you created Factory specifically for instantiation of Knot's, Adapters, etc. that uses createProxy method with or without deliveryOptions. But it's not needed at all. A ....VertxEBProxy implementation handles it for you - if you will set deliveryOptions to null it will not use it - you don't need to do any handling or factories.

Copy link
Member

Choose a reason for hiding this comment

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

I'm just thinking out loud.
@marcinczeczko don't you agree that calling:
AdapterProxy.createProxy(vertx, address, null) looks odd?
Why the null? Should this interface force the user to pass DeliveryOptions parameter?
This is just to make the code look good, and skip in my opinion weird constructions like
Factory.construct(param, null, null, param2).

Copy link
Member Author

@tomaszmichalak tomaszmichalak Nov 29, 2017

Choose a reason for hiding this comment

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

@marcinczeczko You are right that Vert.x handle nulls. But as a result we will have to add nulls in all tests. So should we have AdapterProxy.createProxy(vertx, address, null) in all tests? Agree that it is "a sense of taste".

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, but I don't like overengineering by adding Factories to handle nulls, don't you think isn't too big for such small thing ?

Copy link
Member

Choose a reason for hiding this comment

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

After the offline catchup with @marcinczeczko:

  • let's not break compatibility and stay with 2 factory methods in ProxyGen helpers (like in this interface)
  • classes like XXXProxyFactory are a bit overengineered, let's just construct Proxies directly where it is necessary
  • Optional in config POJOs - suggestion here is to stick with Vert.x approach, and initialize not set properties with default values, e.g. in constructor:
...
deliveryOptions = config.containsKey("deliveryOptions") ? new DeliveryOptions(config.getJsonObject("deliveryOptions")) : new DeliveryOptions();
...

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.

@@ -30,5 +31,9 @@ static KnotProxy createProxy(Vertx vertx, String address) {
return new KnotProxyVertxEBProxy(vertx, address);
}

static KnotProxy createProxyWithOptions(Vertx vertx, String address, DeliveryOptions deliveryOptions) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same here as with AdapterProxy...

Copy link
Member Author

Choose a reason for hiding this comment

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

Done

@@ -31,5 +32,9 @@ static RepositoryConnectorProxy createProxy(Vertx vertx, String address) {
return new RepositoryConnectorProxyVertxEBProxy(vertx, address);
}

static RepositoryConnectorProxy createProxyWithOptions(Vertx vertx, String address, DeliveryOptions deliveryOptions) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same here as with AdapterProxy...

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

@@ -0,0 +1,36 @@
/*
Copy link
Contributor

Choose a reason for hiding this comment

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

See my initial comment - factories are not required at all

@@ -102,7 +103,8 @@ private KnotContext handleGetMethod(List<FormEntity> forms, KnotContext knotCont

private Single<AdapterResponse> callActionAdapter(KnotContext knotContext, FormEntity current) {
LOGGER.trace("Process form for {} ", knotContext);
AdapterProxy adapter = AdapterProxy.createProxy(vertx, current.adapter().getAddress());
AdapterProxy adapter = AdapterProxyFactory
Copy link
Member

Choose a reason for hiding this comment

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

Continuing @toniedzwiedz comment, this should rather look like:

AdapterProxy adapter = configuration.getDeliveryOptions().isPresent()
                                       ? AdapterProxyFactory.createProxy(vertx, configuration.getDeliveryOptions().get(), address)
                                       : AdapterProxyFactory.createProxy(vertx, address)

@@ -31,5 +32,9 @@ static AdapterProxy createProxy(Vertx vertx, String address) {
return new AdapterProxyVertxEBProxy(vertx, address);
}

static AdapterProxy createProxyWithOptions(Vertx vertx, String address, DeliveryOptions deliveryOptions) {
Copy link
Member

Choose a reason for hiding this comment

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

After the offline catchup with @marcinczeczko:

  • let's not break compatibility and stay with 2 factory methods in ProxyGen helpers (like in this interface)
  • classes like XXXProxyFactory are a bit overengineered, let's just construct Proxies directly where it is necessary
  • Optional in config POJOs - suggestion here is to stick with Vert.x approach, and initialize not set properties with default values, e.g. in constructor:
...
deliveryOptions = config.containsKey("deliveryOptions") ? new DeliveryOptions(config.getJsonObject("deliveryOptions")) : new DeliveryOptions();
...

@tomaszmichalak
Copy link
Member Author

CR fixes.


### Vert.x Event Bus delivery options

While HTTP request processing, Action Knot calls Adapter using
Copy link
Contributor

Choose a reason for hiding this comment

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

`During HTTP request processing, Knot communicates with Adapter over the Vert.x event bus. Low level aspects of that communication can be configured using Vert.x Delivery Options object. The caller of the Adapter, such as Action or Service Knot, can customise default settings by providing a deliveryOptions field in the config section of its configuration.

Comment: Can we move a description of setting up delivery option to one place ? e.g. on Knot documentation page ? it would be hard to manage doc if it's in multiple places

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

bus. It can be used to control the low level aspects of the event bus communication like timeouts, headers, message
codec names.

The `deliveryOptions` need to be added in the following place, of the Action Knot configuration to define the
Copy link
Contributor

Choose a reason for hiding this comment

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

deliveryOptions needs to be added as shown below:

NOTE: don't use Action Knot here as it can be set on any Knot

Copy link
Member Author

Choose a reason for hiding this comment

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

@marcinczeczko The communication takes place in three places:

  1. Between Server and Repository Connector / other Knots.
  2. Between Service Knot and Service Adapters.
  3. Between Action Knot and Action Adapters.

This is the reason we define those deliveryOptions in those places. So event publisher defines the event bus rules.

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.

headers, message codec names.


The `repositoryDeliveryOptions` need to be added in the following place, of the KnotxServerVerticle configuration to define
Copy link
Contributor

Choose a reason for hiding this comment

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

why it can be named deliveryOptions ??

Copy link
Member Author

Choose a reason for hiding this comment

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

We want to be able to specify deliveryOptions for a repository connector and knots separately.

Copy link
Member

Choose a reason for hiding this comment

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

If we want to have separate delivery options per each connected address, maybe we should have "global" deliveryOptions that defines default options for each Proxy and additionally allow to define options inside each section and keep consistent name deliveryOptions, e.g.:

{
  "main": "io.knotx.server.KnotxServerVerticle",
  "options": {
    "config": {
      "httpPort": 8092,
      "displayExceptionDetails": true,
      "deliveryOptions": {
        "timeout": 15000
      },
      "repositories": [
        {
          "path": "/content/local/.*",
          "address": "knotx.core.repository.filesystem",
          "deliveryOptions": {
            "timeout": 30000
          }
        },
        {
          "path": "/content/.*",
          "address": "knotx.core.repository.http",
          "deliveryOptions": {
            "timeout": 30000
          }
        }
      ],
      "splitter": {
        "address": "knotx.core.splitter"
      },
      "routing": {
        "GET": [
          {
            "path": ".*",
            "address": "knotx.knot.service",
            "deliveryOptions": {
              "timeout": 60000
            },
            "onTransition": {
              "next": {
                "address": "knotx.knot.handlebars"
              }
            }
          }
        ]
      },
      "assembler": {
        "address": "knotx.core.assembler"
      }
    }
  }
}

In the case above, following timeouts will be like:

  • filesystem repository: 30s,
  • http repository: 30s,
  • knotx.knot.service 60s,
  • all others 15s

Copy link
Member Author

Choose a reason for hiding this comment

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

@Skejven Your proposal looks very interesting. I recommend to merge the current solution and investige more advanced possibilities if required in the future.

Copy link
Member

@malaskowski malaskowski Nov 30, 2017

Choose a reason for hiding this comment

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

Let's then get rid of repositoryDeliveryOptions and enable setting it with name deliveryOptions either on verticle level (e.g. Server) or only on producer-level (e.g. only repositories).

Copy link
Contributor

@marcinczeczko marcinczeczko left a comment

Choose a reason for hiding this comment

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

I forgot to mention that two things need to be done before merging:

  • Update CHANGELOG.md
  • Update wiki UPGRADE NOTES.md - even if it does not require any action after upgrade, it's worth to mention that a delivery options can be customized with references to the documentation

@malaskowski malaskowski merged commit b179457 into master Dec 4, 2017
@malaskowski malaskowski deleted the feature/event-bus-timeouts branch December 4, 2017 07:47
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.

None yet

5 participants