65 lines
1.8 KiB
JavaScript
65 lines
1.8 KiB
JavaScript
// Per-async-flow context for the mutation wraps.
|
|
//
|
|
// AsyncLocalStorage gives every wrap a stack of in-flight op_ids so that ops
|
|
// triggered while another op is running (e.g. cascading field deletes inside
|
|
// a table delete) can attach themselves to the outer op as parent_op_id, and
|
|
// share its correlation_id.
|
|
|
|
const { AsyncLocalStorage } = require("async_hooks");
|
|
|
|
const { randomUuid } = require("./ids");
|
|
|
|
|
|
const storage = new AsyncLocalStorage();
|
|
|
|
|
|
const enterOp = async (opId, fn) => {
|
|
const current = storage.getStore();
|
|
const correlationId = current ? current.correlationId : randomUuid();
|
|
const parentStack = current ? current.stack : [];
|
|
const newStore = {
|
|
stack: [...parentStack, opId],
|
|
correlationId: correlationId
|
|
};
|
|
return await storage.run(newStore, fn);
|
|
};
|
|
|
|
|
|
const currentParentOpId = () => {
|
|
const store = storage.getStore();
|
|
if (!store || store.stack.length < 2) {
|
|
return null;
|
|
}
|
|
return store.stack[store.stack.length - 2];
|
|
};
|
|
|
|
|
|
const currentCorrelationId = () => {
|
|
const store = storage.getStore();
|
|
return store ? store.correlationId : null;
|
|
};
|
|
|
|
|
|
// Suppression mode: when applying ingested ops we run the underlying Saltcorn
|
|
// model methods but want the CRUD wraps to pass through silently — no journal
|
|
// writes, no entity_id assignment. The apply handler manages those side effects
|
|
// itself with the source-env's UUID.
|
|
const runSuppressed = async (fn) => {
|
|
const current = storage.getStore() || { stack: [], correlationId: null };
|
|
return await storage.run({ ...current, suppressed: true }, fn);
|
|
};
|
|
|
|
|
|
const isSuppressed = () => {
|
|
const s = storage.getStore();
|
|
return !!(s && s.suppressed);
|
|
};
|
|
|
|
|
|
module.exports = {
|
|
enterOp,
|
|
currentParentOpId,
|
|
currentCorrelationId,
|
|
runSuppressed,
|
|
isSuppressed
|
|
};
|