@spfn/core 0.2.0-beta.30 → 0.2.0-beta.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/db/index.d.ts +32 -1
- package/dist/db/index.js +42 -3
- package/dist/db/index.js.map +1 -1
- package/dist/logger/index.d.ts +5 -0
- package/dist/logger/index.js.map +1 -1
- package/package.json +1 -1
package/dist/db/index.d.ts
CHANGED
|
@@ -854,6 +854,10 @@ declare function getSchemaInfo(packageName: string): {
|
|
|
854
854
|
* Uses Record<string, unknown> to accept any schema shape
|
|
855
855
|
*/
|
|
856
856
|
type TransactionDB = PostgresJsDatabase<Record<string, unknown>>;
|
|
857
|
+
/**
|
|
858
|
+
* afterCommit callback type
|
|
859
|
+
*/
|
|
860
|
+
type AfterCommitCallback = () => void | Promise<void>;
|
|
857
861
|
/**
|
|
858
862
|
* Transaction context stored in AsyncLocalStorage
|
|
859
863
|
*/
|
|
@@ -863,6 +867,8 @@ type TransactionContext = {
|
|
|
863
867
|
/** Unique transaction ID for logging and tracing */
|
|
864
868
|
txId: string;
|
|
865
869
|
level: number;
|
|
870
|
+
/** Callbacks to execute after root transaction commits */
|
|
871
|
+
afterCommitCallbacks: AfterCommitCallback[];
|
|
866
872
|
};
|
|
867
873
|
/**
|
|
868
874
|
* Get current transaction from AsyncLocalStorage
|
|
@@ -883,6 +889,31 @@ declare function getTransaction(): TransactionDB | null;
|
|
|
883
889
|
*/
|
|
884
890
|
declare function runWithTransaction<T>(tx: TransactionDB, txId: string, // Add txId parameter
|
|
885
891
|
callback: () => Promise<T>): Promise<T>;
|
|
892
|
+
/**
|
|
893
|
+
* Register a callback to run after the current transaction commits
|
|
894
|
+
*
|
|
895
|
+
* - Inside a transaction: queued and executed after root transaction commits
|
|
896
|
+
* - Outside a transaction: executed immediately (already "committed")
|
|
897
|
+
* - Nested transactions: callbacks bubble up to root transaction
|
|
898
|
+
* - Callbacks run outside transaction context (new connection for DB access)
|
|
899
|
+
* - Errors are logged but never thrown (commit already succeeded)
|
|
900
|
+
*
|
|
901
|
+
* @example
|
|
902
|
+
* ```typescript
|
|
903
|
+
* import { onAfterCommit } from '@spfn/core/db/transaction';
|
|
904
|
+
*
|
|
905
|
+
* async function submit(spaceId: string, chatId: string)
|
|
906
|
+
* {
|
|
907
|
+
* const publication = await publicationRepo.create({...});
|
|
908
|
+
* await requestRepo.updateStatusAtomically(...);
|
|
909
|
+
*
|
|
910
|
+
* onAfterCommit(() => generateArticle(spaceId, chatId, publication.id));
|
|
911
|
+
*
|
|
912
|
+
* return publication;
|
|
913
|
+
* }
|
|
914
|
+
* ```
|
|
915
|
+
*/
|
|
916
|
+
declare function onAfterCommit(callback: AfterCommitCallback): void;
|
|
886
917
|
|
|
887
918
|
/**
|
|
888
919
|
* Transaction middleware options
|
|
@@ -1571,4 +1602,4 @@ declare abstract class BaseRepository<TSchema extends Record<string, unknown> =
|
|
|
1571
1602
|
protected _count<T extends PgTable>(table: T, where?: Record<string, any> | SQL | undefined): Promise<number>;
|
|
1572
1603
|
}
|
|
1573
1604
|
|
|
1574
|
-
export { BaseRepository, type DatabaseClients, type DrizzleConfigOptions, type PoolConfig, RepositoryError, type RetryConfig, type TransactionContext, type TransactionDB, Transactional, type TransactionalOptions, auditFields, checkConnection, closeDatabase, count, create, createDatabaseConnection, createDatabaseFromEnv, createMany, createSchema, deleteMany, deleteOne, detectDialect, enumText, findMany, findOne, foreignKey, fromPostgresError, generateDrizzleConfigFile, getDatabase, getDatabaseInfo, getDrizzleConfig, getSchemaInfo, getTransaction, id, initDatabase, optionalForeignKey, packageNameToSchema, publishingFields, runWithTransaction, setDatabase, softDelete, timestamps, typedJsonb, updateMany, updateOne, upsert, utcTimestamp, uuid, verificationTimestamp };
|
|
1605
|
+
export { type AfterCommitCallback, BaseRepository, type DatabaseClients, type DrizzleConfigOptions, type PoolConfig, RepositoryError, type RetryConfig, type TransactionContext, type TransactionDB, Transactional, type TransactionalOptions, auditFields, checkConnection, closeDatabase, count, create, createDatabaseConnection, createDatabaseFromEnv, createMany, createSchema, deleteMany, deleteOne, detectDialect, enumText, findMany, findOne, foreignKey, fromPostgresError, generateDrizzleConfigFile, getDatabase, getDatabaseInfo, getDrizzleConfig, getSchemaInfo, getTransaction, id, initDatabase, onAfterCommit, optionalForeignKey, packageNameToSchema, publishingFields, runWithTransaction, setDatabase, softDelete, timestamps, typedJsonb, updateMany, updateOne, upsert, utcTimestamp, uuid, verificationTimestamp };
|
package/dist/db/index.js
CHANGED
|
@@ -1207,7 +1207,20 @@ function runWithTransaction(tx, txId, callback) {
|
|
|
1207
1207
|
} else {
|
|
1208
1208
|
txLogger.debug("Root transaction context set", { txId, level: newLevel });
|
|
1209
1209
|
}
|
|
1210
|
-
|
|
1210
|
+
const afterCommitCallbacks = existingContext ? existingContext.afterCommitCallbacks : [];
|
|
1211
|
+
return asyncContext.run({ tx, txId, level: newLevel, afterCommitCallbacks }, callback);
|
|
1212
|
+
}
|
|
1213
|
+
function onAfterCommit(callback) {
|
|
1214
|
+
const context = getTransactionContext();
|
|
1215
|
+
if (!context) {
|
|
1216
|
+
Promise.resolve().then(callback).catch((err) => {
|
|
1217
|
+
txLogger.error("afterCommit callback failed (no transaction)", {
|
|
1218
|
+
error: err instanceof Error ? err.message : String(err)
|
|
1219
|
+
});
|
|
1220
|
+
});
|
|
1221
|
+
return;
|
|
1222
|
+
}
|
|
1223
|
+
context.afterCommitCallbacks.push(callback);
|
|
1211
1224
|
}
|
|
1212
1225
|
var MAX_TIMEOUT_MS = 2147483647;
|
|
1213
1226
|
var txLogger2 = logger.child("@spfn/core:transaction");
|
|
@@ -1290,13 +1303,21 @@ async function runInTransaction(callback, options = {}) {
|
|
|
1290
1303
|
txLogger2.debug("Transaction started", { txId, context });
|
|
1291
1304
|
}
|
|
1292
1305
|
const startTime = Date.now();
|
|
1306
|
+
let afterCommitCallbacks = [];
|
|
1293
1307
|
try {
|
|
1294
1308
|
const result = await writeDb.transaction(async (tx) => {
|
|
1295
1309
|
if (timeout > 0 && !isNested) {
|
|
1296
1310
|
await tx.execute(sql.raw(`SET LOCAL statement_timeout = ${timeout}`));
|
|
1297
1311
|
}
|
|
1298
1312
|
return await runWithTransaction(tx, txId, async () => {
|
|
1299
|
-
|
|
1313
|
+
const innerResult = await callback(tx);
|
|
1314
|
+
if (!isNested) {
|
|
1315
|
+
const ctx = getTransactionContext();
|
|
1316
|
+
if (ctx) {
|
|
1317
|
+
afterCommitCallbacks = [...ctx.afterCommitCallbacks];
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
return innerResult;
|
|
1300
1321
|
});
|
|
1301
1322
|
});
|
|
1302
1323
|
const duration = Date.now() - startTime;
|
|
@@ -1316,6 +1337,24 @@ async function runInTransaction(callback, options = {}) {
|
|
|
1316
1337
|
});
|
|
1317
1338
|
}
|
|
1318
1339
|
}
|
|
1340
|
+
if (!isNested && afterCommitCallbacks.length > 0) {
|
|
1341
|
+
if (enableLogging) {
|
|
1342
|
+
txLogger2.debug("Executing afterCommit callbacks", {
|
|
1343
|
+
txId,
|
|
1344
|
+
context,
|
|
1345
|
+
count: afterCommitCallbacks.length
|
|
1346
|
+
});
|
|
1347
|
+
}
|
|
1348
|
+
for (const cb of afterCommitCallbacks) {
|
|
1349
|
+
Promise.resolve().then(cb).catch((err) => {
|
|
1350
|
+
txLogger2.error("afterCommit callback failed", {
|
|
1351
|
+
txId,
|
|
1352
|
+
context,
|
|
1353
|
+
error: err instanceof Error ? err.message : String(err)
|
|
1354
|
+
});
|
|
1355
|
+
});
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1319
1358
|
return result;
|
|
1320
1359
|
} catch (error) {
|
|
1321
1360
|
const duration = Date.now() - startTime;
|
|
@@ -1861,6 +1900,6 @@ var BaseRepository = class {
|
|
|
1861
1900
|
}
|
|
1862
1901
|
};
|
|
1863
1902
|
|
|
1864
|
-
export { BaseRepository, RepositoryError, Transactional, auditFields, checkConnection, closeDatabase, count, create, createDatabaseConnection, createDatabaseFromEnv, createMany, createSchema, deleteMany, deleteOne, detectDialect, enumText, findMany, findOne, foreignKey, fromPostgresError, generateDrizzleConfigFile, getDatabase, getDatabaseInfo, getDrizzleConfig, getSchemaInfo, getTransaction, id, initDatabase, optionalForeignKey, packageNameToSchema, publishingFields, runWithTransaction, setDatabase, softDelete, timestamps, typedJsonb, updateMany, updateOne, upsert, utcTimestamp, uuid, verificationTimestamp };
|
|
1903
|
+
export { BaseRepository, RepositoryError, Transactional, auditFields, checkConnection, closeDatabase, count, create, createDatabaseConnection, createDatabaseFromEnv, createMany, createSchema, deleteMany, deleteOne, detectDialect, enumText, findMany, findOne, foreignKey, fromPostgresError, generateDrizzleConfigFile, getDatabase, getDatabaseInfo, getDrizzleConfig, getSchemaInfo, getTransaction, id, initDatabase, onAfterCommit, optionalForeignKey, packageNameToSchema, publishingFields, runWithTransaction, setDatabase, softDelete, timestamps, typedJsonb, updateMany, updateOne, upsert, utcTimestamp, uuid, verificationTimestamp };
|
|
1865
1904
|
//# sourceMappingURL=index.js.map
|
|
1866
1905
|
//# sourceMappingURL=index.js.map
|