Luca Burgazzoli created CAMEL-10638:
---------------------------------------

             Summary: Refactor ServiceCall EIP
                 Key: CAMEL-10638
                 URL: https://issues.apache.org/jira/browse/CAMEL-10638
             Project: Camel
          Issue Type: Improvement
          Components: camel-ribbon, camel-spring-cloud, camel-consul, 
camel-core, camel-etcd, camel-kubernetes
            Reporter: Luca Burgazzoli
            Assignee: Luca Burgazzoli
             Fix For: 2.19.0


As today the ServiceCall is implemented loading a ProcessorFactory using a 
ServiceLoader like system but this may cause issues as if you have multiple 
components providing an implementation of the ServiceCall SPI so i.e. if you 
have both consul and etcd components in the classpath, the following set-up 
will be initialized with the first ServiceCall SPI found in the classpath 
regardless of the consulConfiguration/etcdConfiguration:

{code:java}
from("timer:consul?period=1s")
    .serviceCall()
        .name("consul")
        .consulConfiguration()
        ...
    .end();
from("timer:etcd?period=1s")
    .serviceCall()
        .name("etcd")
        .etcdConfiguration()
        ...
    .end();
{code}

It may be better to have a different way to set-up the ServiceCall so that each 
element (server discovery, load balancer, server chooser) is provided instead 
of created by the ServiceCall ProcessorFactory.

A possible - high level - definition of the classes may look like:

{code:java}
interface ServiceCallLoadBalancer extends Processor {
    void setServerDiscovery(ServiceCallServerDiscovery serverDiscovery);
    void setServerChooser(ServiceCallServerChooser serverDiscovery);
}

interface ServiceCallServer {
    String getServiceId();
    String getHost();
    int getPort();
    Map<String, String> getMetadata();    
}

interface ServiceCallServerDiscovery {
    List<ServiceCallServer> getInitialListOfServers(String serviceId);
    List<ServiceCallServer> getUpdatedListOfServers(String serviceId); 
}

interface ServiceCallServerChooser {
    ServiceCallServer choose(List<ServiceCallServer> serverList)
}

class ServiceCallConfiguration {
    public void setServiceId(String serviceid);
    public void setComponent(String component);
    public void setUri(String uri);
    public void setExpression(Expression expression);

    public void setLoadBalancer(String loadBalancerRef);
    public void setLoadBalancer(ServiceCallLoadBalancer<ServiceCallServer> 
loadBalancer);

    public void setServerDiscovery(String serverDiscoveryRef);
    public void 
setServerDiscovery(ServiceCallServerDiscovery<ServiceCallServer> 
serverDiscovery);

    public void setServerChooser(String serverChooserRef);
    public void setServerChooser(ServiceCallServerChooser<ServiceCallServer> 
serverChooser);
}

class ServiceCallDefinition extends ServiceCallConfiguration {
    public void setConfiguration(ServiceCallConfiguration configuration);
    public void setConfiguration(String configurationRef);
}
{code}

The configuration part will be similar to the one we have today except the 
etcdConfiguration/consulConfiguration/etc will be removed in favor of a generic 
one, like:

{code:java}
ServiceCallServerDiscovery sd = new EtcdServiceCallServerDiscovery(conf);

from("timer:consul?period=1s")
    .serviceCall()
        .name("consul")
        .loadBalancer("my-load-balancer")
        .serverDiscovery(sd)
        .serverChooser(servers -> servers.get(0))
        .end();
{code}

There will be a default implementation of the load balancer so defining it may 
not be needed but environment like spring-cloud could provide a different 
implementation.

[~davsclaus] what do you think ?




--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to