简体   繁体   中英

How to use a connection elsewhere in NodeJS Express app

I have search everywhere and i cant find a good solution to my problem (witch i think is more..generic..i want to learn how and why). Im using google pubsub and i have a service in my project. It has two functions. I have require the file in app.js and listen. But how can i listen elsewhere in the app? Like say in a controller? Here is the messageService.ts code:

require('dotenv').config();
const {PubSub} = require('@google-cloud/pubsub');

let messageCount = 0;

let projectId = 'xxx';
let topicName = 'xxxt';
let subscriptionName = 'xxx';

// Instantiates a client
const pubsub = new PubSub({projectId});

// Creates a new topic
const topic = pubsub.topic(topicName);

const subscription = topic.subscription(subscriptionName);
module.exports = {
    listenForMessages : () => {
        const messageHandler = message => {
            console.log(`Received message ${message.id}:`);
            console.log(`\tAgresso Data: ${message.data}`);
            //console.log(`\tAttributes: ${message.attributes}`);
            messageCount += 1;
            message.ack();
        };
        
        subscription.on('message', messageHandler);
    },
    sendTestMessage : () => {
        let messageObject = {
            action: 'insert',
            objectType: 'resource',
            objectId: 12456,
            stamp: Date.now()
        }
    
        topic.publish(Buffer.from(JSON.stringify(messageObject)));
        console.log('sent test message') ;
    }

}

Your subscription constant isn't bound to be used only in this file.

I suggest you to have a different approach/architecture. One where you have a file named PubSubConnection.ts where you do your whole PubSub/topic/subscription instantiation and share it across your whole project. This way you won't have to re-create a new topic each time you want to use it. Maybe even factorized as you can you sub to any topic.

Example:

app.ts

import dotenv from 'dotenv';
dotenv.config();
import { PubSub } from '@google-cloud/pubsub';
import express from 'express';
import PubSubConnection from "./PubSubConnection";
import { sendTestMessage } from './listenSub';

const app = express();

// DI (dependency injection)
// Create a one time pubsub as you will certainly only use the same project_id across your app
const pubSub = new PubSub({ projectId: process.env.PROJECT_ID });
// Create the connection to the topic/subscription dynamically here or anywhere else
// in your di where your service/component need an access to a special topic/subscription
const pubSubConnection = new PubSubConnection(pubSub, 'your_topic_name', 'your_sub_name');

// this members could be passed to any services that your app runs
const topic = pubSubConnection.getTopic;
const subscription = pubSubConnection.getSubscription;

// And use as many function anywhere you need it 
// by just passing it the already created topic/subscription
sendTestMessage(topic);

app.listen(process.env.PORT, () => {
    console.log('Server started');
});

PubSubConnection.ts

// Dotenv should always be loaded first in your application (aka app.js in your case) and in the 1st line
// because it only need to be loaded 1 time for the env variable to be accessible
// there is no neeed to load it everywhere you need to access env var
// require('dotenv').config();

import { PubSub, Subscription, Topic } from '@google-cloud/pubsub';

export default class TopicSubConnection {
    topic: Topic
    subscription: Subscription

    constructor(
        private readonly pubSub: PubSub, 
        private readonly topicName: string, 
        private readonly subscriptionName: string
    ) {
        this.topic = new Topic(this.pubSub, this.topicName);
        this.subscription = new Subscription(this.pubSub, this.subscriptionName);
    }
  
    public get getTopic(): Topic {
        return this.topic;
    }
  
    public get getSubscription(): Subscription {
        return this.subscription;
    }
}

subOperations.ts

import { Subscription, Topic, Message } from "@google-cloud/pubsub";

let messageCount = 0;

export const listenForMessages = (subscription: Subscription): void => {
    const messageHandler = (message: Message) => {
        console.log(`Received message ${message.id}:`);
        console.log(`\tAgresso Data: ${message.data}`);
        //console.log(`\tAttributes: ${message.attributes}`);
        messageCount += 1;
        message.ack();
    };
    
    // the handler could be an array of functions, this means you could have different
    // functions listening to the same subscription
    subscription.on('message', messageHandler);
};

export const sendTestMessage = (topic: Topic): void => {
    let messageObject = {
        action: 'insert',
        objectType: 'resource',
        objectId: 12456,
        stamp: Date.now()
    }

    topic.publish(Buffer.from(JSON.stringify(messageObject)));
    console.log('sent test message') 
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM