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

@graphshieldhq/pubsub

v0.0.5

Published

An opinionated Pub/Sub module.

Downloads

1

Readme

Versioning Twitter Follow

Pub/Sub Module

Abstract

This module provides an easy-to use abstraction to send and receive events with attached payloads, both locally and remotely:

  • Locally (namely from a single container), it can be used as a clean replacement for traditional callback or promises-based mechanisms for long-running operations.
  • Remotely (across containers), it can be used to send messages, such as triggering a long-running operation as an independent job.

Features

When an event is triggered, several behaviors could be activated without any additional code based on its specification:

  • Payload validation: Validate events payloads using a Joi schema
  • Logging: Log the event using our logging module
  • Telemetry: Track the event in telemetry
  • Audit trail: Make the event audit trail accessible to clients
  • Organization webhooks: Make the event accessible to webhook subscriptions by clients
  • System webhook: Relay the event as a webhook for internal use
  • Queuing: Push the event to a queue for remote consumption by a queue consumer
  • Scheduling: Schedule the triggering of an event using a cron tab

How is it used today?

  • Everywhere in the app to log, track and trigger webhooks based on events.
  • The jobs service uses the events specifications to instanciate the required queues consumers that are processing messages asynchronously. See src/services/jobs/jobs.js.
  • The scheduler service uses the events specifications to trigger some events using their defined cron tab. See src/services/scheduler/scheduler.js.

Major dependencies

This module relies on the following modules:

  • events: Standard node.js events emitter, used for "local" communication.
  • bull: Queue package handling distributed jobs and messages in NodeJS, used for "remote" communication. See: https://github.com/OptimalBits/bull

🚀 Get Started

Register events

Before using an event (emitting or listening to), it has to be properly registered and its characteristics and behaviors specified.

Conventions:

  • Events specifications should be exported as default from a module located in the specifications directory.
  • Each module represents a different logical category of events.
  • Events specifications are loaded dynamically and their schema validated at runtime. See events-specifications.js.
  • Events codes MUST be snail_cased.

For more details, the events specification schema is defined as the eventSpecificationSchema constant in events-specifications.js.

Send and receive messages locally

// Import the module
const pubSub = require('@graphshieldhq/pubsub')
// Create a local event listener
pubSub.on('event_code', (payload) => { 
  console.debug(payload)
})
// Emit an event
pubSub.emit('event_code', {status: 'success'})

Send and receive messages remotely

Define the event with the queue property as true:

module.exports = {
  event_code: {
    ...
    queue: true
    ...
  }
}

Create a consumer module in the /src/services/jobs/consumers directory, using your event code as the file name:

// File: 'event_code.js'
// Import the module
const pubSub = require('@graphshieldhq/pubsub')
// Open the queue associated with your event
const queue = pubSub.queues.event_code
// Process messages
queue.process((job, done) => {
  // N.B: `job` is a job object from the `bull` module
  job.progress(1) // Update job progress
  job.log('Start') // Write a log message
  // The event payload is accessible as the job `data` property
  console.log(job.data)
  job.progress(100)
  job.log('Done')
  // Call the `done` callback function to flag the job as done, accepts an error + an optional result
  done(null, {status: 'success'})
})

Validate events payload schema

Optionally, the Pub/Sub module can validate payloads received using a Joi schema:

// Include Joi as a dependency
const Joi = require('joi')
// Use the `payload_schema` property to define a Joi validation schema
module.exports = {
  server_started: {
    name: 'Server instance started',
    description: 'When a server instance has started',
    payload_schema: Joi.object({
      loaded_services_count: Joi.number().min(0).required(),
    }),
    log: true,
    log_level: 'info',
    telemetry: true,
    audit_trail: false,
    organizations_webhook: false,
    system_webhook: false,
    queue: false,
    schedule: false
  }
}

Specify additional job options

By default, when queue is true, this module creates a bull job in the related queue by letting bull automatically generate a job id. You can use a specific job id by passing a correlation_id property to the event payload:

// Emit an event leading to a specific job id
pubSub.emit('event_code', {
  correlation_id: '19ff75f4-3bda-4615-bee2-c47d8b975684',
  status: 'success'
})

You can also specify the job priority by usaing the priority property in the pevent payload:

// Emit an event leading to a specific job priority
pubSub.emit('event_code', {
  job_priority: 5, // By convention, use a value from 1 to 10, 1 being the highest priority
  status: 'success'
})

Emit organization webhook

Organization webhooks are dispatched across clients by using their tenant id. Any payload associated with an event with organizations_webhook as true MUST be comprised of a tenant.id property with a valid tenant UUID or it will be ignored:

// Emit an event that could be relayed as a webhook for clients
pubSub.emit('event_code', {
  tenant: {
    id: 'e5bce8f5-2ba0-4baf-a6e3-7a1891b07763'
  },
  status: 'success'
})

Additional resources