You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I have two suggestions for the NodeJS subscribe example:
Our current example could be made much simpler with the use of the new SUBSCRIBE ... ENVELOPE UPSERT ...
Our current example doesn't show how to gracefully shut down subscribes
I included a minimal express js app where multiple users can subscribe to data by hitting http://localhost:3000/data. The subscribes are closed when the client closes, and the whole thing shuts down gracefully when the server is closed.
Some ideas for further refinement of this express app:
add a parameter to the endpoint so the user can choose which view to subscribe to
add a Redis cache so each view is subscribed to only once, and expose the server sent events over Redis pubsub channels
require('dotenv').config();constexpress=require('express');constapp=express();const{ Pool }=require('pg');// Configure the Postgres clientconstpool=newPool({user: process.env.MZ_USER,host: process.env.MZ_HOST,database: process.env.MZ_DB,password: process.env.MZ_PASSWORD,port: process.env.MZ_PORT,ssl: true});// global set of active subscription loopsletactiveLoops=newSet();app.get('/data',(req,res)=>{res.setHeader('Content-Type','text/event-stream');res.setHeader('Cache-Control','no-cache');res.setHeader('Connection','keep-alive');res.flushHeaders();letclient;// on request, activate a subscription loop and add it to the set of active loopsletloopControl={active: true};activeLoops.add(loopControl);(async()=>{try{client=awaitpool.connect();awaitclient.query('BEGIN');awaitclient.query('DECLARE c CURSOR FOR SUBSCRIBE t WITH (PROGRESS) ENVELOPE UPSERT (KEY(id))');// Fetch rows while the loop is switched on.// We need FETCH ALL for minimal latency, but that means this loop will not exit until the next datum comes through.// Hence why we needed WITH (PROGRESS). This ensures data will be received and the loop with be able to exit.while(loopControl.active){constdata=awaitclient.query("FETCH ALL c");data.rows.forEach(function(row){// filter out progress messagesif(!row.mz_progressed){// map row fieldsrow={mz_progressed: row.mz_progressed,mz_timestamp: Number(row.mz_timestamp),mz_state: row.mz_state,id: row.id,content: row.content}// publish server-sent eventsres.write(`data: ${JSON.stringify(row)}\n\n`);}});}}catch(err){handleError(err);}finally{if(client){res.end()console.log('closing pg client');awaitclient.query('COMMIT')console.log('committed transaction');awaitclient.release();}}})();consthandleError=(err)=>{console.error(err);res.end();loopControl.active=false;activeLoops.delete(loopControl);};req.on('close',()=>{res.end();loopControl.active=false;activeLoops.delete(loopControl);console.log('client closed');});});server=app.listen(3000,function(){console.log('Example app listening on port 3000!');});asyncfunctiongracefulShutdown(){console.log('Initiating graceful shutdown');// Stop all active subscriptionsactiveLoops.forEach(loop=>{loop.active=false;});try{// Using a promise to handle server.close since it doesn't natively return oneawaitnewPromise((resolve)=>{server.close(resolve);});console.log('Express server closed.');// End the database poolawaitpool.end();console.log('Database pool closed.');process.exit(0);}catch(err){console.error('Error during graceful shutdown:',err);process.exit(1);}}// Listen for specific signals to initiate graceful shutdownprocess.on('SIGINT',gracefulShutdown);process.on('SIGTERM',gracefulShutdown);
The text was updated successfully, but these errors were encountered:
Hey team,
I have two suggestions for the NodeJS subscribe example:
SUBSCRIBE ... ENVELOPE UPSERT ...
I included a minimal express js app where multiple users can subscribe to data by hitting
http://localhost:3000/data
. The subscribes are closed when the client closes, and the whole thing shuts down gracefully when the server is closed.Some ideas for further refinement of this express app:
The text was updated successfully, but these errors were encountered: