@fuzzy-ai/microservice-client

Simple microservice client class used by Fuzzy.ai

Usage no npm install needed!

<script type="module">
  import fuzzyAiMicroserviceClient from 'https://cdn.skypack.dev/@fuzzy-ai/microservice-client';
</script>

README

fuzzy.ai-microservice-client

This is a useful client library for interacting with certain kinds of microservices.

In particular, it works well for RESTful services that use JSON for request and response payloads, and RFC 6750 Bearer Tokens for authorization.

License

Copyright 2016,2018 Fuzzy.ai

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

MicroserviceClient

The main class is MicroserviceClient, which is also the export from the module. You can use it directly to access microservices.

  var util = require('util');
  var MicroserviceClient = require('fuzzy.ai-microservice-client');

  var options = {
    root: "http://service.example",
    key: "A1B2C3D4E5F6G7",
    queueLength: 32,
    maxWait: 10
  };

  var client = new MicroserviceClient(options);

  client.get("/widget", function(err, widgets) {
      if (err) {
        console.error(err);
      } else {
        console.dir(widgets);
      }
  });

You can also use it to inherit for your own client classes.

  var util = require('util');
  var MicroserviceClient = require('fuzzy.ai-microservice-client');

  var MyServiceClient = function(options) {
    MicroserviceClient.call(this, options);
  };

  util.inherits(MyServiceClient, MicroserviceClient);

  MyServiceClient.prototype.getAllWidgets = function(callback) {
    this.get("/widget", callback);
  };

Constructor

The constructor takes an options object as the only parameter. options can have the following properties.

  • root: The root of the microservice's URLs. Usually something like 'https://hostname' or 'http://hostname:port' or 'http://hostname'. Required.
  • key: The API key for the microservice. This is used to identify your client and authorize it for whatever stuff it can do on the microservice.
  • queueLength: The client will queue up requests to the microservice to avoid flooding it with requests. This parameter defines how many requests can go into the queue concurrently. Default is 16.
  • maxWait: If there are errors that look sporadic or related to the server, the client will retry the requests. (See "Retries" below.) This parameter defines how many seconds you're willing to wait on retries. Default is Infinity; the client will retry forever otherwise.
  • cacheSize: Size of the cache to use. We use an LRU caching library, so if there are more GETs than fit in the cache, the oldest ones get kicked. Must be a number greater than 0; default is 100.
  • timeout: For persistent connections, this is how long in ms to keep the connections open before closing them. Defaults to 1000 (1 second). If it's Infinity, connections never time out. If it's 0, don't use persistent connections.
  • webClient A WebClient instance to use, instead of having the MicroserviceClient create its own. This is useful if you want to share persistent connections and so on.

Methods

  • get(relative, callback) GET the resource at relative. callback takes two parameters: an error and the parsed results.
  • post(relative, reqBody, callback) POST the reqBody to relative. callback takes two parameters: an error and the parsed results.
  • put(relative, reqBody, callback) PUT the reqBody to relative which should replace the contents of that resource. callback takes two parameters: an error and the parsed results.
  • patch(relative, reqBody, callback) PATCH the reqBody to relative which should be added the contents of that resource. callback takes two parameters: an error and the parsed results.
  • delete(relative, callback) DELETE the resource at relative. callback takes two parameters: an error and the parsed results.
  • stop(callback) Close all persistent connections. Needed at shutdown if you have persistent connections on (otherwise your program won't stop).

Events

The client is an (EventEmitter)[https://nodejs.org/api/events.html] so you can use all the regular event-monitoring methods you expect. It emits the following events:

  • error When there is an error with a request. Sometimes these errors are passed back to callback functions; other times the system retries. This event is mostly useful for logging and debugging.

  • cache-hit When there is a GET request for an URL that is already in the cache. Arguments are url, cacheItem, where cacheItem is a CacheItem instance as described below. Note that cache hits are not always returned directly; only if their expires property is in the future.

  • cache-miss When there is a GET request and the URL is not in the cache. Argument is url.

  • cache-results When there is a cache item that has a far-enough future expires property to return it directly. Arguments are url and cacheItem.

  • cache-unmodified When an URL is in the cache, but the expires is not sufficiently in the future that we can count on it, we continue the request. If the request comes back with the 304 Unmodified status, the cache results are returned, and this event is fired. Arguments are url and cacheItem.

  • cache-modified If the request comes back succesfully but with a different status than 304 Unmodified. Arguments are url and cacheItem.

The CacheItem class has the following properties.

  • url: The URL that was requested.
  • body: body of the response, as a string.
  • lastModified: Last-Modified date, in Date number format.
  • expires: Expires date, in Date number format.
  • etag: ETag for the response.

Queue

The client tries not to flood a microservice with too many concurrent requests, by putting them into a queue. If you increase the queue length, it should give you faster responses, with corresponding higher load on the microservice.

Retries

If there are errors that seem to be recoverable, the client will retry the request after waiting a variable amount of time. It uses a truncated exponential backoff algorithm to avoid congestion.

If you need to have results in a fixed amount of time (for example, for interactive code), set the maxWait for the client. Note that the maxWait parameter works for all the methods.

Cache

Results of GET requests are saved in an LRU (least-recently-used) cache within the client. There are several events (see above) for getting finer information on the cache performance.

To benefit from caching, there are a few things worth doing:

  • Add a Last-Modified header for resources where you know when they were last modified.
  • Add an Expires header for resources where you know when they will expire.
  • For resources that are immutable (never change) set the Expires header to the far future, e.g. 10 years from last modification.

Persistent connections

The class will use persistent connections if you set the timeout option to something non-zero (it's 1000 by default, so persistent connections are on by default). To clean up any persistent connections before exiting, run the stop() method.