small-typeorm-persist-thread
v0.1.1
Published
Explicit persistence thread for TypeORM with dedicated QueryRunner, batching, transaction control and optional parallel flush.
Maintainers
Readme
small-typeorm-persist-thread
Explicit persistence thread for TypeORM with:
- dedicated
QueryRunner - explicit transaction control
- queued operations
- grouped
save/remove/softRemove - high-performance
insert/update/upsert/delete - optional parallel flush outside transactions
- operation merging for compatible explicit operations
Install
npm install small-typeorm-persist-threadtypeorm must already be installed in your project.
Why
TypeORM already provides QueryRunner, transactions, and persistence APIs.
This package adds an explicit persistence thread abstraction that:
- keeps one database connection open during a unit of work
- accumulates operations
- flushes them in a controlled way
- favors explicit intent over unreliable entity-state detection
Quick example
import { createPersistenceThread } from "typeorm-persist-thread";
const thread = await createPersistenceThread(dataSource);
try {
await thread.startTransaction();
thread.insert(User, [
{ email: "[email protected]", name: "A" },
{ email: "[email protected]", name: "B" }
]);
thread.update(User, { active: false }, { active: true });
thread.upsert(
User,
[{ externalId: "42", name: "Updated" }],
["externalId"]
);
await thread.flush();
await thread.commit();
} catch (error) {
await thread.rollback();
throw error;
} finally {
await thread.close();
}Parallel flush
await thread.flush({ singleConnection: false });Rules:
- default is
singleConnection: true - if a transaction is active, flush is always forced to single connection
- parallel mode is best-effort and should be used only for independent operations
- parallel mode is not globally atomic
Best-effort entity mode
thread.persist(userEntity);
thread.remove(oldSessionEntity);
thread.softRemove(oldTokenEntity);
await thread.flush();This mode is convenient but less explicit than insert/update/upsert/delete.
Optimization
The thread merges compatible explicit operations before execution:
- multiple
insert(Entity, rows)become one merged insert per target - multiple
upsert(Entity, rows, conflictPaths, options)become one merged upsert when target and conflict config match - multiple
update(Entity, criteria, partial)may become one merged update when:- target is the same
- partial is the same
- criteria are simple flat objects with the same shape
- multiple
delete(Entity, criteria)may become one merged delete when:- target is the same
- criteria are simple flat objects with the same shape
Example:
thread.insert(User, { email: "[email protected]" });
thread.insert(User, { email: "[email protected]" });
thread.insert(User, { email: "[email protected]" });
await thread.flush();This becomes one merged insert call.
Caveat for merged update/delete
Merged update/delete only apply to simple criteria objects such as:
{ id: 1 }
{ email: "[email protected]" }
{ shopId: 10, active: false }Complex operators, arrays, nested objects or custom expressions are kept as individual operations.
API
Lifecycle
startTransaction()flush(options?)commit()rollback()close()
Explicit operations
insert(Entity, rows)update(Entity, criteria, partial)upsert(Entity, rows, conflictPaths, options?)delete(Entity, criteria)
Best-effort entity operations
persist(entity)remove(entity)softRemove(entity)
Notes
close()must always be called.commit()flushes before committing.rollback()clears queued operations and rolls back the current SQL transaction if active.upsert()support depends on your TypeORM driver.flush({ singleConnection: false })may execute groups in parallel on multiple connections.
License
MIT
