Router Production can have different business services listening on same port number?

Primary tabs

Replies

simply NO! no OS would allow this.
1 port = 1 listener
but you may build a listener dispatching to various services according to some content / signal you receive.
or using a kind of load balancer to distribute incoming messages

How are you planning to determine to which service the message should go?

Hi

Business Services support an OnInit() method and in that method you could write some code like this:

In the Business service add the following Parameters:

Parameter StartPort = 51000

Parameter LastPort = 51100

Parameter SETTINGS = "StartPort:Basic,LastPort:Basic"

/// You will need a mapping table to global in the form ^BusinessServiceProductionNames({Bussiness_Service_ClassName})={Production_Item_Name}

method OnInit() as %Status

{

    set tSC=$$$OK

    try {

        set  tPort=..#StartPort,found=0

        while 'found {

              if $l($g(^BusinessServicePorts(tPort))) {

                     set tPort=tPort=tPort+1

                     if tPort>..#LastPort {set tSC=$$$ERROR(5001,"Cannot find available Port") $$$ThrowStatus(tSC)}

                     else {continue}

             Else {

                     set ^BusinessServicePorts(tPort)=$classname(),^BusinessServicePortsIndex($classname())=tPort

                     set ..Adapter.Port=tPort,found=1 quit

              }

         }

    }

    catch ex {set tSC=ex.AsStatus()}

    if 'tSC!('found) set ..Adapter.Port=""

    quit tSC

}

method OnTearDown () as %Status

{

    set tSC=$$$OK

    try {

         if ..Adapter.Port'="" {

              kill ^BusinessServicePorts(..Adapter.Port),^BusinessServicePortsIndex($classname())

       }

    }

    catch ex {set tSC=ex.AsStatus()}

    quit tSC

}

The only thing you would need to do now is somehow notify the Client appliction would need to be notified which Port they should use to access a particular Business Service. I would suggest a WebService that accepts a request consisting of a property "BusinessServiceName" and will return ^BuinessServiceNames($classname()) and a second property "BusinessServicePort" which will return ^BusinessServicePortsIndex($classname())

You would need to supply the client with a list of available Business Service Names and what the Business Service Does. Again you could do this with a WebService which the client invokes and the WebService would return a List of Business Services and Function Description

This solution does make certain assumptions such as the client being willing/able to introduce the code to invoke the WebServices to get the list of Available Services and the Port number for a specific Business Service

The reason you need a 'LastPort" parameter is to ensure that the Business Service will not get into a loop testing every port from 51000 through to whatever the last Possible port number is in TCP/Port architecture

Nigel

This is interesting, so in the init() method can I check the HL7 message sending facility field?  so assume

System A - > ADT Service Port 5100 -> Init(check MSH Sending Facility) - > EdgeProduction 1

System B - > ADT Service Port 5100 -> Init(check MSH Sending Facility) - > EdgeProduction 2

Hi

No, the OnInit() method is called when the Business Service Starts Up, the OnTearDown() is invoked when the Business Service stops. The OnInit() is not aware of the request message and therefore It is not aware of any Request messages at this point. The ProcessInput() and more specifically the OnProcessInput() method is the first time you get to see the incoming request message and it is in the OnProcessInput() method that you decide what you are going to do with the request HL& Message, whether you route it to a Business Process based on the Ensemble HL7 Passthrough Architecture or whether you pass it to a custom Business Process However I made the assumption that your Business Service is a conventional HL7 TCP Inbound Adapter based service. 

If however it is an HTTP REST service then that is another matter altogether. If it is an HTTP REST service then by default the request will be handled by the %CSP.REST Dispatch class. The basic functionality of the %CSP.REST class is to route HTTP requests to a Business Service. You can inherit the %CSP.REST class into your own REST dispatcher class. 

I have a REST Dispatcher class in Ensemble that emulates the IRIS FHIR End Point functionality.

I have 4 csp applications defined:

/csp/endpoint

/csp/endpoint/endpointA

/csp/endpoint/endpointB

/csp/endpoint/EndPointC

All 4 csp applications invoke my custom Rest.Dispatch class (which inherits from %CSP.REST) 

I have a Business Service Class named BusinessService.MyEndPointService

I create 4 Business Services in my production

End Point General (/csp/endpoint)

End Point A (/csp/endpoint/endpointA

and so on

In the Rest Dispatch class I look at the request URL and based on the URL I invoke the OnRequest() method of the Appropriate Business Service using the Production Service Name.

However as I am writing this there is something in the back of my mind that is telling me that if you are using the EnsLib.HL7.TCP Adapter that you can reroute an incoming message to another service but I would have to go back to the documentation to remind myself of what exactly you can do and how it works.

The most common way that developers normally use is the EnsLib.HL7.MsgRouter architecture where you create routine rules that test the MSH Message Structure and you can then route the message to another specific Business Process to process that specific Message Type. This is all handled through the Management Portal->Ensemble->Build set of functions which allow you to create Business Processes, Business Rules, Transformations and so on.

If you are using HTTP REST and want more information on how I have implemented that then I would send you a far more detailed description of my implementation.

Nigel

Historically Cache and Ensemble did not support WebSockets and so you could not have two processes using the same (incoming) port but if I remember correctly IRIS supports WebSockets and though I can't remember how these work something in the depths of my mind tells me that I think WebSockets were aimed at this specific requirement

Check out the IRIS documentation on WebSockets

Nigel