-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature request: Add NodeJS server example that uses Websockets/SSE for SUBSCRIBE #10
Comments
I'd love to know if there is more info available on this. However, just thinking about it... if the websocket API endpoint is used as an example, I don't see how that would be a practical starting-off point for a react app? The websocket API seems to require "full access" authorization, i.e. access to the database that a web app should never have. I'd like to see a little bit more practical usage, perhaps with an intermediating auth layer? |
Updating this issue since another customer came across this and wants to read updates into a frontend over websockets. A good place for a websockets API example would probably be the NodeJS backend example This would allow the backend to handle auth, which is a good point by @canadaduane. To disambiguate, there are two ways to receive updates from Materialize:
Either way the NodeJS webserver gets the data, it can expose these updates over websockets or SSE. |
An alternative to websockets would be Server-Sent Events (SSE). SSE is a one-way push protocol where the server pushes events to the client over a long-lived HTTP connection. It is a little more straightforward and lightweight than websockets. Since Here is a minimal express.js app that achieves this: require('dotenv').config();
const express = require('express');
const app = express();
const { Pool } = require('pg');
// Configure the Postgres client
const pool = new Pool({
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
});
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();
let client;
let loopActive = true;
const handleError = (err) => {
console.error(err);
res.end();
loopActive = false;
};
req.on('close', () => {
res.end();
loopActive = false;
console.log('client closed');
});
(async () => {
try {
client = await pool.connect();
await client.query('BEGIN');
await client.query('DECLARE c CURSOR FOR SUBSCRIBE t ENVELOPE UPSERT (KEY(id))');
while (loopActive) {
const data = await client.query('FETCH ALL c');
data.rows.forEach(function(row) {
// map row fields
row = {
mz_timestamp: Number(row.mz_timestamp),
mz_state: row.mz_state,
id: row.id,
content: row.content
}
// publish server-sent events
res.write(`data: ${JSON.stringify(row)}\n\n`);
});
}
} catch (err) {
handleError(err);
} finally {
if (client) {
console.log('closing pg client');
client.release();
}
}
})();
});
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
}); After pointing a browser at http://localhost:3000/data, updates from the view
|
We have a nice internal example here:
It would be nice if we could simplify this down to a minimal but useful websocket app .
We may want to wait until the websocket API endpoint is considered stable.
The text was updated successfully, but these errors were encountered: