- Connecting to the Avid Platform using the Avid Connector API
- Debugging the Gateway Connection
- Threading Model
- Using the Avid Connector API as a Client
- Using the Avid Connector API to Host Services
- Anatomy of a Node.js Platform Service
- Registering the Service
- Register Service With Custom Options
- Unregistering the Service
- Structured Errors
- Multi-Zone Services
- Getting Configuration Information from a Service Manager
- Providing Custom Service Health Information
- Changing Service Status
- Providing Compatible Version
- Using the Avid Connector API for Channels
- Logging
- Accessing Constants
- Exposing Operations for Upstream REST requests
- Auto Client API
- Metrics API
- Liveness probe
- Error Handling
- Migration Guides
Connecting to the Avid Platform using the Avid Connector API
The Avid Connector API connects to the Avid Platform over the Avid Secure Gateway. To connect your service to the Avid Platform, the Avid Secure Gateway must be running on a known host and port. The default port is 9900.
Default Connection Settings
By default the Avid Connector API connects using the following default options:
- Gateway Port: 9900
- Gateway Host: 127.0.0.1
- Query Timeout (ms): 10,000
- Connection Lost Threshold: 2000ms
- Reconnection Delay: 2000ms
- Initial Connection Attempts: -1 (infinite)
- Reconnection Attempts: -1 (infinite)
- Bus exponential back-off reconnection duration for unlicensed connection (ms): 600000
- Bus exponential back-off reconnection jitter for unlicensed connection: true
When connecting to Avid Platform, authentication provider may be specified with valid ClientId and ClientSecret. If service is started from trusted IP address, it may be started w/o authentication provider. In this case authentication provider must be null
:
To connect to the Avid Platform using the default settings:
1 | var bal = require('proxy-bal'); |
To connect to the Avid Platform with authentication provider:
1 | var bal = require('proxy-bal'); |
Overriding Default Settings with Environment Variables
Some of the default connection settings can be overridden using environment variables, as indicated in the following table:
Environment Variable | Description |
---|---|
ACS_BUS_QUERY_TIMEOUT | The default timeout (in ms) for queries. Default is 10000 ms. |
ACS_GATEWAY_HOST | Gateway connection host (Default 127.0.0.1) |
ACS_GATEWAY_PORT | Gateway connection port (Default 9900) |
ACS_GATEWAY_UNSECURE_PORT | Port for not secured connection. Default is 9966 |
ACS_GATEWAY_PROTOCOL_SEQUENCE | Sequence of protocols (or just one protocol) separated by coma ‘,’ in which Avid Connector API will try to establish connection to Secure Gateway. Default is ‘wss’. Allowed protocols are ‘wss’ and ‘ws’. Possible combinations are ‘wss,ws’, ‘ws’, ‘wss’ or ‘ws,wss’. |
ACS_PLATFORM_IDENTIFIER | Unique node identifier, where wrapper is running, provided by target platform, i.e. AWS, Open Stack etc. (Default ‘unknown’) |
ACS_SERVICE_BUILD_NUMBER | RPM or any other binary version of the service, hosted by the wrapper (Default ‘unknown’) |
ACS_ENVIRONMENT_IDENTIFIER | Environment identifier is basically chef generalized identifier for any collection of nodes (Default ‘unknown’) |
ACS_GATEWAY_CONNECTION_LOST_THRESHOLD | Amount of time, after which connection to Gateway considered as broken if we didn’t get ping from gateway. (Default 5000 ms) |
ACS_BUS_INITIAL_CONNECTION_ATTEMPTS | Number of initial connection attempts to Secure Gateway. Default is -1, means infinite number of connections. |
ACS_GATEWAY_CONNECTION_LOST_THRESHOLD | Amount of time, after which connection to Gateway considered as broken if we didn’t get ping from gateway. (Default 5000 ms) |
ACS_BUS_RECONNECTION_ATTEMPTS | Number of subsequent reconnections to Secure Gateway. Default is -1, means infinite number of reconnections. |
ACS_BUS_RECONNECTION_DELAY | Delay in ms between connection attempts to Secure Gateway. This delay same both for initial connection attempts and reconnections attempts. Default is 1000 ms. |
ACS_BUS_MAX_BACK_OFF_DURATION | Maximum duration of back-off re-connection attempts for unlicensed connection. (Default 600000 ms) |
ACS_BUS_BACK_OFF_JITTER | Back-off reconnection jitter for unlicensed connection. (Default true) |
ACS_SECURITY_TRUST_SELF_SIGNED | Whether to trust (true) or not trust (false) to self signed certificates (Default true) |
ACS_METRICS_TAG | Metric tag used by metrics to make metric unique. Default value is “default”. |
ACS_METRICS_ENABLED | Whether or not metrics are enabled. By default metrics are enabled. |
ACS_METRICS_REPORT_INTERVAL | Defines metrics reporter interval in seconds (default 10) |
ACS_WEBSOCKET_HANDSHAKE_TIMEOUT | Timeout in milliseconds for the handshake request |
ACS_WEBSOCKET_KEEPALIVE_INTERVAL | Keepalive interval in milliseconds for sending ping message |
ACS_HTTP_SERVER_ENABLED | Enables Http Server (now only Liveness Probe reporting functionality). Defaults to false. |
ACS_HTTP_SERVER_LISTEN_HOST | Ip address or host to bind HTTP server to. Defaults to 0.0.0.0 . |
ACS_HTTP_SERVER_LISTEN_PORT | Port for HTTP liveness server to listen to. Defaults to 9991. |
Overriding Default Settings in Code
You can override the default settings directly in your code by passing an options object when you create the Access
object. The following example shows the possible settings:
1 | var access = bus.createAccess({ |
Note that you only need to pass in the settings you wish to override. For example:
1 | var access = bus.createAccess({ |
Debugging the Gateway Connection
The Avid Connector API and the gateway have an internal failover logic that validates the connection between them. If you are debugging your service in an IDE or on the command line, a breakpoint can block your service from receiving the information it needs to know that it is still connected to the Secure Gateway. To prevent the service from thinking it has lost its connection to the Secure Gateway, and thus failing over into reconnection mode, you should set the variable ACS_GATEWAY_CONNECTION_LOST_THRESHOLD=600000 (10 minutes). This should prevent the service from thinking it has lost its connection while giving you enough time to inspect the information you need at the breakpoint.
Threading Model
Due to the nature of the Node.js (javascript), everything is executed in the event loop and it is not possible to configure number of threads for processing incoming or outgoing messages.
Alternatively you may think about multiprocess execution of the Node.js services to distribute load, or start service on several nodes in cluster.
Using the Avid Connector API as a Client
The Avid Connector API can be used to query services, send to services, and broadcast to services. Messages are a simple JavaScript object of the following format:
1 | { |
Providing Message Options
With each message operation (e.g query, send and broadcast) you may provide message options. The following options are available:
- timeout - Specifies a message timeout in ms for query operations. Default is 10000ms.
- durable - Sets whether message should be durable or not. Default is false. NOTE: This option is currently not implemented, and will be revised in the future releases.
- anyCompatibleVersion - Set whether the message should be delivered to any compatible version of the service or to an exact version of the service. Default is true.
1 | var opt = { |
Querying Services
Service queries are messages that invoke a service operation and expect a response. Response and timeouts are returned via separate callbacks:
1 | var m = { |
Sending to Services
Sending to a service is a one-way communication from the client to the service. There is no response. In comparison to a broadcast (described below), the client is also guaranteed that no more than one service instance will process the message.
1 | var m = { |
Broadcasting to Services
Broadcasting to a service is a one-way communication from the client to all instances of a given service. There is no response. As opposed to a send, the message is processed by every available instance of the service.
1 | var m = { |
Remote Zone and Multi-Zone Communications
The default behavior of the Avid Connector API is to communicate within its own local zone. All of the example above use this default behavior. If the local zone has been initialized in a multi-zone environment, however, it is possible to also communicate with services in other zones.
Zone-Specific Communications
To communicate with a specific remote zone, use the access.zone(zoneID)
object. The following are examples of communications with a specific remote zone:
1 | var m = { |
In all the above cases, only services in the remote zone with an ID of 85a6af75-5fa1-46d7-bb09-66f4cc1cf9f7
are invoked. In addition, only the service instances registered with a scope of multi-zone
are considered.
Muti-Zone Communications
To communicate across multiple zones, use the access.multiZone()
object. The following are examples of multi-zone communications:
1 | var m = { |
Note that access.multiZone().query
and access.multiZone().send
only send to one service instance in one zone. If there is a service instance in the local zone, it sends to that one. Otherwise it sends to a service instance in a remote zone (if one is available and registered with the multi-zone
scope). This is particularly useful if you know the service is in a zone, but aren’t sure which one.
access.multiZone().broadcast
broadcasts to all matching service instances in all zones.
Local Zone Communications
Note that there is also an access.localZone()
object. Invoking query
, send
, and broadcast
on this object is functionally equivalent to invoking the same methods on the base access
object.
Wildcard Usage in the Realm
If multiple realms of the same service are registered, you can use wildcards to address any service instance satisfying the wildcard expression. Wildcards can substitute any letters/digits between dots.
For example, consider an Avid Platform service registered with the following realms:
1 | montreal.workgroup1; |
In the above case, you can address the services by supplying the following wildcarded realms in the request:
1 | var m = { |
In contrast, the following wildcarded realms won’t match any instance in the above example:
*
*.*.*.*
montreal.workgroup*.id3
etc...
Using the Avid Connector API to Host Services
You can use the Avid Connector API to host services on the Avid Platform.
Anatomy of a Node.js Platform Service
In its simplest form, a Node.js Avid Platform service is simply an extension of the Service prototype with functions for each operation. The following is a basic example of an Avid Platform service:
1 | var util = require('util'); |
The API Info Object
In the above example, the apiInfo
object defines the external API of the Avid Platform service. This external API consists of the service type, realm, and version info, as well as the set of operations it supports. The operations in apiInfo
can also inline examples that will be available via the ACS Monitor web page.
The bal.Service Super Class
In the above example, the calculator service inherits from bal.Service
. The bal.Service
class is defined by the Node.js Bus Access Layer (BAL) and provides much of the base functionality needed to host the service on the Avid Platform.
Note that the service’s super-constructor is called with four arguments: i) a reference to the service instance, ii) a reference to the access instance, iii) the api info, and iv) the options object.
The onInitialize Function
When you register a service on the Avid Platform, its onInitialize
function is invoked with a single argument: the init_proceed
argument. This allows your service to do any configuration or initialization that is needed before it becomes available for remote invocations. Once initialization is done, the service should call the init_proceed
callback.
If a service does not require initialization, it does not need to implement the onInitialize
function. It is implemented in the example above for demonstration purposes only.
The onStop Function
When a service is stopped by the wrapper, its onStop
function is invoked with a single argument: the stop_proceed
argument. This allows the service to do any resource releasing before completely stopping the service. Once the work associated with stopping is done, it should call the stop_proceed
callback.
NOTE: Don’t exit process in the onStop
implementation. The API’s implementation of this method is subject to revision. Do not depend on it in this manner.
The Operation Implementations
For each operation in the service’s register API (see apiInfo
), there must be a function of the same name. For example, if the apiInfo
lists a multiply
operation, then CalculatorService.prototype.multiply
must be defined.
Each function that supports an Avid Platform service operation must have the following signature: function(m, operationContext)
. In this case, m
is the incoming request message and operationContext
is the object used to send back the reply or errors.
Using the OperationContext object
Service operations all have the signature function(m, operationContext)
and the operationContext provides methods for handling the incoming request. The OperationContext has taken the place of the responder (which has been deprecated) and extended to include additional methods for use when forwarding transaction information to other services while in a service operation. Like the responder, the OperationContext will only accept calls to reply() or error() once. These calls send the response back to the callee and therefore cannot be called again.
1 | MyService.Prototype.example = function(m, operationContext) { |
Registering the Service
NOTE: registerService method arguments are changed. Now 2-nd argument is options and third is callback. Previously second (last) argument was callback. Backward compatibility kept. If two arguments passed, and second one is function the old semantic is used.
Once you define your service, the next step is registering it on the Avid Platform. There are two ways to register on the Avid Platform:
Registering Using access.registerService
The first way to register a service is to construct the service instance yourself and then register it on a connected access
:
1 | var bal = require('proxy-bal'); |
Alternatively you can register a service by passing the service module. This functionality was moved from the load
method which has been deprecated.
1 | var bal = require('proxy-bal'); |
If you wish to register your service this way, then the service must export a two-argument constructor similar to the following:
1 | module.exports = function(access, options) { return new CalculatorService(access, options); } |
Registering Using access.load
NOTE : The load method has been deprecated and will evenutally be removed from the Avid Connector API, please use the functionality provided by registerService
. See above for migration details when using registerService.
Register Service With Custom Options
You may configure following service options for service registration:
- requestServiceConfiguration, whether to request service configuration from Service Manager or not. Default is true;
- startSuspended, whether to start service in suspended mode or not. Default is false. Note, if service developer start service in suspended mode, it’s service developer responsibility to change service state to OK or any other appropriate according to service business logic.
1 | var bal = require('proxy-bal'); |
For information how to subscribe for configuration notifications look Getting Configuration Information from a Service Manager
Unregistering the Service
To unregister a service:
1 | access.unregisterService(function(err) { |
Structured Errors
Declaration of the structured errors in the service contract
A service must declare its complete list of possible error codes in the errorCodes
object of the service contract JSON. Example of the service with errors definition:
1 | var CalculatorService = function(access, options) { |
code
is the name of the object. This parameter is part of the service’s public API and therefore the format of thecode
should be a short sentence in uppercase with an underscore symbol used as a separator, e.g. BAD_REQUEST, BULK_DUPLICATION, MISSING_ARGUMENT, QUOTA_EXCEEDED.status
parameter is the appropriate corresponding HTTP error code.messageTemplate
parameter is text in en_US locale, that may include%{identifier}
placeholders for error message parameters. ThemessageTemplate
(and any parameters) should convey meaningful information e.g. “Quota on %{resourceName} exceeded for %{projectName}.”severity
parameter is the severity level of the error. Available severity levels are: ‘EMERGENCY’, ‘ALERT’, ‘CRITICAL’, ‘ERROR’, ‘WARNING’, ‘NOTICE’, ‘INFO’, ‘DEBUG’.
Composing response message with structured errors
To compose message with structure errors operationContext
must be used as second argument of the service operation implementation. Using above example of error declaration, implementation of two methods, which produce POWER_FAILURE and DIVIDE_BY_ZERO errors may look following:
1 | CalculatorService.prototype.divide = function(m, operationContext) { |
Multi-Zone Services
The default behavior of the Avid Connector API is to register services in the local zone scope. This means that by default services only receive requests from clients within the same zone. If the local zone has been initialized in a multi-zone environment, however, it is possible to register a service in multi-zone scope. This allows the service to be invoked by clients in any connected zone.
To register a service in the multi-zone scope, use the access.multiZone()
object:
1 | var bal = require('proxy-bal'); |
If you wish to use the access.load() method to register your service you must provide the appropriate options to make sure your service is registered as a multizone service.
1 | var bal = require('proxy-bal'); |
Local Zone Scope
Registering a service using the access.localZone()
object is functionally equivalent to registering it using the base access
object. The service is only accessible within the local zone.
Getting Configuration Information from a Service Manager
To intercept configuration provided by a Service Manager, the service must be subscribed to the configured event.
1 | var BusService = function(bus_access, options) { |
To set service configuration in the Service Manager, send the following request with your configuration in the serviceConfiguration
object:
1 | { |
Providing Custom Service Health Information
One of the core operations provided by the Avid Connector API is serviceHealth
. By default if service receives this operation request it replies back with such message in resultSet
:
1 | { |
Service developers may overwrite serviceHealth
operation by providing specific healthStatus
or additional customHealthInfo
. In this case serviceHealth
response may look like:
1 | { |
To overwrite serviceHealth
operation, overwrite onHealthCheck
method in your service and make it taking one callback argument report
:
1 | var HealthStatus = require('proxy-bal').health.HealthStatus; |
Changing Service Status
Sometimes, resources external to a service will have errors or act in an unexpected way. When this happens services do not need to stop while dealing with the external resource. The service can change its status to give insight into what is wrong. It also allows services to stay registered on the platform while the resource is dealt with appropriatly. The connector API supports 5 status states (OK, WARNING, ERROR, SUSPENDED, OFFLINE). Each state has its own behavior which define whether the service is still visible on the platform, and if it is able to recieve messages. See the table below to see the behavior defined by each status.
Status | Visible on Platform | Receives Requests | Example Use Case |
---|---|---|---|
OK | Yes | Yes | Service is fully functional (default state) |
WARNING | Yes | Yes | Service is still fully functioning, but want to warn about some resource (ie. high memory useage, large db latency, many timeouts to another service) |
ERROR | Yes | No | Service is not functioning properly, needs some intervention to fix (ie. ran out of memory, but wish to keep the process alive for debugging) |
SUSPENDED | Yes | No | Service is ok, but cannot function properly due to an external resource (ie. DB connection lost and service cannot proceed without persisting data) |
OFFLINE | No | No | Service process should stay alive, but should not be visible or routed to (ie. Keep service process alive during DB migration) |
Setting the Service Status
1 | var access = require('proxy-bal').createAccess(); |
Providing Compatible Version
Services on the Avid platform provide the concept of ‘Compatible Versions’ to provide a way to remain backwards compatibility with older versions of your service. When you declare that a newer version of your service is compatible with previous versions, it gains the ability to receive messages which were sent to an older version. This way clients who are sending messages to an older version of your service, will get a valid response, even if there are no instances of the old service running. For example, if we declare a new version of our service to be version == 3, but we also declare that it is compatible with versions 2 & 1, then any message which is sent to version 1, 2, or 3 of your service will be routed to version 3 if there is no running instance of your service in the specified version. To declare your service as compatible with other versions we add a comaptibleVersions array to the service info object.
1 | var apiInfo = { |
Using the Avid Connector API for Channels
The Avid Connector API features channels, which are analogous to JMS Topics. When a message is posted to a channel, it is broadcast as a one-way communication to all the subscribers listening to that channel. It is important to note that channel messages are not persisted, and if you post to a channel that has no subscribers, it will not result in an error.
Channels are identified by their name. Subscribers interested in listening on a channel must either receive the channel name from the service that owns the channel, or use a predefined or well-known channel name.
Channel Messages
Like service messages, channel messages are simple JavaScript objects:
1 | { |
Posting to a Channel
The access
object provides a simple method for posting to a channel. There is no support for a callback.
1 | var m = { |
NOTE: Once a channel is registered, anyone who knows the channel name can post to it. Although the poster is most often the creator of the channel, this is not enforced in any way. The security model associated with channel publishing/consuming is subject to revision.
Subscribing to a Channel
Clients can subscribe to channels by channel name and bindings. In the following example, the catch-all #
binding is used, so the onChannelMessage function receives every message posted to the channel. When subscribing to a channel you must pass in a onChannelMessage callback. This callback will be called with one parameter which is an instance of a ChannelContext object. The ChannelContext provides users with the ability to forward the incoming messages’ transaction information to any future callers. This is achieved by calling the ChannelContext.getBusAccess() which will allow users to call any normal access method, with the transaction information wrapped into the outgoing message. If users are calling other services or posting to channels during their onChannelMessage callback it is prefered that they use this contextualized access object for tracking messages throughout the Avid Platform. Callback method can be used to check whether subscribed successfully or not:
1 | const callback = function(err, subscriberId) { |
Clients can also subscribe to shared channels by shared name, channel name and bindings. In this case, when multiple instances are subscribed to the same channel with same shared name, only one instance will receive each message. You can also pass callback method, to check whether subscribed successfully or not.
1 | const callback = function(err, subscriberId) { |
Using Bindings
Bindings can be used to filter which messages are sent to subscribers. The binding string will filter messages based on their dot-separated subject.
The *
wildcard character can be used to match whole words only. For example, the binding status.*
matches the subject status.12345
, but the binding status.123*
does not.
The #
wildcard character can be used to match zero or more entire words. For example, the binding status.#
matches both the subject status.12345
and status.12345.complete
.
The Avid Connector API allows clients to subscribe to the same channel using multiple bindings:
1 | const channel = 'com.avid.upload.notifications'; |
Unsubscribing from a Channel
Clients can unsubscribe from channels, they subscribed earlier by channel name and bindings. In the following example, the catch-all #
binding is used. Callback method can be used to check whether unsubscribed successfully or not:
1 | var callback = function(err) { |
NOTE: This capability is not secured in any way. Anyone who knows the channel name is able to shut it down.
Unsubscribing from a Channel
Clients also have the ability to unsubscribe from specific bindings on a given channel. For example we have a client listening on the channel ‘event.123’ with the bindings ‘start-event’, ‘ping-event’ and ‘done-event’. The client now only wants to know when events are starting but doesn’t need and update on the event, or to know when its done. We can accopmlish this by unsubscribing from those sepcific bindings.
1 | const bindings = ['ping-event', 'done-event']; |
Remote Zone and Multi-Zone Channel Communications
The default behavior of the Avid Connector API is to scope channel communications within the local zone. All the examples given above use this default behavior. If the local zone has been initialized in a multi-zone environment, however, it is possible to communicate using channels across multiple zones.
Interacting with Channel Subscribers in a Specific Remote Zone
To communicate with channel subscribers in a specific remote zone, use the access.zone(String zoneID)
object. The following example sends channel events and messages to subscribers in a specific zone only:
1 | var callback = function(err) { |
In the above case, only multi-zone subscribers in the remote zone with ID 5b2123f1-3f8e-4fcb-9263-f7b98bbdab0c
receive the channel messages. If there are local scope subscribers listening on the same channel in that zone, they do not receive the messages (since they only receive messages sourced from their local zone).
Interacting with Channel Subscribers in All Zones
To communicate with channel subscribers in all connected zones, use the access.multiZone()
object. The following is an example of multi-zone channel communication:
1 | var callback = function(err) { |
In the above case, all multi-zone subscribers across all connected zones receive the channel messages. The local scope subscribers in the poster’s zone also receive the messages. The local scope subscribers in remote zones, however, do not receive the messages.
Subscribing to Multi-Zone Channels
If the local zone has been initialized in a multi-zone environment, channel subscribers can listen using the multi-zone scope. This means that they can receive channel messages from posters in remote zones.
To subscribe to a channel in the multi-zone scope, use the access.multiZone()
object:
1 | var callback = function(err, subscriberId) { |
Local Zone Communications
Note that there are also channel methods in the access.localZone()
object. Invoking channel methods on this object is functionally equivalent to invoking the same methods on the base access
object.
Logging
Although not shown here, the bal.Service
exposes a method meant for use in logging. The Avid Connector API logging system uses the popular Winston library. For specifics on the logging API, please see the Winston docs.
The following is an example of how the divide
operation could be modified to log errors and results:
1 | CalculatorService.prototype.divide = function(m, operationContext) { |
Using another logger
Although the default logger is sufficient for some uses, some service writers may wish to use their own logger in its place.
To do so you must create a proxy object which implements the methods, info/warn/error/debug and trace. The logger in the bal
will only call these methods and therefore you can drop in your own replacement logger in its place. The logger can be replaced
as soon as you import the proxybal into your code.
1 | const MyProxy = { |
Accessing Constants
The Avid Connector API provides constants, which represent core Avid Platform service types. To access these constants:
1 | var constants = require('proxy-bal/lib/constants'); |
Exposing Operations for Upstream REST requests
To declare an operation supporting a REST request, add the corresponding JSON object as part of the service operation definition.
1 | { |
Paths can also have templates that match with a parameter.
1 | { |
The incoming service message will have the id parameter populated with the value passed in the path of the REST request.
You can also have wildcarded paths, that can be used to match some unknown path which will be spcified by the user.
1 | { |
In this case a user could pass the paths
1 | /example/path/my/thing |
And the incoming message will have a parameter path which will be set to the path (from the start of the wildcard) value.
The REST object has the options:
- path - required;
- queryParam - not required;
- bodyParam - not required, default = *;
- method - not required, default GET;
IMPORTANT: Service can not expose multiple operations or/and commands with the same HTTP method on the same endpoint.
1 | { |
Example above is invalid, because operation and command are both exposed using the same path and method. During service registration
Avid Connector API will detect conflicting REST endpoints, if any, it will throw DuplicateRestEndpointsError.
For more detailed information about how REST requests are mapped and delivered to your service,
please view the upstream HTTP docs.
Liveness probe
The Avid Connector API has built in functionality to collect and display liveness status of registered BusAccess instances. As well as display these instances together with registered services.
This functionality is available through the endpoints exposed by internally started HTTP server.
Liveness status functionality is disabled by default and can be enabled with environmental variable. Refer to environmental variables list.
The server instance is Singleton, and is configured and started at the first invocation of BusAccess.connect method.
All other connections will use the exactly the same server instance created during the first connection.
Liveness probe server uses only ConnectionOptions and environmental variables for its configuration.
Default liveness probe implementation
The default implementation of Liveness Probe server is available and works out of the box when liveness probe functionality is enabled via environmental variables.
Default bind address is 0.0.0.0 and port 9991.
Default endpoints server exposes :
- /api/v1/liveness (GET) - returns aggregated health of all registered services and clients
- /api/v1/instances (GET) - returns list of all registered services and clients
- /api/v1/instances/{id}/liveness (GET) - returns health of specific instance
/api/v1/liveness Returns text/plain with Status code 200/500 and text ok/error indicating that aggregated status of all instances is healthy or not correspondingly
/api/v1/instances/{id}/liveness Returns text/plain with Status code 200/500 and text ok/error indicating that BusAccess instance is healthy or not correspondingly
- id - instance id of the BusAccess instance
/api/v1/instances Returns application/json containing description of all registered BusAccess instances and services assigned to them
1 |
|
Custom liveness probe implementation
Custom InstanceLivenessProvider and AggregatedLivenessProvider
The Avid Connector API provides a possibility to re-define AggregatedLivenessProvider and InstanceLivenessProvider, which the server will use to report liveness statuses.
AggregatedLivenessProvider
Synchronous provider.
This provider must return liveness code.
1 | const bal = require('proxy-bal'); |
Asynchronous provider.
This provider must return object Promise. Liveness code must be returned by Promise.resolve.
1 | const bal = require('proxy-bal'); |
InstanceLivenessProvider
Synchronous provider.
This provider must return liveness code.
1 | const bal = require('proxy-bal'); |
Asynchronous provider.
This provider must return object Promise. Liveness code must be returned by Promise.resolve.
1 | const bal = require('proxy-bal'); |
Custom BusAccessWebServer
The Avid Connector API allows to provide your own implementation of HTTP liveness server.
1 | const bal = require('proxy-bal'); |
In this case implementation is entirely up to you, as well as thirdparty libs used for it.
The Avid Connector API though will still wrap your server as Singleton, startServer() on first connect and stopServer() when no active connections left.
It will still call (providing the default implementation for AggregatedLivenessProvider and InstanceLivenessProvider if no custom is available)
- server.registerAggregatedLivenessProvider(AggregatedLivenessProvider aggregatedLivenessProvider) for the first call to not deprecated BusAccess.connect
- server.registerInstance(String instanceId, InstanceLivenessProvider instanceLivenessProvider) for each call to not deprecated BusAccess.connect,
- server.unregisterInstance(String instanceId) for each call to not deprecated BusAccess.disconnect
- server.registerService(String instanceId, String serviceId, ServiceSignature signature) for each call to not deprecated BusAccess.registerService
- server.unregisterService(String instanceId, String serviceId) for each call to not deprecated BusAccess.unregisterService
Use this design doc if you need more information on how to implement server instance.
Error Handling
A service can fail an operation by calling `operationContext.error(…)’. The error function accepts either an object or an array of objects. The error object can have following fields:
code
- (string/required) This should match a code defined in the service declaration.params
- (object/optional) A flat map of values can be used for substituation ofmessageTemplate
Defined in the service declaration.details
- (string/optional) A message indicating the error.
Migration Guides
This migration guide is valid for migrating to Avid Connector API version >= 3.8.
Migration to Asynchronous API
Service operations migration to OperationContext
Your service operation might be declared similarly to the following example:
1 | CalculatorService.prototype.add = function(m, responder) { |
Now, operationContext
took place of responder
. So service operations looks like:
1 | CalculatorService.prototype.add = function(m, operationContext) { |
NOTE: The following rules must be used
- to access incoming messages either
m
argument oroperationContext.getMessage()
can be used - to get instance of
BusAccess
and perform nested calls withBusAccess
useoperationContext.getBusAccess()
- to reply back with result of given type use
context.reply()
- to reply back with error use
error()
- do not use
BusAccess
instance you have created for the nested calls. Always useBusAccess
from context for the nested calls
Channel subscription migration to ChannelMessageHandler
To handle incoming channel messages, instead of two arguments subscriber
1 | var subscriber = function (err, m) { |
NOTE: The following rules must be used
- to access incoming messages use
channelContext.getChannelMessage()
- to get instance of
BusAccess
and perform nested calls withBusAccess
usechannelContext.getBusAccess()
- do not use
BusAccess
instance you have created for the nested calls. Always useBusAccess
from context for the nested calls