How about a slightly different architecture:

  1. Create a table, visible in all namespaces called Requests - and from Data Source namespace add 1 row to it on every new message.
  2. Create a table, visible in all namespaces called Ack which contains {RequestId, Namespace, State}
  3. In each namespace create a Business Service which would:
    1. Poll Requests/Ack tables to get new unprocessed requests (no corresponding Ack record).
    2. If an unprocessed request is found create an Ack record and send a message in a local namespace for BP processing
    3. Maybe write a response after the message is processed (or do it in BP/ProxyBP/job)

Advantage of this architecture is that you decouple processing on a namespace level - so if a production in one namespace is in error state/down the rest can proceed. It also eliminates a single point of failure in namespace switching job.
 

tl;dr instead of pushing your event make consumers pull it whenever convenient.

If you're sure that there's only one object in response array, replace:

Set tSC = pResponse.%JSONImport(tHttpResponse.Data.Read())

with:

Set tSC = pResponse.%JSONImport({}.%FromJSON(tHttpResponse.Data).%Get(0)) 

It would parse your JSON stream into a dynamic JSON array (via {}.%FromJSON(tHttpResponse.Data)), get zeroth element from it (via %Get(0)), and pass it for JSON import (via pResponse.%JSONImport).

If you're sure that there's only one object in response, replace:

Set tSC = pResponse.%JSONImport(tHttpResponse.Data.Read())

with:

Set tSC = pResponse.%JSONImport({}.%FromJSON(tHttpResponse.Data).%Get(0)) 

If you want to parse an entire array, you'll need another class:

Class CDSM.ProviderAPI.Responses Extends (%Persistent, %JSON.Adaptor) {

Property Responses As List Of CDSM.ProviderAPI.ProviderInfo;

}

And in this case replace this code:

Set pResponse=##class(CDSM.ProviderAPI.Response).%New()
Set tSC = pResponse.%JSONImport(tHttpResponse.Data.Read())

With:

Set pResponse=##class(CDSM.ProviderAPI.Responses).%New()
Set tSC = pResponse.%JSONImport(tHttpResponse.Data)

and update the method signature too.

Why would be better or recommended to use %CSP.REST directly, instead of EnsLib.REST.Service?

To start with using %CSP.REST is the recommended way to use REST with productions.

Are there any improvements if we use %CSP.REST?

It's easier to develop, there are more examples available, you can have a combined production/non-production REST services easily.

The first, but not the last one, so still not getting the idea of having this intermediate upgrade point.

Sure, but you can start freezing on 2016.2. There's no point in freezing if you jump to latest version from pre 2016.2

Sorry, on which topic? Everyone knows that Cache/IRIS never runs on an unsupported OS.

Upgrade path between Cache/IRIS versions where OS for old and new Cache/IRIS versions must be different.