Cleanup
This commit is contained in:
@@ -7,105 +7,104 @@ 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.
|
||||
// leaves 10922 as the hard ceiling.
|
||||
const INSERT_BATCH_SIZE = 1000;
|
||||
|
||||
export const getAllNotes = async () => {
|
||||
const { rows } = await query(SELECT_NOTES);
|
||||
return rows;
|
||||
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.
|
||||
* Streams every note as an object-mode Readable. The pooled client is released on end, error, or
|
||||
* destruction by consumer.
|
||||
*
|
||||
* @returns {Promise<import('node:stream').Readable>}
|
||||
*/
|
||||
export const streamAllNotes = async () => {
|
||||
const client = await getPool().connect();
|
||||
const client = await getPool().connect();
|
||||
|
||||
let released = false;
|
||||
const release = () => {
|
||||
if (released) return;
|
||||
released = true;
|
||||
client.release();
|
||||
};
|
||||
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;
|
||||
}
|
||||
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',
|
||||
[id]
|
||||
);
|
||||
return rows[0] || null;
|
||||
const { rows } = await query(
|
||||
'SELECT id, text, x, y, author, color FROM notes WHERE id = $1',
|
||||
[id]
|
||||
);
|
||||
return rows[0] || null;
|
||||
};
|
||||
|
||||
export const createNote = async (note) => {
|
||||
const { rows } = await query(
|
||||
`INSERT INTO notes (id, text, x, y, author, color)
|
||||
const { rows } = await query(
|
||||
`INSERT INTO notes (id, text, x, y, author, color)
|
||||
VALUES ($1, $2, $3, $4, $5, $6)
|
||||
RETURNING id, text, x, y, author, color`,
|
||||
[note.id, note.text, note.x ?? 0, note.y ?? 0, note.author, note.color ?? 'yellow']
|
||||
);
|
||||
return rows[0];
|
||||
[note.id, note.text, note.x ?? 0, note.y ?? 0, note.author, note.color ?? 'yellow']
|
||||
);
|
||||
return rows[0];
|
||||
};
|
||||
|
||||
const insertNoteBatch = async (notes) => {
|
||||
const values = [];
|
||||
const placeholders = [];
|
||||
const values = [];
|
||||
const placeholders = [];
|
||||
|
||||
notes.forEach((note, i) => {
|
||||
const offset = i * 6;
|
||||
placeholders.push(
|
||||
`($${offset + 1}, $${offset + 2}, $${offset + 3}, $${offset + 4}, $${offset + 5}, $${offset + 6})`
|
||||
);
|
||||
values.push(
|
||||
note.id,
|
||||
note.text,
|
||||
note.x ?? 0,
|
||||
note.y ?? 0,
|
||||
note.author,
|
||||
note.color ?? 'yellow'
|
||||
);
|
||||
});
|
||||
notes.forEach((note, i) => {
|
||||
const offset = i * 6;
|
||||
placeholders.push(
|
||||
`($${offset + 1}, $${offset + 2}, $${offset + 3}, $${offset + 4}, $${offset + 5}, $${offset + 6})`
|
||||
);
|
||||
values.push(
|
||||
note.id,
|
||||
note.text,
|
||||
note.x ?? 0,
|
||||
note.y ?? 0,
|
||||
note.author,
|
||||
note.color ?? 'yellow'
|
||||
);
|
||||
});
|
||||
|
||||
const { rows } = await query(
|
||||
`INSERT INTO notes (id, text, x, y, author, color)
|
||||
const { rows } = await query(
|
||||
`INSERT INTO notes (id, text, x, y, author, color)
|
||||
VALUES ${placeholders.join(', ')}
|
||||
RETURNING id, text, x, y, author, color`,
|
||||
values
|
||||
);
|
||||
return rows;
|
||||
values
|
||||
);
|
||||
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));
|
||||
}
|
||||
if (!notes || notes.length === 0) {
|
||||
return [];
|
||||
}
|
||||
);
|
||||
|
||||
return inserted;
|
||||
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;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user