npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

glued-store

v0.3.9

Published

Interface for storing objects through HTTP, Pub-Sub or RPC

Downloads

7

Readme

Glue - Store

Interface for storing objects through HTTP, Pub-Sub or RPC.

Build Status JavaScript Style Guide

Usage

This can be used as a standalone library or micro service for storing data (objects) into RethinkDB from any number of sources.

Example: Using Logstash to centralise your logs into a RethinkDB database

To store your logs using Logstash you could configure Logstash it like so:

input {
    file {
        path => "/var/log/**/*.log"
        start_position => beginning
        ignore_older => 0
    }
}

output {
    rabbitmq {
        exchange => 'message_bus'
        exchange_type => 'topic'
        key => 'logstash.log.var.post.store'
        host => '127.0.0.1'
    }
}

Glue entry point

This is also the main entry point for Glue ecosystems. Every service in a way or another listens for object events on the message bus and performs additional operations accordingly. There are services that scan the objects and save the information collected, others that send texts or notifications if the stored object is recognised to be a message, others that logs everything that goes on between the users and the store.

Interfaces

To store objects there are many interfaces available:

  • an HTTP REST API with POST, PUT, PATCH, DELETE and GET methods;

  • a Pub-Sub API topic based over the topics #.post.store, #.put.store, #.patch.store, #.delete.store, #.create.store;

  • an RPC API through the store_rpc queue, accepts create, post, put, patch, delete and get request;

  • a Javascript API for direct and quick access to the underlying methods.

HTTP API

The REST API accepts only application/json content type when posting, putting or patching objects.

Main methods:

  • POST /:objectDomain/:objectType stores an object and sends a message with topic store.{domain}.{type}.{id}.inserted or store.{domain}.{type}.{id}.updated depending if the object is new or if it gets updated. The content of the message is the JSON encoded object. Use this when you don't want to specify the ID of the object or if you want it returned in the response.

  • PUT /:objectDomain/:objectType/:objectId stores an object and sends a message with topic store.{domain}.{type}.{id}.inserted or store.{domain}.{type}.{id}.updated depending if the object is new or if it gets updated. No message is sent if no change is made. The content of the message is the JSON encoded object. Use this if you already know the object ID.

  • PATCH /:objectDomain/:objectType/:objectId patches an object and sends a message with topic store.{domain}.{type}.{id}.updated. No message is sent if no change is made. This endpoint accept a list of actions to be executed on the requested object, for more information see Store.patchObject.

Other methods:

  • GET /:objectDomain/:objectType/:objectId returns the requested object.

  • DELETE /:objectDomain/:objectType/:objectId deletes the specified object and sends a message with topic store.{domain}.{type}.{id}.deleted. The message contains the ID of the deleted object, JSON encoded.

  • PUT /:objectDomain/:objectType prepare for a new domain and/or type and sends a message with topic store.{domain}.{type}.type.created. The message contains a JSON encoded object with two properties, domain and type.

Examples:

$ curl --request PUT \
    --url http://127.0.0.1:9210/glued/benchmark

$ curl --request POST \
    --url http://127.0.0.1:9210/glued/benchmark \
    --header 'content-type: application/json' \
    --data '{"payload":"test payload mesage","counter":123}'

$ curl --request PUT \
    --url http://127.0.0.1:9210/glued/benchmark/f4b9fc30-7f87-4f4a-9987-5389e19cb1a0 \
    --header 'content-type: application/json' \
    --data '{"payload":"test payload mesage","counter":123}'

$ curl --request PATCH \
    --url http://127.0.0.1:9210/glued/benchmark/f4b9fc30-7f87-4f4a-9987-5389e19cb1a0 \
    --header 'content-type: application/json' \
    --data '{"items":[{"action":"update","patch":{"payload":"test payload mesage","counter":234}}]}'

$ curl --request DELETE \
    --url http://127.0.0.1:9210/glued/benchmark/f4b9fc30-7f87-4f4a-9987-5389e19cb1a0 \
    --header 'content-type: application/json'

Pub-Sub API

Main methods:

  • PUBLISH ON *.{domain}.{type}.post.store stores an object and sends a message with topic store.{domain}.{type}.{id}.inserted or store.{domain}.{type}.{id}.updated depending if the object is new or if it gets updated. The content of the message is the JSON encoded object. Use this when you don't want to specify the ID of the object or if you want it returned in the response.

  • PUBLISH ON *.{domain}.{type}.{id}.put.store stores an object and sends a message with topic store.{domain}.{type}.{id}.inserted or store.{domain}.{type}.{id}.updated depending if the object is new or if it gets updated. No message is sent if no change is made. The content of the message is the JSON encoded object. Use this if you already know the object ID.

  • PUBLISH ON *.{domain}.{type}.{id}.patch.store patches an object and sends a message with topic store.{domain}.{type}.{id}.updated. No message is sent if no change is made. This endpoint accept a list of actions to be executed on the requested object, for more information see Store.patchObject.

  • PUBLISH ON *.{domain}.{type}.{id}.delete.store deletes the specified object and sends a message with topic store.{domain}.{type}.{id}.deleted. The message contains the ID of the deleted object, JSON encoded.

To create a domain or type:

  • PUBLISH ON *.{domain}.{type}.create.store prepare for a new domain and/or type and sends a message with topic store.{domain}.{type}.type.created. The message contains a JSON encoded object with two properties, domain and type.

Example:

const MessageBus = require('glued-message-bus').MessageBus,
  mb = new MessageBus('amqp://localhost', 'glued_message_bus');

mb.connectModule(function (err, messageBusChannel) {
  if (err) throw err;

  messageBusChannel.publish('my_package.music.song.post', {
    artist: 'Led Zeppelin',
    title: 'Stariway To Heaven'
  });
  
  messageBusChannel.publish('my_package.music.song.a9d71caa-b946-4d0b-a5fb-3d95a6f0a3f1.put', {
    artist: 'Led Zeppelin',
    title: 'Whole Lotta Love'
  });
  
  messageBusChannel.publish('my_package.music.song.a9d71caa-b946-4d0b-a5fb-3d95a6f0a3f1.delete', {});
});

RPC API

The store listens for RPC calls on the store_rpc queue. Each request must contain:

  • the method, one in:

    • create to create a new type of object;

    • post to store a new object, if the object has an ID it will replace a previous object with the same ID if any;

    • put to store an object with a known ID;

    • patch to patch an existing object, check Store.patchObject for more information;

    • delete to delete an object;

    • get to retrieve an object by ID;

  • the domain of the object;

  • the type of the object;

  • the id of the object, only for put, patch, delete and get requests;

  • the object to be stored, only for post, put and patch requests.

Check the Glue - Message Bus for an easy way of interacting between services through RPC.

JavaScript API

You can initialise the store yourself and use its public interface directly. The available methods are:

  • createType(domain, type, callback), to create a new object type;

  • storeObject(domain, type, document, callback), to store an object. If the object doesn't have an ID it'll get one once stored;

  • patchObject(domain, type, id, patch, callback), to patch an object. See inline documentation for more information;

  • deleteObject(domain, type, id, callback), to delete an object;

  • getObject(domain, type, id, callback), to retrieve an object;

  • diffObjects(a, b), computes the differences between object a and object b;

  • equalObjects(a, b), checks if the two given objects, a and b are equal.

Installation

You can install this library using npm:

$ npm install --save glued-store

To run the services you can install the module with the -g flag and then run the glued-store-http, glued-store-pubsub and glued-store-rpc commands:

$ npm install -g glued-store
$ glued-store-http
$ glued-store-pubsub
$ glued-store-rpc

The HTTP server will run by default on port 9210. Both services will connect to AMQP and RethinkDB on the local machine. To change these options you can use the environment.

To change host and/or port for the HTTP service:

  • GLUED_STORE_PORT: the number of the port to use, default 9210;

  • GLUED_STORE_HOST: the host to bind the server to, default 127.0.0.1.

To change the configuration for AMQP and/or RethinkDB:

  • GLUED_AMQP: the URI of the AMQP server, default to amqp://localhost;

  • GLUED_MESSAGE_BUS: the name of the AMQP exchange, default to glued_message_bus;

  • GLUED_RETHINKDB: the path to a JS/JSON file holding the configuration for RethinkDB, default to an empty configuration {}.

The above are inherited from Glue Common Utilities, check its documentation for more information.

Example:

$ GLUE_STORE_PORT=8080 GLUE_AMQP=amqp://1.2.3.4 \
    RETHINKDB=/path/to/rethinkdb.conf.json glued-store-http
$ GLUE_AMQP=amqp://1.2.3.4 \
    RETHINKDB=/path/to/rethinkdb.conf.json glued-store-pubsub
$ GLUE_AMQP=amqp://1.2.3.4 \
    RETHINKDB=/path/to/rethinkdb.conf.json glued-store-rpc

Test

Run the tests with:

$ npm test

License

This software is distributed under MIT license.