pg-pubsub

repository·main·Indexed 42 days ago

https://github.com/voxpelli/node-pg-pubsub

A Node.js implementation of the Publish/Subscribe pattern built on top of PostgreSQL NOTIFY/LISTEN functionality. Version 0.8.1 requires PostgreSQL 9.4 or higher. It provides the PGPubsub class, which inherits from EventEmitter to manage channel subscriptions, automatic connection retries, and JSON-encoded data publishing.

Tokens
2.4K
Snippets
14
Records
16
Agent score
52%

What's inside pg-pubsub

  1. Configure PGPubsub options

    main

    When instantiating PGPubsub, you can provide an optional options object:

    • log: A Function used for logging. By default, it is silent when NODE_ENV=production. Otherwise, it defaults to console.log(...).
    {
      log: function(msg) { console.log(msg); }
    }
  2. Advanced usage with EventEmitter

    main

    Because PGPubsub is an EventEmitter, you can use standard event methods like .once() or .on() to handle channel notifications.

    const PGPubsub = require('pg-pubsub');
    const pubsubInstance = new PGPubsub('postgres://username@localhost/database');
    
    await pubsubInstance.addChannel('channelName');
    
    // pubsubInstance is a full EventEmitter object that sends events on channel names
    pubsubInstance.once('channelName', channelPayload => {
      // Process the payload
    });
  3. Simple usage example

    main

    This example demonstrates how to subscribe to a channel and publish a message to it.

    const PGPubsub = require('pg-pubsub');
    const pubsubInstance = new PGPubsub('postgres://username@localhost/database');
    
    await pubsubInstance.addChannel('channelName', function (channelPayload) {
      // Process the payload – if it was JSON that JSON has been parsed into an object for you
    });
    
    await pubsubInstance.publish('channelName', { hello: "world" });
  4. Initialize a PGPubsub instance

    main

    Create a new instance of PGPubsub by providing a PostgreSQL connection URI. The instance will prepare itself to connect once the first channel is added and will maintain an open connection to listen for notifications, reconnecting automatically if the connection is lost.

    const PGPubsub = require('pg-pubsub');
    const pubsubInstance = new PGPubsub('postgres://username@localhost/database', options);
  5. Publish data with publish()

    main

    Use publish(channelName, data) to send JSON-encoded data to a specific channel.

    Note: For high-performance applications, it may be better to send the NOTIFY channelName, '...' query yourself using your application's standard Postgres connection pool rather than relying on the single connection maintained by this module.

    Returns a Promise that resolves or rejects based on the success of the Postgres call.

    await pubsubInstance.publish('channelName', { hello: 'world' });
  6. Stop listening with removeChannel()

    main

    Use removeChannel(channelName[, eventListener]) to stop listening on a channel:

    • If an eventListener is provided, it removes that specific listener. If it was the last listener attached to that channel, the module stops listening to the channel in Postgres.
    • If no eventListener is provided, it removes all event listeners and stops listening on the channel.
  7. Listen to a channel with addChannel()

    main

    Use addChannel(channelName[, eventListener]) to start listening for notifications on a specific PostgreSQL channel.

    • channelName: The name of the channel to listen to.
    • eventListener (optional): A callback function that receives the payload. If the payload was JSON-encoded in Postgres, it is automatically parsed into a JavaScript object.

    Returns a Promise that resolves when listening has started. Since PGPubsub inherits from EventEmitter, you can also listen to events using standard Node.js EventEmitter methods.

    await pubsubInstance.addChannel('channelName', function (channelPayload) {
      // Process the payload
    });
  8. Use the PGPubsub class for PostgreSQL PubSub

    main

    The PGPubsub class provides a high-level interface for managing PostgreSQL NOTIFY and LISTEN channels using an EventEmitter pattern. It handles automatic connection retries and manages the lifecycle of database connections and channel subscriptions.

    Initialization

    Initialize the class with either a connection string or a pg ClientConfig object. If no connection string is provided, it defaults to the DATABASE_URL environment variable.

    const PGPubsub = require('pg-pubsub');
    
    // Using a connection string
    const pubsub = new PGPubsub('postgresql://user:pass@localhost:5432/db');
    
    // Using a ClientConfig object
    const pubsub = new PGPubsub({ host: 'localhost', user: 'postgres' }, { retryLimit: 5 });
    const PGPubsub = require('pg-pubsub');
    const pubsub = new PGPubsub('postgresql://user:pass@localhost:5432/db');
  9. Use pgClientRetry for resilient PostgreSQL connections

    main

    The pgClientRetry function provides a mechanism to create a resilient PostgreSQL client connection using promised-retry. It handles connection attempts, retries upon failure, and allows for custom reconnection logic and success callbacks. This is useful for ensuring your application can recover from database connection drops or initial connection failures.

    Configuration Options

    When calling pgClientRetry, you must provide an options object with the following properties:

    • clientOptions: A string (connection string) or an import('pg').ClientConfig object used to instantiate the pg.Client.
    • log (optional): A logging function. Defaults to console.log in non-production environments and a no-op function in production.
    • retryLimit (optional): The maximum number of retry attempts.
    • successCallback (optional): An async function called after a successful connection. It receives the client and should return the client (or a modified version of it).
    • shouldReconnect (optional): A function that returns a boolean indicating whether the client should attempt to reconnect when an error occurs.
    const { pgClientRetry } = require('pg-pubsub/lib/client');
    
    const retry = pgClientRetry({
      clientOptions: 'postgresql://user:password@localhost:5432/mydb',
      retryLimit: 5,
      successCallback: async (client) => {
        console.log('Connected successfully!');
        return client;
      },
      shouldReconnect: () => true
    });
    
    // Usage involves calling retry.try() to initiate the connection process
    // as per the promised-retry API.