Add nonblocking/asyn I/O operations

This commit is contained in:
KS Jannette
2026-08-01 01:06:19 -04:00
parent 90035b3568
commit ee6fa9e576
16 changed files with 711 additions and 137 deletions

View File

@@ -1,12 +1,49 @@
import { query } from './index.js';
import QueryStream from 'pg-query-stream';
import { pipeline } from 'node:stream/promises';
import { Readable } from 'node:stream';
import { query, getPool } from './index.js';
import { batch } from '../lib/streams.js';
const SELECT_NOTES = 'SELECT id, text, x, y, author, color FROM notes ORDER BY id';
// Postgres caps a statement at 65535 bind parameters; six columns per note
// leaves 10922 as the hard ceiling, so stay well under it.
const INSERT_BATCH_SIZE = 1000;
export const getAllNotes = async () => {
const { rows } = await query(
'SELECT id, text, x, y, author, color FROM notes ORDER BY id'
);
const { rows } = await query(SELECT_NOTES);
return rows;
};
/**
* Streams every note as an object-mode Readable. The pooled client is checked
* out for the life of the stream and released once it ends, errors, or is
* destroyed early by a consumer.
*
* @returns {Promise<import('node:stream').Readable>}
*/
export const streamAllNotes = async () => {
const client = await getPool().connect();
let released = false;
const release = () => {
if (released) return;
released = true;
client.release();
};
try {
const rows = client.query(new QueryStream(SELECT_NOTES));
rows.once('end', release);
rows.once('error', release);
rows.once('close', release);
return rows;
} catch (err) {
release();
throw err;
}
};
export const getNoteById = async (id) => {
const { rows } = await query(
'SELECT id, text, x, y, author, color FROM notes WHERE id = $1',
@@ -25,7 +62,7 @@ export const createNote = async (note) => {
return rows[0];
};
export const createNotes = async (notes) => {
const insertNoteBatch = async (notes) => {
const values = [];
const placeholders = [];
@@ -52,3 +89,23 @@ export const createNotes = async (notes) => {
);
return rows;
};
export const createNotes = async (notes) => {
if (!notes || notes.length === 0) {
return [];
}
const inserted = [];
await pipeline(
Readable.from(notes, { objectMode: true }),
batch(INSERT_BATCH_SIZE),
async (batches) => {
for await (const chunk of batches) {
inserted.push(...await insertNoteBatch(chunk));
}
}
);
return inserted;
};