locked
Pattern for selecting one partner from many similar ones? RRS feed

  • Question

  • I have encountered a problem trying to use the Kuka Educational Framework code. They use their own articulated arm contract which is different from the one that comes with MSRS. If I want to use either one or the other, how can I specify this? In other words, my service requires that an "arm" service is running, but should not care which one. Of course, it will have to know at runtime which one it has partnered with or it won't be able to send the correct requests. It could restrict itself to only the subset of operations that is common to both contracts (except that they are different classes and the types won't match!).

     

    I know that I can trawl through the service directory and find matching services just like the Dashboard, but I would prefer to programmatically specify the partners so that the partnering happens automatically as soon as the services start up. Maybe what I want to do just isn't possible.

     

    By the way, I suspect this might be the tip of the iceberg. For instance, the Dashboard will not work with the Kuka LBR3 simulation because it can't find a generic arm contract (the MSRS version) even though there is a generic contract in place (the Kuka version) which is an expanded version of the MSRS one.

     

    Philosophically, this is a subclassing problem. I should be able to say that a Kuka contract is a subclass of a MSRS contract and therefore be able to use the MSRS operations with both of them (because they are a subset of the Kuka operations). This works at a code level with classes and subclasses, i.e. you can cast a subclass to its parent class.

     

    Is there any "inheritance" for contracts?

     

    Trevor

     

    P.S. Sorry -- this post wandered off the topic a bit ... :-0
    Thursday, November 22, 2007 12:25 PM

Answers

  • It is only possible to partner using attributes (declarative) if you know at compile time the exact contracts of the services you need. No magic here, this is a common issue.

     

    If you want to dynamically hook up with services that implement "arm-like" things, then you should

     

    1) Subscribe to the directory for the contracts you are aware of, or the contracts specified in your state file. So if a new contract is available someone just specifies a new config file with thenew contract! YOur service reads them, and subscribes to each one

    2) Using the ContractDirectory and QueryServiceContract, you can determine each operation a service supports, its types, it proxies dlls, etc all dynamically. FOr really advanced super wierd stuff, you can use this functionality to talk to any services. Some posts in this forum explain this. Using our contratc direcotry you can determine if a service implements the types (Get, Query, etc )  you know about so its very powerfull and future proof

     

    g

     

     

     

     

    Sunday, November 25, 2007 6:28 AM

All replies

  • We are starting to run into similar issues related to contract inheritance.

    In the ideal case, the KUKA service would implement the MSRS contract as an alternate contract and you would only send requests supported by that contract.  Likewise, you would specify partnerships based on the generic MSRS contract and use the manifest to specify the actual service that acts as partner.  This is the whole point of generic contracts.

    In one case where I am partnering programmatically with distinct contracts that share a subset of message types, I know in advance which contract I'm partnering with and I use that knowledge later when I need to send messages.  It would be great to have a portset type that takes two portset types as template arguments and exposes the intersection of their message types. I'd have to think about the details of instantiation/partnering.

    The main issue for us is the question of publicly releasing upgrades to a service.  If you want to add message types to the service contract, it seems to me that you need to define a whole new contract and then implement the old one as an alternate for backwards compatibility.  Over time one can imagine accruing a long list of alternate contracts attached to a service.  Likewise, if I release v 1.5 of my service, should I force the user to uninstall 1.0 and if not then I need to rename my assemblies, etc.  I suppose this is the whole point of the Y[XXXX].M[YY] assembly naming convention.

    cheers,
    R




    Thursday, November 22, 2007 5:04 PM
  • Hi Rob,

     

    I'm glad that I am not just a voice crying in the wilderness on this one. I think it is a fundamental flaw in the design of MSRS and that it will come back to bite a lot of people like yourself who are producing commerical software that needs to be updated continually.

     

    Updates to generic contracts need to be completely transparent to existing (read that as old) services that depend on them. Take the case for instance where you install some new software that uses an updated arm contract. Then you try to use the old software to control it. It won't work! Gee, that's exactly what happened with the Kuka robot arm simulation and the Dashboard!

     

    Part of the problem is the naming convention. There should be a generic name, and then a separate version number. It should then be possible to connect to a service by specifying "version 1.5 or higher" for instance. Provided that all new services retain the old operations and the state only ever has more properties added at the bottom, then it should be possible to continue to use the old classes that were defined previously and still talk to the service. Of course, feel free to tell me that I don't know what I am talking about and this is impossible ...

     

    I really don't know what the solution to this problem is, but I strongly recommend to Microsoft that they take a serious look at it for Version 2.0.

     

    Trevor

     

     

    Friday, November 23, 2007 5:22 AM
  • Using alternate contracts is the approach we recommend for maintaining backwards compatibility. I would respectfully disagree with Trevor that we dont have a versioning story. I think we have one that is much stronger than simple object inheritance.

     

    Alternate contracts can be implemented side by side to each other and services can also extend existing contracts (include operations and types from older contracts).

     

    In v2.0 we will be doing something that will help folks: The DssPRoxy code will generate an "uber" port that contains fields with port sets for each alternate contract a service supports. This way you can connect to any one of the contracts a service supports and send messages to any of its alternates!

     

    The DSS infra will allow you to send messages for any contract, to any URI the service handles. For example, if you have a ARM main contract and URI, plus you have a KUKA arm alternate contract and URI, you can send ARM msgs to the KUKA URI/port and the infra will attempt a re-route (transparently) to the main port.

     

    Versioning in a distributed environment is not easy, but alternate contracts, with their side-by-side and full isolation to each other, seem a reasonable first step, vs complicated naming schemes or numbering schemes

     

    thanx

    g

     

     

    Saturday, November 24, 2007 4:35 AM
  • Hi George,

     

    Thanks for not flaming me :-)  I can be a little dogmatic at times.

     

    I think that the V2.0 features should solve the problem.

     

    For right now though, I still don't see a solution to my problem. Please correct me if I have it wrong.

     

    What I want to do is write a service that uses the Kuka sim or another sim for a Lynxmotion arm that I am working on. The Kuka one implements its own contract which is an extension of the generic contract. I have only implemented the generic arm contract in the Lynxmotion sim. How do I declaratively (I think I said programmatically in my original post by mistake) set up the two services so that either one of them will connect? Is this even possiible?

     

    I can't make them both Required because only one will be running at a time. If I make them Optional then the orchestration service will not necessarily wait for them to start (or will it???) and I still have to figure out which one is the actual partner even though I might only be using the original generic subset of operations. So I guess I have to do a directory lookup and see which of the services has started. Of course I have to use the right port to send requests to anyway, so I suppose it's just a matter of trying a Get on each port.

     

    Maybe I have answered my own question.

     

    However, what happens if a third sim comes along that extends the Kuka contract? Then I will have to modify my code because it is not aware of this new contract even though it is backwards compatible with the previous two. And I would now have three ports!

     

    Trevor

     

    Sunday, November 25, 2007 1:57 AM
  • It is only possible to partner using attributes (declarative) if you know at compile time the exact contracts of the services you need. No magic here, this is a common issue.

     

    If you want to dynamically hook up with services that implement "arm-like" things, then you should

     

    1) Subscribe to the directory for the contracts you are aware of, or the contracts specified in your state file. So if a new contract is available someone just specifies a new config file with thenew contract! YOur service reads them, and subscribes to each one

    2) Using the ContractDirectory and QueryServiceContract, you can determine each operation a service supports, its types, it proxies dlls, etc all dynamically. FOr really advanced super wierd stuff, you can use this functionality to talk to any services. Some posts in this forum explain this. Using our contratc direcotry you can determine if a service implements the types (Get, Query, etc )  you know about so its very powerfull and future proof

     

    g

     

     

     

     

    Sunday, November 25, 2007 6:28 AM
  • Thanks George. I was hoping that it would not be necessary to write any code because you could declaratively specify an "arm-like" contract and DSS would trawl through all of the services for you to find the compatible ones. I guess that 1) above basically gives you that option. Perhaps there should be a pattern for this?

     

    Let's give it a rest :-)

     

    Trevor

     

     

    Monday, November 26, 2007 10:21 AM