SkillAgentSearch skills...

Trooba

Fast isomorphic lightweight framework to build pipelines for request/response, stream/response, request/response and stream/stream use-cases

Install / Use

/learn @trooba/Trooba
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

<p align="center"> <img src="https://github.com/trooba/branding/raw/master/images/trooba_trans_bg.png" alt="Trooba logo" width="332" /><br /><br /> </p>

codecov Build Status NPM Downloads Known Vulnerabilities

"Trooba" [tru:ba'] means "Pipe" in Russian and it is not a pipe.

What is it?

Trooba a fast isomorphic lightweight pipeline framework from eBay. Trooba can build pipelines for request/response, stream/response, request/response and stream/stream use-cases spanning from a browser to a front-end app and further to a backend services.

Try it online to see what it can do for you as well as read about ideas behind it here

It uses a stateless generic pipeline/bus used to route multiple requests in "parallel" without any conflicts. The contextual information is passed along with the message.

Trooba does not dictate specific data structures that should be used for request/response/messages/stream objects. It assumes basic requirements and leaves everything else to the implementor of the transport.

What is it not?

It is not another http based server framework like express, koa or hapi. It can be used to build a pipline for those as it is protocol independent and allows to specify any transport one needs. For example see examples

What can it do for you?

  • Define a pipeline of handlers and execute it
    • The handlers are executed in order they were added.
  • Define a service client:
    • The request object is passed from client through a set of handlers before getting to the transport handler.
    • The response object is passed in the reverse order of handlers from transport handler to the client.
  • Define a service:
    • The request object is passed from transport through a set of handlers before getting to the controller
    • The response object is passed in the reversed order from the controller defined by the user through a set of handlers to the transport of the service.
  • Set transport handler or a set of them in the fallback order (http, soap, grpc, mock or custom) for a pipeline.
  • Inject API that can be returned by pipe.build().create(customApiName) method, mostly useful to provide a protocol specific API, for example, gRPC can expose API defined in proto file as client and service API or soap API defined by wsdl.
  • It supports request/response, pub/sub or a mix of these modes or you can use it as a one-way or bidirectional message bus.
  • You can link different pipelines together in definition or on-the-fly.
  • You can trace the route to troubleshoot any problems or learn some complex pipeline.

pipeline flow

Get Involved

  • Contributing: Pull requests are welcome!
  • Support: Join our gitter chat to ask questions to get support from the maintainers and other Trooba developers

Install

npm install trooba --save

Usage

Client example

Example on how the pipe for http calls can be configured. The middleware used is for demonstration and is not provided out of the box except for the transport and need to be built. You can try simpler working examples mentioned down this page.

require('trooba')
    .use('circuit')
    .use('retry')
    .use('logging')
    .use('tracing')
    .use('security')
    .use('analytics')
    .use('trooba-http-transport', {
        protocol: 'http:',
        hostname: 'www.google.com',
        connectTimeout: 100,
        socketTimeout: 1000
    })
    .build()                    // build the pipe
    .create('client:default')     // create client
    .request({                  // initiate a request
        q: 'nike',
        method: 'GET'
    }, function (err, response) {// get the results
        console.log(err || response.body.toString());
    });

Service example

Example on how one can configure a service endpoint. The middleware used is for demonstration and is not provided out of the box except for the transport and needs to be built. You can try simpler working examples mentioned down this page.

require('trooba')
    .use('trooba-grpc-transport', {
        port: port,
        hostname: 'localhost',
        proto: Grpc.load(require.resolve('./path/to/hello.proto'))
    })
    .use('tracing')
    .use('rate-limiter')
    .use('security')
    .use('analytics')
    .use('router')
    .build()                    // build the pipe
    .create('service:default')     // create service
    .listen();

Building a pipe

var pipe = require('trooba')
    // adding handler to collect metrics
    .use(function (pipe) {
        var start;
        pipe.on('request', function (request, next) {
            start = Date.now();
            next(); // continue with request
        })
        pipe.on('response', function (response, next) {
            console.log('call time is', Date.now() - start, 'ms');
            next(); // continue with reponse flow
        })
    })  
    .use(retry, 2); // retry 2 times, see example of retry handler below

Adding a transport

// setting transport or you can use module reference
pipe.use(function transport(pipe) {
    // hook to request
    pipe.on('request', function (request) {
        // respond
        pipe.respond('Hello ' + request.name);
    })
})

Make a request

Injecting static context if any needed or this can be skipped.

pipe = pipe.build()

At this point the pipe becomes re-usable between multiple "parallel" requests.

Make a request

pipe.create()
    .request({
        name: 'John'
    })
    .on('error', console.error)
    .on('response', console.log);

Or you can do it with a callback style

pipe.create()
    .request({
        name: 'John'
    }, console.log);

Note: Though pipe API to add hooks looks like event emitter, it does not allow multiple hooks and will throw error if one attempts to add a hook for the event that already has it. If you really need to support multiple listeners, you can add an event dispatcher as a hook.

Creating custom pipeline protocols

The request and response hooks used above are just event names and a developer is not limited to them. One can create different protocols using different names. Trooba framework just provides default protocol based on request/response pattern. One can mix custom events in the default pipeline or create completely new one if needed.

Adding custom event

Let's assume we want to update global config for some handlers.

// setting transport or you can use module reference
let config;    

pipe.use(function config(pipe) {
    // hook to config message
    pipe.on('config', function (cfg) {
        config = cfg;
    });
})
Broadcast configuration
pipe.create()
    .send({
        type: 'config',
        flow: Types.REQUEST,
        ref: {
            some: 'config'
        }
    });

Trooba API

  • use(handler[, config]) - adds a handler to the pipeline
    • handler - a function handler(pipe) {} or another pipe to join into this pipe.
    • config is a config object for the handler
  • build([context]) - creates a pipe and returns a generic pipe object.
  • set(name, value) - used set system value to the context. The name is prefixed with '$' that prevents it from being propagated beyond the current pipe context boundaries.
  • get(name) - is used to get system value from the context.

Pipe API

The pipe object is passed to all handlers and transport during initialization whenever new context is created via trooba.build(context) or pipe.create(context) call.

  • create([context], [customApiImpl]) - creates a pipeline with new context or clones from the existing one if any present. The method is mandatory to initiate a new flow, otherwise the subsequent call will fail.
    • context is a context object to be used in request/message flow.
    • customApiImpl is a name for a specific API implementation. It allows to inject custom API provided by one of the handlers that needs to be returned instead of the generic pipe interface.
  • context is an object available to all handlers/transport in the same request/response flow. One can use it to store data that needs to be shared between handlers if needed. The values in the context that have their names started with '$' will not be propagated beyond the pipe boundaries. To access context one can use pipe.context;
  • store is a storage for properties specific to the given pipe point. This is useful to share things between different requests. One can store there objects that needs to be initialized only once.
Trooba.use(function (pipe, config) {
    if (!pipe.store.obj) {
        // do it only once
    
View on GitHub
GitHub Stars41
CategoryDevelopment
Updated6mo ago
Forks11

Languages

JavaScript

Security Score

82/100

Audited on Oct 10, 2025

No findings