Checking status_code of an invoked service


#1

Hey there!

When invoking another service, if the invoked service sets the response in a way such as:

self.response.status_code = OK
self.response.payload = result

Or such as:

self.response.status_code = CONFLICT
self.response.payload = result

How can I check the value of status_code from the service that invokes another service?

Thanks.


#2

This is not possible - without an HTTP request, the headers that you set in your service are never used anywhere.

The logic under the hood is that, since this is not an HTTP request, no HTTP processing takes place at all and there is no HTTP response to extract this information from.

Similarly, if you use HTTP then (say) AMQP metadata will be ignored. This is the same principle.


#3

Understood. It makes sense.

I was asking this because I have this situation in which a tier-2 service is beginning a transaction and then passing on the session to a number of invoked tier-1 services. These tier-1 services may be called directly or by a tier-2 service. So, when a tier-1 service detects and reuses the session, there’s still the chance that it cannot complete the request and has to return an error.

And I am figuring out the proper way in which a tier-2 service should detect such error and, perhaps, clear a number of cache entries in addition to rolling back the transaction (which is the easy part).

So, my question would be, in addition to what is being sent back through the payload (which is received as result[‘response’] by default), which other parameters, if any, are available at the tier-2 service when invoking a tier-1 service? Or should I just use some key in the dictionary being assigned to the payload by the tier-1 service (e.g. error)?

Thanks.


#4

I think it is easiest to keep in mind that there is a separation between data returned and protocols or data formats that this data uses.

To return data, one uses self.response.payload. Usage of any other protocol-specific automatically ties one in to that other protocol.

When you call a service using self.invoke, this is internally treated as a call from a separate channel that is unrelated to HTTP. Naturally, HTTP / REST are super-popular so I can see a need to make use-cases such as yours possible to handle but currently, this is not possible in a way other than returning what you need via self.response.payload.

What you can do in the other direction is to provide additional parameters to your backend services via environ dictionary, e.g.

self.invoke(service_name, request, environ={‘key’:‘value’})

The target service will now have access to this dictionary under self.environ. You could even create this dictionary in the initial service and have the other one populate it with additional information, which would be a way to exchange data without employing self.response.payload - this is an opaque dictionary and Zato does not inspect it.

By the way - all the possible channel types, including internal ones, are in zato.common.CHANNEL.


#5

Excellent! That seems like the way to proceed. I’ll give it a try as soon as possible. Come to that, it looks like the best way to pass on the session, as discussed on a separate thread, doesn’t it? This way it would not interfere in the payload.


#6

Yes, this is a way to achieve it too. Basically, self.environ is a piece of user-defined opaque data, so you can transfer anything through it.


#7

Just made the changes in the code and it’s working fine. Thanks! :slight_smile: