@kikko-land/kikko
Advanced tools
Comparing version 0.10.0 to 0.11.0
# @kikko-land/core | ||
## 0.11.0 | ||
### Minor Changes | ||
- de4fd98: Increase job timeout time | ||
- d6204b9: Add preparedQueries support | ||
## 0.10.0 | ||
@@ -4,0 +11,0 @@ |
import { deepEqual as z } from "fast-equals"; | ||
import { sql as p } from "@kikko-land/boono-sql"; | ||
import { sql as v } from "@kikko-land/boono-sql"; | ||
export * from "@kikko-land/boono-sql"; | ||
const A = (e, i) => { | ||
const N = (e, t) => { | ||
if (!e.__state.localState.transactionState.current) | ||
throw new Error("Not in transaction."); | ||
const t = e.__state.localState.transactionState.current, r = [], a = (s) => (T, c) => { | ||
if (t.id === c.id) { | ||
i(s, T, t); | ||
for (const l of r) | ||
l(); | ||
const a = e.__state.localState.transactionState.current, i = [], r = (m) => (T, d) => { | ||
if (a.id === d.id) { | ||
t(m, T, a); | ||
for (const o of i) | ||
o(); | ||
} | ||
}; | ||
r.push( | ||
i.push( | ||
e.__state.sharedState.eventsEmitter.on( | ||
"transactionCommitted", | ||
a("committed") | ||
r("committed") | ||
) | ||
), r.push( | ||
), i.push( | ||
e.__state.sharedState.eventsEmitter.on( | ||
"transactionRollbacked", | ||
a("rollbacked") | ||
r("rollbacked") | ||
) | ||
@@ -29,11 +29,11 @@ ); | ||
return { | ||
async emit(i, ...t) { | ||
const r = e[i] || []; | ||
for (const a of r) | ||
await a(...t); | ||
async emit(t, ...a) { | ||
const i = e[t] || []; | ||
for (const r of i) | ||
await r(...a); | ||
}, | ||
on(i, t) { | ||
return (e[i] = e[i] || []).push(t), () => { | ||
const r = e[i] || []; | ||
e[i] = r.filter((a) => a !== t); | ||
on(t, a) { | ||
return (e[t] = e[t] || []).push(a), () => { | ||
const i = e[t] || []; | ||
e[t] = i.filter((r) => r !== a); | ||
}; | ||
@@ -43,8 +43,8 @@ } | ||
} | ||
class y extends Error { | ||
class $ extends Error { | ||
} | ||
class q extends Error { | ||
} | ||
const J = (e, i) => { | ||
const t = i.deduplicate === void 0 ? !0 : i.deduplicate; | ||
const V = (e, t) => { | ||
const a = t.deduplicate === void 0 ? !0 : t.deduplicate; | ||
return { | ||
@@ -60,9 +60,9 @@ __state: { | ||
}, | ||
set value(r) { | ||
set value(i) { | ||
if (this.isStopped) | ||
throw new Error(`reactiveVar ${i.label} is stopped!`); | ||
if (!(t && z(this.__state.value, r))) { | ||
this.__state.value = r; | ||
for (const a of this.__state.subscriptions) | ||
a(r); | ||
throw new Error(`reactiveVar ${t.label} is stopped!`); | ||
if (!(a && z(this.__state.value, i))) { | ||
this.__state.value = i; | ||
for (const r of this.__state.subscriptions) | ||
r(i); | ||
} | ||
@@ -72,54 +72,54 @@ }, | ||
if (this.isStopped) | ||
throw new Error(`reactiveVar ${i.label} is stopped!`); | ||
throw new Error(`reactiveVar ${t.label} is stopped!`); | ||
return this.__state.value; | ||
}, | ||
subscribe(r, a = !0) { | ||
subscribe(i, r = !0) { | ||
if (this.isStopped) | ||
throw new Error(`reactiveVar ${i.label} is stopped!`); | ||
let s; | ||
const T = (c) => { | ||
s && s(), s = r(c); | ||
throw new Error(`reactiveVar ${t.label} is stopped!`); | ||
let m; | ||
const T = (d) => { | ||
m && m(), m = i(d); | ||
}; | ||
return this.__state.subscriptions.push(T), a && T(this.__state.value), () => { | ||
this.__state.subscriptions = this.__state.subscriptions.filter((c) => c !== T); | ||
return this.__state.subscriptions.push(T), r && T(this.__state.value), () => { | ||
this.__state.subscriptions = this.__state.subscriptions.filter((d) => d !== T); | ||
}; | ||
}, | ||
waitTill(r, a) { | ||
const s = new q( | ||
`waitUntil for reactiveVar ${i.label} is stopped due to stop signal` | ||
), T = new y( | ||
`waitUntil for reactiveVar ${i.label} is timed out` | ||
), c = new q( | ||
`waitUntil for reactiveVar ${i.label} is stopped due to reactive var stop` | ||
waitTill(i, r) { | ||
const m = new q( | ||
`waitUntil for reactiveVar ${t.label} is stopped due to stop signal` | ||
), T = new $( | ||
`waitUntil for reactiveVar ${t.label} is timed out` | ||
), d = new q( | ||
`waitUntil for reactiveVar ${t.label} is stopped due to reactive var stop` | ||
); | ||
if (this.isStopped) | ||
throw new Error(`reactiveVar ${i.label} is stopped!`); | ||
return new Promise((f, o) => { | ||
var m; | ||
const u = [], n = () => { | ||
for (const d of u) | ||
d(); | ||
throw new Error(`reactiveVar ${t.label} is stopped!`); | ||
return new Promise((s, h) => { | ||
var l; | ||
const c = [], n = () => { | ||
for (const u of c) | ||
u(); | ||
}; | ||
if (u.push( | ||
((m = a == null ? void 0 : a.stopIf) == null ? void 0 : m.subscribe((d) => { | ||
!d || (n(), o(s)); | ||
if (c.push( | ||
((l = r == null ? void 0 : r.stopIf) == null ? void 0 : l.subscribe((u) => { | ||
!u || (n(), h(m)); | ||
}, !0)) || (() => { | ||
}) | ||
), u.push( | ||
this.subscribe((d) => { | ||
!r(d) || (n(), f()); | ||
), c.push( | ||
this.subscribe((u) => { | ||
!i(u) || (n(), s()); | ||
}, !0) | ||
), (a == null ? void 0 : a.timeout) === void 0 || typeof (a == null ? void 0 : a.timeout) == "number") { | ||
const d = setTimeout( | ||
), (r == null ? void 0 : r.timeout) === void 0 || typeof (r == null ? void 0 : r.timeout) == "number") { | ||
const u = setTimeout( | ||
() => { | ||
n(), o(T); | ||
n(), h(T); | ||
}, | ||
(a == null ? void 0 : a.timeout) === void 0 ? 6e4 : a.timeout | ||
(r == null ? void 0 : r.timeout) === void 0 ? 12e4 : r.timeout | ||
); | ||
u.push(() => { | ||
clearTimeout(d); | ||
c.push(() => { | ||
clearTimeout(u); | ||
}); | ||
} | ||
this.__state.onStop.push(() => { | ||
n(), o(c); | ||
n(), h(d); | ||
}); | ||
@@ -130,46 +130,49 @@ }); | ||
if (this.isStopped) | ||
throw new Error(`reactiveVar ${i.label} is already stopped!`); | ||
throw new Error(`reactiveVar ${t.label} is already stopped!`); | ||
this.__state.subscriptions = []; | ||
for (const r of this.__state.onStop) | ||
r(); | ||
for (const i of this.__state.onStop) | ||
i(); | ||
this.__state.isStopped = !0; | ||
} | ||
}; | ||
}, v = typeof performance < "u" ? () => performance.now() : () => Date.now(), Q = (e, i) => { | ||
}, k = typeof performance < "u" ? () => performance.now() : () => Date.now(), B = (e, t) => { | ||
const { | ||
__state: { | ||
sharedState: { runningState: t, dbName: r } | ||
sharedState: { runningState: a, dbName: i } | ||
} | ||
} = e; | ||
if (t.value !== "running") | ||
throw new Error(`Failed to start ${i()}, db ${r} is stopping`); | ||
}, K = (e) => e.map((i) => i.preparedQuery); | ||
function $() { | ||
if (a.value !== "running") | ||
throw new Error(`Failed to start ${t()}, db ${i} is stopping`); | ||
}; | ||
function E() { | ||
let e = ""; | ||
const i = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", t = i.length; | ||
for (let r = 0; r < 32; r++) | ||
e += i.charAt(Math.floor(Math.random() * t)); | ||
const t = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", a = t.length; | ||
for (let i = 0; i < 32; i++) | ||
e += t.charAt(Math.floor(Math.random() * a)); | ||
return e; | ||
} | ||
const Y = async ({ | ||
const Y = (e) => e.filter((t) => t !== null), K = (e) => e.reduce((t, a) => t + a, 0), L = (e) => K(Y(e)), H = async ({ | ||
db: e, | ||
queries: i, | ||
transactionOpts: t | ||
queries: t, | ||
transactionOpts: a | ||
}) => { | ||
var m, d, h, b, F, E, C, R, I; | ||
var l, u, f, b, R, C, A, I, Q; | ||
const { | ||
localState: { transactionState: r }, | ||
sharedState: { dbBackend: a, logFns: s }, | ||
localState: { transactionState: i }, | ||
sharedState: { dbBackend: r, logFns: m }, | ||
sharedState: T | ||
} = e.__state; | ||
if (r.current || Q(e, () => JSON.stringify(i)), t && ((m = r.current) == null ? void 0 : m.id) !== t.transactionId) | ||
if (i.current || B(e, () => JSON.stringify(t)), a && ((l = i.current) == null ? void 0 : l.id) !== a.transactionId) | ||
throw new Error( | ||
`Cannot run queries in a transaction that is not the current one. Transaction opts: ${JSON.stringify( | ||
t | ||
)}, local transaction: ${JSON.stringify(r)}` | ||
a | ||
)}, local transaction: ${JSON.stringify(i)}` | ||
); | ||
const c = K(i.map((_) => _.toSql())), l = v(), { result: f, performance: o } = await a.execQueries( | ||
c, | ||
t || (r.current ? { | ||
transactionId: r.current.id, | ||
const d = k(), { | ||
result: o, | ||
performance: s, | ||
textQueries: h | ||
} = await (async () => { | ||
const p = a || (i.current ? { | ||
transactionId: i.current.id, | ||
containsTransactionStart: !1, | ||
@@ -180,55 +183,91 @@ containsTransactionFinish: !1, | ||
isAtomic: !1 | ||
} : void 0) | ||
), u = v(); | ||
} : void 0); | ||
if (t.type === "prepared") { | ||
const _ = t.query.toSql(); | ||
if (_._values.length !== 0) | ||
throw new Error( | ||
"You can't use prepared var through ${} for runPreparedQuery. Please, manually specify variables with '?'." | ||
); | ||
const w = _.preparedQuery.text; | ||
return { | ||
...await r.execPreparedQuery( | ||
_.preparedQuery, | ||
t.preparedValues, | ||
p | ||
), | ||
textQueries: [w] | ||
}; | ||
} else { | ||
const _ = t.values.map((w) => w.preparedQuery); | ||
return { | ||
...await r.execQueries(_, p), | ||
textQueries: _.map((w) => w.text) | ||
}; | ||
} | ||
})(), c = k(); | ||
if (!e.__state.localState.suppressLog) { | ||
const _ = f.map(({ performance: w }, V) => { | ||
const U = [ | ||
w.prepareTime !== void 0 ? `prepareTime=${(w.prepareTime / 1e3).toFixed(4)}` : "", | ||
w.execTime !== void 0 ? `execTime=${(w.execTime / 1e3).toFixed(4)}` : "", | ||
w.freeTime !== void 0 ? `freeTime=${(w.freeTime / 1e3).toFixed(4)}` : "" | ||
].filter((x) => x.length !== 0).join(" "); | ||
return [c[V].text.slice(0, 1e3), U].filter((x) => x.length !== 0).join(" "); | ||
}), g = (() => _.length === 1 ? _[0] : ` | ||
` + _.map((w) => `{${w}}`).join(` | ||
`))(), S = `%c[${e.__state.sharedState.dbName}] ` + [ | ||
(d = r.current) != null && d.id ? `[tr_id=${(h = r.current) == null ? void 0 : h.id.substring(0, 6)}]` : "", | ||
g, | ||
(o == null ? void 0 : o.sendTime) !== void 0 ? `sendTime=${(o.sendTime / 1e3).toFixed(4)}` : "", | ||
(o == null ? void 0 : o.receiveTime) !== void 0 ? `receiveTime=${(o.receiveTime / 1e3).toFixed(4)}` : "", | ||
(o == null ? void 0 : o.blockTime) !== void 0 ? `blockTime=${(o.blockTime / 1e3).toFixed(4)}` : "", | ||
`totalTime=${((u - l) / 1e3).toFixed(4)}` | ||
].filter((w) => w.length !== 0).join(" "), W = (E = T.transactionsStates.byId[(F = (b = r.current) == null ? void 0 : b.id) != null ? F : ""]) == null ? void 0 : E.i; | ||
s.logQuery(S, W); | ||
const p = (S, x) => `${S}=${(x / 1e3).toFixed(4)}`, _ = (() => { | ||
if (t.type === "prepared") { | ||
const S = o[0], x = [ | ||
S.performance.prepareTime !== void 0 ? p( | ||
"prepareTime", | ||
L(o.map((g) => g.performance.prepareTime)) | ||
) : "", | ||
S.performance.execTime !== void 0 ? p( | ||
"execTime", | ||
L(o.map((g) => g.performance.execTime)) | ||
) : "" | ||
].filter((g) => g.length !== 0).join(" "); | ||
return [ | ||
[ | ||
h[0].slice(0, 1e3), | ||
`for ${t.preparedValues.length} values`, | ||
x | ||
].filter((g) => g.length !== 0).join(" ") | ||
]; | ||
} else | ||
return o.map(({ performance: S }, x) => { | ||
const g = [ | ||
S.prepareTime !== void 0 ? p("prepareTime", S.prepareTime) : "", | ||
S.execTime !== void 0 ? p("execTime", S.execTime) : "" | ||
].filter((F) => F.length !== 0).join(" "); | ||
return [h[x].slice(0, 1e3), g].filter((F) => F.length !== 0).join(" "); | ||
}); | ||
})(), w = (() => _.length === 1 ? _[0] : ` | ||
` + _.map((S) => `{${S}}`).join(` | ||
`))(), P = `%c[${e.__state.sharedState.dbName}] ` + [ | ||
(u = i.current) != null && u.id ? `[tr_id=${(f = i.current) == null ? void 0 : f.id.substring(0, 6)}]` : "", | ||
w, | ||
(s == null ? void 0 : s.sendTime) !== void 0 ? `sendTime=${(s.sendTime / 1e3).toFixed(4)}` : "", | ||
(s == null ? void 0 : s.receiveTime) !== void 0 ? `receiveTime=${(s.receiveTime / 1e3).toFixed(4)}` : "", | ||
(s == null ? void 0 : s.blockTime) !== void 0 ? `blockTime=${(s.blockTime / 1e3).toFixed(4)}` : "", | ||
`totalTime=${((c - d) / 1e3).toFixed(4)}` | ||
].filter((S) => S.length !== 0).join(" "), j = (C = T.transactionsStates.byId[(R = (b = i.current) == null ? void 0 : b.id) != null ? R : ""]) == null ? void 0 : C.i; | ||
m.logQuery(P, j); | ||
} | ||
const n = (I = T.transactionsStates.byId[(R = (C = r.current) == null ? void 0 : C.id) != null ? R : ""]) == null ? void 0 : I.performance; | ||
return n && (f.some((_) => _.performance.execTime !== void 0) && (n.execTime === void 0 && (n.execTime = 0), n.execTime += f.reduce( | ||
(_, g) => { | ||
var S; | ||
return _ + ((S = g.performance.execTime) != null ? S : 0); | ||
const n = (Q = T.transactionsStates.byId[(I = (A = i.current) == null ? void 0 : A.id) != null ? I : ""]) == null ? void 0 : Q.performance; | ||
return n && (o.some((p) => p.performance.execTime !== void 0) && (n.execTime === void 0 && (n.execTime = 0), n.execTime += o.reduce( | ||
(p, _) => { | ||
var w; | ||
return p + ((w = _.performance.execTime) != null ? w : 0); | ||
}, | ||
0 | ||
)), f.some((_) => _.performance.freeTime !== void 0) && (n.freeTime === void 0 && (n.freeTime = 0), n.freeTime += f.reduce( | ||
(_, g) => { | ||
var S; | ||
return _ + ((S = g.performance.freeTime) != null ? S : 0); | ||
)), o.some((p) => p.performance.prepareTime !== void 0) && (n.prepareTime === void 0 && (n.prepareTime = 0), n.prepareTime += o.reduce( | ||
(p, _) => { | ||
var w; | ||
return p + ((w = _.performance.prepareTime) != null ? w : 0); | ||
}, | ||
0 | ||
)), f.some((_) => _.performance.prepareTime !== void 0) && (n.prepareTime === void 0 && (n.prepareTime = 0), n.prepareTime += f.reduce( | ||
(_, g) => { | ||
var S; | ||
return _ + ((S = g.performance.prepareTime) != null ? S : 0); | ||
}, | ||
0 | ||
)), o.sendTime && (n.sendTime || (n.sendTime = 0), n.sendTime += o.sendTime), o.receiveTime && (n.receiveTime || (n.receiveTime = 0), n.receiveTime += o.receiveTime), o.blockTime && (n.blockTime || (n.blockTime = 0), n.blockTime += o.blockTime)), { db: e, result: f, performance: o, queries: i }; | ||
}, k = async (e, i, t) => { | ||
const r = [ | ||
)), s.sendTime && (n.sendTime || (n.sendTime = 0), n.sendTime += s.sendTime), s.receiveTime && (n.receiveTime || (n.receiveTime = 0), n.receiveTime += s.receiveTime), s.blockTime && (n.blockTime || (n.blockTime = 0), n.blockTime += s.blockTime)), { db: e, result: o, performance: s, queries: t }; | ||
}, y = async (e, t, a) => { | ||
const i = [ | ||
...e.__state.localState.queriesMiddlewares, | ||
Y | ||
H | ||
].reverse(); | ||
let a = (s) => Promise.resolve(s); | ||
for (const s of r) { | ||
const T = a; | ||
a = (c) => s({ ...c, next: T }); | ||
let r = (m) => Promise.resolve(m); | ||
for (const m of i) { | ||
const T = r; | ||
r = (d) => m({ ...d, next: T }); | ||
} | ||
return await a({ | ||
return await r({ | ||
db: e, | ||
@@ -241,30 +280,29 @@ result: [], | ||
}, | ||
queries: i.map((s) => s.toSql()), | ||
transactionOpts: t | ||
queries: t, | ||
transactionOpts: a | ||
}); | ||
}; | ||
let D = 0; | ||
const B = (e, i, t) => { | ||
const r = e.__state.sharedState.logFns; | ||
let M = 0; | ||
const W = (e, t, a) => { | ||
const i = e.__state.sharedState.logFns; | ||
if (e.__state.localState.suppressLog) | ||
return; | ||
const a = [ | ||
t.prepareTime === void 0 ? "" : `prepareTime=${(t.prepareTime / 1e3).toFixed(4)}`, | ||
t.execTime === void 0 ? "" : `execTime=${(t.execTime / 1e3).toFixed(4)}`, | ||
t.freeTime === void 0 ? "" : `freeTime=${(t.freeTime / 1e3).toFixed(4)}`, | ||
t.sendTime === void 0 ? "" : `sendTime=${(t.sendTime / 1e3).toFixed(4)}`, | ||
t.receiveTime === void 0 ? "" : `receiveTime=${(t.receiveTime / 1e3).toFixed(4)}`, | ||
t.blockTime === void 0 ? "" : `blockTime=${(t.blockTime / 1e3).toFixed(4)}`, | ||
`totalTime=${(t.totalTime / 1e3).toFixed(4)}` | ||
].filter((s) => s.length !== 0).join(" "); | ||
r.logTrFinish( | ||
`%c[${e.__state.sharedState.dbName}][tr_id=${i.slice( | ||
const r = [ | ||
a.prepareTime === void 0 ? "" : `prepareTime=${(a.prepareTime / 1e3).toFixed(4)}`, | ||
a.execTime === void 0 ? "" : `execTime=${(a.execTime / 1e3).toFixed(4)}`, | ||
a.sendTime === void 0 ? "" : `sendTime=${(a.sendTime / 1e3).toFixed(4)}`, | ||
a.receiveTime === void 0 ? "" : `receiveTime=${(a.receiveTime / 1e3).toFixed(4)}`, | ||
a.blockTime === void 0 ? "" : `blockTime=${(a.blockTime / 1e3).toFixed(4)}`, | ||
`totalTime=${(a.totalTime / 1e3).toFixed(4)}` | ||
].filter((m) => m.length !== 0).join(" "); | ||
i.logTrFinish( | ||
`%c[${e.__state.sharedState.dbName}][tr_id=${t.slice( | ||
0, | ||
6 | ||
)}] Transaction finished with ${a}` | ||
)}] Transaction finished with ${r}` | ||
); | ||
}, j = async (e, i, t) => { | ||
}, X = async (e, t, a) => { | ||
const { | ||
localState: { transactionState: r }, | ||
sharedState: { eventsEmitter: a, transactionsStates: s, dbBackend: T, logFns: c } | ||
localState: { transactionState: i }, | ||
sharedState: { eventsEmitter: r, transactionsStates: m, dbBackend: T, logFns: d } | ||
} = e.__state; | ||
@@ -275,7 +313,7 @@ if (T.isUsualTransactionDisabled) | ||
); | ||
if (r.current) | ||
return await t(e); | ||
Q(e, () => "transaction"); | ||
const l = { | ||
id: $(), | ||
if (i.current) | ||
return await a(e); | ||
B(e, () => "transaction"); | ||
const o = { | ||
id: E(), | ||
type: "async" | ||
@@ -289,9 +327,9 @@ }; | ||
...e.__state.localState, | ||
transactionState: { current: l } | ||
transactionState: { current: o } | ||
} | ||
} | ||
}; | ||
const f = v(), o = { | ||
i: D++, | ||
current: l, | ||
const s = k(), h = { | ||
i: M++, | ||
current: o, | ||
performance: { | ||
@@ -307,9 +345,16 @@ prepareTime: 0, | ||
}; | ||
s.byId[l.id] = o; | ||
m.byId[o.id] = h; | ||
try { | ||
await a.emit("transactionWillStart", e, l), await k( | ||
await r.emit("transactionWillStart", e, o), await y( | ||
e, | ||
[p`BEGIN ${p.raw(i.toLocaleUpperCase())} TRANSACTION`], | ||
{ | ||
transactionId: l.id, | ||
type: "usual", | ||
values: [ | ||
v`BEGIN ${v.raw( | ||
t.toLocaleUpperCase() | ||
)} TRANSACTION` | ||
] | ||
}, | ||
{ | ||
transactionId: o.id, | ||
containsTransactionStart: !0, | ||
@@ -321,33 +366,41 @@ containsTransactionFinish: !1, | ||
} | ||
), await a.emit("transactionStarted", e, l); | ||
), await r.emit("transactionStarted", e, o); | ||
try { | ||
const u = await t(e); | ||
return await a.emit("transactionWillCommit", e, l), await k(e, [p`COMMIT`], { | ||
transactionId: l.id, | ||
containsTransactionStart: !1, | ||
containsTransactionFinish: !0, | ||
containsTransactionRollback: !1, | ||
rollbackOnFail: !1, | ||
isAtomic: !1 | ||
}), await a.emit("transactionCommitted", e, l), u; | ||
} catch (u) { | ||
c.logError("Rollback transaction", u), await a.emit("transactionWillRollback", e, l); | ||
try { | ||
await k(e, [p`ROLLBACK`], { | ||
transactionId: l.id, | ||
const c = await a(e); | ||
return await r.emit("transactionWillCommit", e, o), await y( | ||
e, | ||
{ type: "usual", values: [v`COMMIT`] }, | ||
{ | ||
transactionId: o.id, | ||
containsTransactionStart: !1, | ||
containsTransactionFinish: !1, | ||
containsTransactionRollback: !0, | ||
containsTransactionFinish: !0, | ||
containsTransactionRollback: !1, | ||
rollbackOnFail: !1, | ||
isAtomic: !1 | ||
}); | ||
} | ||
), await r.emit("transactionCommitted", e, o), c; | ||
} catch (c) { | ||
d.logError("Rollback transaction", c), await r.emit("transactionWillRollback", e, o); | ||
try { | ||
await y( | ||
e, | ||
{ type: "usual", values: [v`ROLLBACK`] }, | ||
{ | ||
transactionId: o.id, | ||
containsTransactionStart: !1, | ||
containsTransactionFinish: !1, | ||
containsTransactionRollback: !0, | ||
rollbackOnFail: !1, | ||
isAtomic: !1 | ||
} | ||
); | ||
} catch (n) { | ||
c.logError("Rollback transaction failed", n); | ||
d.logError("Rollback transaction failed", n); | ||
} | ||
throw await a.emit("transactionRollbacked", e, l), u; | ||
throw await r.emit("transactionRollbacked", e, o), c; | ||
} | ||
} finally { | ||
o.performance.totalTime = v() - f, B(e, l.id, o.performance), delete s.byId[l.id]; | ||
h.performance.totalTime = k() - s, W(e, o.id, h.performance), delete m.byId[o.id]; | ||
} | ||
}, H = () => ({ | ||
}, Z = () => ({ | ||
__state: { | ||
@@ -367,15 +420,15 @@ queries: [], | ||
} | ||
}), X = async (e, i, t) => { | ||
}), O = async (e, t, a) => { | ||
const { | ||
localState: { transactionState: r }, | ||
sharedState: { eventsEmitter: a, transactionsStates: s, dbBackend: T, logFns: c } | ||
localState: { transactionState: i }, | ||
sharedState: { eventsEmitter: r, transactionsStates: m, dbBackend: T, logFns: d } | ||
} = e.__state; | ||
if (r.current) | ||
if (i.current) | ||
throw new Error( | ||
"You are running atomic transaction inside of a transaction. Consider moving atomic transaction call to runAfterTransaction callback." | ||
); | ||
const { inputQueries: l, afterCommits: f, afterRollbacks: o } = await (async () => { | ||
if (Array.isArray(t)) | ||
const { inputQueries: o, afterCommits: s, afterRollbacks: h } = await (async () => { | ||
if (Array.isArray(a)) | ||
return { | ||
inputQueries: t, | ||
inputQueries: a, | ||
afterCommits: [], | ||
@@ -385,15 +438,15 @@ afterRollbacks: [] | ||
{ | ||
const h = H(); | ||
return await t(h), { | ||
inputQueries: h.__state.queries, | ||
afterCommits: h.__state.afterCommits, | ||
afterRollbacks: h.__state.afterRollbacks | ||
const f = Z(); | ||
return await a(f), { | ||
inputQueries: f.__state.queries, | ||
afterCommits: f.__state.afterCommits, | ||
afterRollbacks: f.__state.afterRollbacks | ||
}; | ||
} | ||
})(), u = { | ||
id: $(), | ||
})(), c = { | ||
id: E(), | ||
type: "atomic" | ||
}, n = { | ||
i: D++, | ||
current: u, | ||
i: M++, | ||
current: c, | ||
performance: { | ||
@@ -415,55 +468,59 @@ prepareTime: 0, | ||
...e.__state.localState, | ||
transactionState: { current: u } | ||
transactionState: { current: c } | ||
} | ||
} | ||
}, s.byId[u.id] = n; | ||
const m = v(), d = []; | ||
T.isAtomicRollbackCommitDisabled || d.push(p`BEGIN ${p.raw(i.toUpperCase())} TRANSACTION`), d.push(...l), T.isAtomicRollbackCommitDisabled || d.push(p`COMMIT`); | ||
}, m.byId[c.id] = n; | ||
const l = k(), u = []; | ||
T.isAtomicRollbackCommitDisabled || u.push(v`BEGIN ${v.raw(t.toUpperCase())} TRANSACTION`), u.push(...o.map((f) => f.toSql())), T.isAtomicRollbackCommitDisabled || u.push(v`COMMIT`); | ||
try { | ||
await a.emit("transactionWillStart", e, u), await a.emit("transactionStarted", e, u), await k(e, d, { | ||
transactionId: u.id, | ||
containsTransactionStart: !0, | ||
containsTransactionFinish: !0, | ||
containsTransactionRollback: !1, | ||
rollbackOnFail: !0, | ||
isAtomic: !0 | ||
}), await a.emit("transactionWillCommit", e, u), await a.emit("transactionCommitted", e, u); | ||
await r.emit("transactionWillStart", e, c), await r.emit("transactionStarted", e, c), await y( | ||
e, | ||
{ type: "usual", values: u }, | ||
{ | ||
transactionId: c.id, | ||
containsTransactionStart: !0, | ||
containsTransactionFinish: !0, | ||
containsTransactionRollback: !1, | ||
rollbackOnFail: !0, | ||
isAtomic: !0 | ||
} | ||
), await r.emit("transactionWillCommit", e, c), await r.emit("transactionCommitted", e, c); | ||
try { | ||
for (const h of f) | ||
h(); | ||
} catch (h) { | ||
c.logError("Error in afterCommit callback", h); | ||
for (const f of s) | ||
f(); | ||
} catch (f) { | ||
d.logError("Error in afterCommit callback", f); | ||
} | ||
} catch (h) { | ||
c.logError("Rollback transaction", h), await a.emit("transactionWillRollback", e, u), await a.emit("transactionRollbacked", e, u); | ||
} catch (f) { | ||
d.logError("Rollback transaction", f), await r.emit("transactionWillRollback", e, c), await r.emit("transactionRollbacked", e, c); | ||
try { | ||
for (const b of o) | ||
for (const b of h) | ||
b(); | ||
} catch (b) { | ||
c.logError("Error in afterRallback callback", b); | ||
d.logError("Error in afterRallback callback", b); | ||
} | ||
throw h; | ||
throw f; | ||
} finally { | ||
n.performance.totalTime = v() - m, B(e, u.id, n.performance), delete s.byId[u.id]; | ||
n.performance.totalTime = k() - l, W(e, c.id, n.performance), delete m.byId[c.id]; | ||
} | ||
}, N = ["yellow", "cyan", "magenta"], ee = async ({ | ||
}, J = ["yellow", "cyan", "magenta"], re = async ({ | ||
dbName: e, | ||
plugins: i, | ||
queriesMiddlewares: t, | ||
dbBackend: r, | ||
suppressLog: a, | ||
logFns: s | ||
plugins: t, | ||
queriesMiddlewares: a, | ||
dbBackend: i, | ||
suppressLog: r, | ||
logFns: m | ||
}) => { | ||
const T = s || { | ||
logQuery: (n, m) => { | ||
const d = typeof m == "number" ? N[m % N.length] : void 0; | ||
const T = m || { | ||
logQuery: (n, l) => { | ||
const u = typeof l == "number" ? J[l % J.length] : void 0; | ||
console.log( | ||
...d ? [ | ||
...u ? [ | ||
n, | ||
`color: ${d}; background-color: #202124; padding: 2px 4px; border-radius: 2px` | ||
] : [n] | ||
`color: ${u}; background-color: #202124; padding: 2px 4px; border-radius: 2px` | ||
] : [n, "padding: 0"] | ||
); | ||
}, | ||
logError: (n, m) => { | ||
console.error(n, m); | ||
logError: (n, l) => { | ||
console.error(n, l); | ||
}, | ||
@@ -476,14 +533,14 @@ logTrFinish: (n) => { | ||
} | ||
}, c = J( | ||
}, d = V( | ||
"running", | ||
{ label: "runningState" } | ||
), l = (await r)({ | ||
), o = (await i)({ | ||
dbName: e | ||
}), f = { | ||
}), s = { | ||
__state: { | ||
sharedState: { | ||
clientId: $(), | ||
dbBackend: l, | ||
clientId: E(), | ||
dbBackend: o, | ||
dbName: e, | ||
runningState: c, | ||
runningState: d, | ||
eventsEmitter: G(), | ||
@@ -494,15 +551,18 @@ transactionsStates: { byId: {} }, | ||
localState: { | ||
queriesMiddlewares: t || [], | ||
queriesMiddlewares: a || [], | ||
transactionState: {}, | ||
suppressLog: Boolean(a) | ||
suppressLog: Boolean(r) | ||
} | ||
}, | ||
runInTransaction(n, m) { | ||
return j(this, (m == null ? void 0 : m.type) || "deferred", n); | ||
runInTransaction(n, l) { | ||
return X(this, (l == null ? void 0 : l.type) || "deferred", n); | ||
}, | ||
async runInAtomicTransaction(n, m) { | ||
return await X(this, (m == null ? void 0 : m.type) || "deferred", n); | ||
async runInAtomicTransaction(n, l) { | ||
return await O(this, (l == null ? void 0 : l.type) || "deferred", n); | ||
}, | ||
async runQueries(n) { | ||
return (await k(this, n)).result.map(({ rows: d }) => d); | ||
return (await y(this, { | ||
type: "usual", | ||
values: n.map((u) => u.toSql()) | ||
})).result.map(({ rows: u }) => u); | ||
}, | ||
@@ -512,32 +572,39 @@ async runQuery(n) { | ||
}, | ||
async runPreparedQuery(n, l) { | ||
return (await y(this, { | ||
type: "prepared", | ||
query: n, | ||
preparedValues: l | ||
})).result.map(({ rows: f }) => f); | ||
}, | ||
runAfterTransactionCommitted(n) { | ||
return A(this, (m, d, h) => { | ||
m === "committed" && n(d, h); | ||
return N(this, (l, u, f) => { | ||
l === "committed" && n(u, f); | ||
}); | ||
}, | ||
runAfterTransactionRollbacked(n) { | ||
A(f, (m, d, h) => { | ||
m === "rollbacked" && n(d, h); | ||
N(s, (l, u, f) => { | ||
l === "rollbacked" && n(u, f); | ||
}); | ||
} | ||
}; | ||
let o = f; | ||
const u = () => f.__state.sharedState.runningState.value; | ||
if (u() !== "running" || (await l.initialize(), u() !== "running")) | ||
return f; | ||
for (const n of i || []) | ||
o = n(o); | ||
return await f.__state.sharedState.eventsEmitter.emit("initialized", f), o; | ||
}, te = async (e) => { | ||
let h = s; | ||
const c = () => s.__state.sharedState.runningState.value; | ||
if (c() !== "running" || (await o.initialize(), c() !== "running")) | ||
return s; | ||
for (const n of t || []) | ||
h = n(h); | ||
return await s.__state.sharedState.eventsEmitter.emit("initialized", s), h; | ||
}, ie = async (e) => { | ||
e.__state.sharedState.runningState.value = "stopping", await e.__state.sharedState.dbBackend.stop(), e.__state.sharedState.runningState.value = "stopped", queueMicrotask(() => { | ||
e.__state.sharedState.runningState.stop(); | ||
}); | ||
}, M = (e) => { | ||
const { current: i, queue: t } = e; | ||
}, U = (e) => { | ||
const { current: t, queue: a } = e; | ||
return `current running job: ${JSON.stringify( | ||
i, | ||
t, | ||
null, | ||
2 | ||
)}, queue: ${JSON.stringify(t, null, 2)}`; | ||
}, ie = () => J( | ||
)}, queue: ${JSON.stringify(a, null, 2)}`; | ||
}, ne = () => V( | ||
{ | ||
@@ -548,21 +615,23 @@ queue: [], | ||
{ label: "jobsState" } | ||
), Z = async (e, i) => { | ||
const t = i != null ? i : $(), r = { id: t }, { current: a, queue: s } = e.value; | ||
if (a || s.length > 0) { | ||
const T = e.waitTill((c) => { | ||
var l; | ||
return ((l = c.current) == null ? void 0 : l.id) === t; | ||
), ee = async (e, t) => { | ||
const a = t != null ? t : E(), i = { id: a }, { current: r, queue: m } = e.value; | ||
if (r || m.length > 0) { | ||
const T = e.waitTill((d) => { | ||
var o; | ||
return ((o = d.current) == null ? void 0 : o.id) === a; | ||
}, { | ||
timeout: 12e4 | ||
}); | ||
e.value = { | ||
queue: [...s, r], | ||
current: a | ||
queue: [...m, i], | ||
current: r | ||
}; | ||
try { | ||
await T; | ||
} catch (c) { | ||
throw c instanceof y ? new y( | ||
`Timeout error while job acquire: '${c.message}'. Is it a dead lock? ${M( | ||
} catch (d) { | ||
throw d instanceof $ ? new $( | ||
`Timeout error while job acquire: '${d.message}'. Is it a dead lock? ${U( | ||
e.value | ||
)}, jobToAcquire: ${JSON.stringify(r, null, 2)}` | ||
) : c; | ||
)}, jobToAcquire: ${JSON.stringify(i, null, 2)}` | ||
) : d; | ||
} | ||
@@ -572,26 +641,26 @@ } else | ||
queue: [], | ||
current: r | ||
current: i | ||
}; | ||
return r; | ||
}, L = (e, i) => { | ||
const { current: t, queue: r } = e.value; | ||
if ((t == null ? void 0 : t.id) !== i.id) | ||
return i; | ||
}, D = (e, t) => { | ||
const { current: a, queue: i } = e.value; | ||
if ((a == null ? void 0 : a.id) !== t.id) | ||
throw new Error( | ||
`Can't release job that is not currently running, ${M( | ||
`Can't release job that is not currently running, ${U( | ||
e.value | ||
)}, toRelease: ${JSON.stringify(i, null, 2)}` | ||
)}, toRelease: ${JSON.stringify(t, null, 2)}` | ||
); | ||
e.value = { queue: r.slice(1), current: r[0] }; | ||
}, ae = async (e) => { | ||
e.value = { queue: i.slice(1), current: i[0] }; | ||
}, oe = async (e) => { | ||
try { | ||
return e.waitTill( | ||
({ queue: i, current: t }) => i.length === 0 && t === void 0, | ||
{ timeout: 3e4 } | ||
({ queue: t, current: a }) => t.length === 0 && a === void 0, | ||
{ timeout: 12e4 } | ||
); | ||
} catch (i) { | ||
throw i instanceof y ? new y( | ||
`Timeout error while awaiting all jobs done: '${i.message}'. Is it a dead lock?` | ||
) : i; | ||
} catch (t) { | ||
throw t instanceof $ ? new $( | ||
`Timeout error while awaiting all jobs done: '${t.message}'. Is it a dead lock?` | ||
) : t; | ||
} | ||
}, re = (e, i) => i({ | ||
}, se = (e, t) => t({ | ||
...e, | ||
@@ -605,3 +674,3 @@ __state: { | ||
} | ||
}), ne = (e) => ({ | ||
}), ce = (e) => ({ | ||
...e, | ||
@@ -612,30 +681,30 @@ __state: { | ||
} | ||
}), oe = async (e, i) => { | ||
let t; | ||
return (!i || (i == null ? void 0 : i.containsTransactionStart)) && (t = await Z(e, i == null ? void 0 : i.transactionId)), i && !i.containsTransactionStart && await e.waitTill( | ||
(r) => { | ||
var a; | ||
return ((a = r.current) == null ? void 0 : a.id) === i.transactionId; | ||
}), le = async (e, t) => { | ||
let a; | ||
return (!t || (t == null ? void 0 : t.containsTransactionStart)) && (a = await ee(e, t == null ? void 0 : t.transactionId)), t && !t.containsTransactionStart && await e.waitTill( | ||
(i) => { | ||
var r; | ||
return ((r = i.current) == null ? void 0 : r.id) === t.transactionId; | ||
} | ||
), t; | ||
}, se = (e, i, t) => { | ||
i && (!t || (t == null ? void 0 : t.containsTransactionFinish) || (t == null ? void 0 : t.containsTransactionRollback)) && L(e, i), !i && t && ((t == null ? void 0 : t.containsTransactionRollback) || (t == null ? void 0 : t.containsTransactionFinish)) && L(e, { id: t.transactionId }); | ||
), a; | ||
}, ue = (e, t, a) => { | ||
t && (!a || (a == null ? void 0 : a.containsTransactionFinish) || (a == null ? void 0 : a.containsTransactionRollback)) && D(e, t), !t && a && ((a == null ? void 0 : a.containsTransactionRollback) || (a == null ? void 0 : a.containsTransactionFinish)) && D(e, { id: a.transactionId }); | ||
}; | ||
export { | ||
q as StoppedError, | ||
y as TimeoutError, | ||
Z as acquireJob, | ||
oe as acquireWithTrJobOrWait, | ||
v as getTime, | ||
ee as initDbClient, | ||
ie as initJobsState, | ||
$ as makeId, | ||
J as reactiveVar, | ||
L as releaseJob, | ||
se as releaseTrJobIfPossible, | ||
te as stopDb, | ||
re as suppressLog, | ||
ae as whenAllJobsDone, | ||
ne as withSuppressedLog | ||
$ as TimeoutError, | ||
ee as acquireJob, | ||
le as acquireWithTrJobOrWait, | ||
k as getTime, | ||
re as initDbClient, | ||
ne as initJobsState, | ||
E as makeId, | ||
V as reactiveVar, | ||
D as releaseJob, | ||
ue as releaseTrJobIfPossible, | ||
ie as stopDb, | ||
se as suppressLog, | ||
oe as whenAllJobsDone, | ||
ce as withSuppressedLog | ||
}; | ||
//# sourceMappingURL=index.es.js.map |
@@ -1,4 +0,4 @@ | ||
(function(m,$){typeof exports=="object"&&typeof module<"u"?$(exports,require("fast-equals"),require("@kikko-land/boono-sql")):typeof define=="function"&&define.amd?define(["exports","fast-equals","@kikko-land/boono-sql"],$):(m=typeof globalThis<"u"?globalThis:m||self,$(m.core={},m.fastEquals,m.boonoSql))})(this,function(m,$,g){"use strict";const q=(e,i)=>{if(!e.__state.localState.transactionState.current)throw new Error("Not in transaction.");const t=e.__state.localState.transactionState.current,r=[],a=o=>(h,c)=>{if(t.id===c.id){i(o,h,t);for(const l of r)l()}};r.push(e.__state.sharedState.eventsEmitter.on("transactionCommitted",a("committed"))),r.push(e.__state.sharedState.eventsEmitter.on("transactionRollbacked",a("rollbacked")))};function j(){const e={};return{async emit(i,...t){const r=e[i]||[];for(const a of r)await a(...t)},on(i,t){return(e[i]=e[i]||[]).push(t),()=>{const r=e[i]||[];e[i]=r.filter(a=>a!==t)}}}}class k extends Error{}class C extends Error{}const R=(e,i)=>{const t=i.deduplicate===void 0?!0:i.deduplicate;return{__state:{subscriptions:[],value:e,isStopped:!1,onStop:[]},get isStopped(){return this.__state.isStopped},set value(r){if(this.isStopped)throw new Error(`reactiveVar ${i.label} is stopped!`);if(!(t&&$.deepEqual(this.__state.value,r))){this.__state.value=r;for(const a of this.__state.subscriptions)a(r)}},get value(){if(this.isStopped)throw new Error(`reactiveVar ${i.label} is stopped!`);return this.__state.value},subscribe(r,a=!0){if(this.isStopped)throw new Error(`reactiveVar ${i.label} is stopped!`);let o;const h=c=>{o&&o(),o=r(c)};return this.__state.subscriptions.push(h),a&&h(this.__state.value),()=>{this.__state.subscriptions=this.__state.subscriptions.filter(c=>c!==h)}},waitTill(r,a){const o=new C(`waitUntil for reactiveVar ${i.label} is stopped due to stop signal`),h=new k(`waitUntil for reactiveVar ${i.label} is timed out`),c=new C(`waitUntil for reactiveVar ${i.label} is stopped due to reactive var stop`);if(this.isStopped)throw new Error(`reactiveVar ${i.label} is stopped!`);return new Promise((T,s)=>{var d;const u=[],n=()=>{for(const f of u)f()};if(u.push(((d=a==null?void 0:a.stopIf)==null?void 0:d.subscribe(f=>{!f||(n(),s(o))},!0))||(()=>{})),u.push(this.subscribe(f=>{!r(f)||(n(),T())},!0)),(a==null?void 0:a.timeout)===void 0||typeof(a==null?void 0:a.timeout)=="number"){const f=setTimeout(()=>{n(),s(h)},(a==null?void 0:a.timeout)===void 0?6e4:a.timeout);u.push(()=>{clearTimeout(f)})}this.__state.onStop.push(()=>{n(),s(c)})})},stop(){if(this.isStopped)throw new Error(`reactiveVar ${i.label} is already stopped!`);this.__state.subscriptions=[];for(const r of this.__state.onStop)r();this.__state.isStopped=!0}}},v=typeof performance<"u"?()=>performance.now():()=>Date.now(),x=(e,i)=>{const{__state:{sharedState:{runningState:t,dbName:r}}}=e;if(t.value!=="running")throw new Error(`Failed to start ${i()}, db ${r} is stopping`)},P=e=>e.map(i=>i.preparedQuery);function E(){let e="";const i="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",t=i.length;for(let r=0;r<32;r++)e+=i.charAt(Math.floor(Math.random()*t));return e}const z=async({db:e,queries:i,transactionOpts:t})=>{var d,f,_,y,M,W,B,V,U;const{localState:{transactionState:r},sharedState:{dbBackend:a,logFns:o},sharedState:h}=e.__state;if(r.current||x(e,()=>JSON.stringify(i)),t&&((d=r.current)==null?void 0:d.id)!==t.transactionId)throw new Error(`Cannot run queries in a transaction that is not the current one. Transaction opts: ${JSON.stringify(t)}, local transaction: ${JSON.stringify(r)}`);const c=P(i.map(w=>w.toSql())),l=v(),{result:T,performance:s}=await a.execQueries(c,t||(r.current?{transactionId:r.current.id,containsTransactionStart:!1,containsTransactionFinish:!1,containsTransactionRollback:!1,rollbackOnFail:!1,isAtomic:!1}:void 0)),u=v();if(!e.__state.localState.suppressLog){const w=T.map(({performance:b},ne)=>{const se=[b.prepareTime!==void 0?`prepareTime=${(b.prepareTime/1e3).toFixed(4)}`:"",b.execTime!==void 0?`execTime=${(b.execTime/1e3).toFixed(4)}`:"",b.freeTime!==void 0?`freeTime=${(b.freeTime/1e3).toFixed(4)}`:""].filter(A=>A.length!==0).join(" ");return[c[ne].text.slice(0,1e3),se].filter(A=>A.length!==0).join(" ")}),p=(()=>w.length===1?w[0]:` | ||
`+w.map(b=>`{${b}}`).join(` | ||
`))(),S=`%c[${e.__state.sharedState.dbName}] `+[(f=r.current)!=null&&f.id?`[tr_id=${(_=r.current)==null?void 0:_.id.substring(0,6)}]`:"",p,(s==null?void 0:s.sendTime)!==void 0?`sendTime=${(s.sendTime/1e3).toFixed(4)}`:"",(s==null?void 0:s.receiveTime)!==void 0?`receiveTime=${(s.receiveTime/1e3).toFixed(4)}`:"",(s==null?void 0:s.blockTime)!==void 0?`blockTime=${(s.blockTime/1e3).toFixed(4)}`:"",`totalTime=${((u-l)/1e3).toFixed(4)}`].filter(b=>b.length!==0).join(" "),re=(W=h.transactionsStates.byId[(M=(y=r.current)==null?void 0:y.id)!=null?M:""])==null?void 0:W.i;o.logQuery(S,re)}const n=(U=h.transactionsStates.byId[(V=(B=r.current)==null?void 0:B.id)!=null?V:""])==null?void 0:U.performance;return n&&(T.some(w=>w.performance.execTime!==void 0)&&(n.execTime===void 0&&(n.execTime=0),n.execTime+=T.reduce((w,p)=>{var S;return w+((S=p.performance.execTime)!=null?S:0)},0)),T.some(w=>w.performance.freeTime!==void 0)&&(n.freeTime===void 0&&(n.freeTime=0),n.freeTime+=T.reduce((w,p)=>{var S;return w+((S=p.performance.freeTime)!=null?S:0)},0)),T.some(w=>w.performance.prepareTime!==void 0)&&(n.prepareTime===void 0&&(n.prepareTime=0),n.prepareTime+=T.reduce((w,p)=>{var S;return w+((S=p.performance.prepareTime)!=null?S:0)},0)),s.sendTime&&(n.sendTime||(n.sendTime=0),n.sendTime+=s.sendTime),s.receiveTime&&(n.receiveTime||(n.receiveTime=0),n.receiveTime+=s.receiveTime),s.blockTime&&(n.blockTime||(n.blockTime=0),n.blockTime+=s.blockTime)),{db:e,result:T,performance:s,queries:i}},F=async(e,i,t)=>{const r=[...e.__state.localState.queriesMiddlewares,z].reverse();let a=o=>Promise.resolve(o);for(const o of r){const h=a;a=c=>o({...c,next:h})}return await a({db:e,result:[],performance:{sendTime:void 0,receiveTime:void 0,totalTime:0},queries:i.map(o=>o.toSql()),transactionOpts:t})};let J=0;const N=(e,i,t)=>{const r=e.__state.sharedState.logFns;if(e.__state.localState.suppressLog)return;const a=[t.prepareTime===void 0?"":`prepareTime=${(t.prepareTime/1e3).toFixed(4)}`,t.execTime===void 0?"":`execTime=${(t.execTime/1e3).toFixed(4)}`,t.freeTime===void 0?"":`freeTime=${(t.freeTime/1e3).toFixed(4)}`,t.sendTime===void 0?"":`sendTime=${(t.sendTime/1e3).toFixed(4)}`,t.receiveTime===void 0?"":`receiveTime=${(t.receiveTime/1e3).toFixed(4)}`,t.blockTime===void 0?"":`blockTime=${(t.blockTime/1e3).toFixed(4)}`,`totalTime=${(t.totalTime/1e3).toFixed(4)}`].filter(o=>o.length!==0).join(" ");r.logTrFinish(`%c[${e.__state.sharedState.dbName}][tr_id=${i.slice(0,6)}] Transaction finished with ${a}`)},G=async(e,i,t)=>{const{localState:{transactionState:r},sharedState:{eventsEmitter:a,transactionsStates:o,dbBackend:h,logFns:c}}=e.__state;if(h.isUsualTransactionDisabled)throw new Error("Usual transactions are disabled for this type of backend. Please, use atomic transactions instead.");if(r.current)return await t(e);x(e,()=>"transaction");const l={id:E(),type:"async"};e={...e,__state:{...e.__state,localState:{...e.__state.localState,transactionState:{current:l}}}};const T=v(),s={i:J++,current:l,performance:{prepareTime:0,execTime:0,freeTime:0,sendTime:0,receiveTime:0,totalTime:0,blockTime:0}};o.byId[l.id]=s;try{await a.emit("transactionWillStart",e,l),await F(e,[g.sql`BEGIN ${g.sql.raw(i.toLocaleUpperCase())} TRANSACTION`],{transactionId:l.id,containsTransactionStart:!0,containsTransactionFinish:!1,containsTransactionRollback:!1,rollbackOnFail:!1,isAtomic:!1}),await a.emit("transactionStarted",e,l);try{const u=await t(e);return await a.emit("transactionWillCommit",e,l),await F(e,[g.sql`COMMIT`],{transactionId:l.id,containsTransactionStart:!1,containsTransactionFinish:!0,containsTransactionRollback:!1,rollbackOnFail:!1,isAtomic:!1}),await a.emit("transactionCommitted",e,l),u}catch(u){c.logError("Rollback transaction",u),await a.emit("transactionWillRollback",e,l);try{await F(e,[g.sql`ROLLBACK`],{transactionId:l.id,containsTransactionStart:!1,containsTransactionFinish:!1,containsTransactionRollback:!0,rollbackOnFail:!1,isAtomic:!1})}catch(n){c.logError("Rollback transaction failed",n)}throw await a.emit("transactionRollbacked",e,l),u}}finally{s.performance.totalTime=v()-T,N(e,l.id,s.performance),delete o.byId[l.id]}},K=()=>({__state:{queries:[],afterCommits:[],afterRollbacks:[]},addQuery(e){this.__state.queries.push(e)},afterCommit(e){this.__state.afterCommits.push(e)},afterRollback(e){this.__state.afterRollbacks.push(e)}}),Y=async(e,i,t)=>{const{localState:{transactionState:r},sharedState:{eventsEmitter:a,transactionsStates:o,dbBackend:h,logFns:c}}=e.__state;if(r.current)throw new Error("You are running atomic transaction inside of a transaction. Consider moving atomic transaction call to runAfterTransaction callback.");const{inputQueries:l,afterCommits:T,afterRollbacks:s}=await(async()=>{if(Array.isArray(t))return{inputQueries:t,afterCommits:[],afterRollbacks:[]};{const _=K();return await t(_),{inputQueries:_.__state.queries,afterCommits:_.__state.afterCommits,afterRollbacks:_.__state.afterRollbacks}}})(),u={id:E(),type:"atomic"},n={i:J++,current:u,performance:{prepareTime:0,execTime:0,freeTime:0,sendTime:0,receiveTime:0,totalTime:0,blockTime:0}};e={...e,__state:{...e.__state,localState:{...e.__state.localState,transactionState:{current:u}}}},o.byId[u.id]=n;const d=v(),f=[];h.isAtomicRollbackCommitDisabled||f.push(g.sql`BEGIN ${g.sql.raw(i.toUpperCase())} TRANSACTION`),f.push(...l),h.isAtomicRollbackCommitDisabled||f.push(g.sql`COMMIT`);try{await a.emit("transactionWillStart",e,u),await a.emit("transactionStarted",e,u),await F(e,f,{transactionId:u.id,containsTransactionStart:!0,containsTransactionFinish:!0,containsTransactionRollback:!1,rollbackOnFail:!0,isAtomic:!0}),await a.emit("transactionWillCommit",e,u),await a.emit("transactionCommitted",e,u);try{for(const _ of T)_()}catch(_){c.logError("Error in afterCommit callback",_)}}catch(_){c.logError("Rollback transaction",_),await a.emit("transactionWillRollback",e,u),await a.emit("transactionRollbacked",e,u);try{for(const y of s)y()}catch(y){c.logError("Error in afterRallback callback",y)}throw _}finally{n.performance.totalTime=v()-d,N(e,u.id,n.performance),delete o.byId[u.id]}},L=["yellow","cyan","magenta"],H=async({dbName:e,plugins:i,queriesMiddlewares:t,dbBackend:r,suppressLog:a,logFns:o})=>{const h=o||{logQuery:(n,d)=>{const f=typeof d=="number"?L[d%L.length]:void 0;console.log(...f?[n,`color: ${f}; background-color: #202124; padding: 2px 4px; border-radius: 2px`]:[n])},logError:(n,d)=>{console.error(n,d)},logTrFinish:n=>{console.log(n,"color: #fff; background-color: #1da1f2; padding: 2px 4px; border-radius: 2px")}},c=R("running",{label:"runningState"}),l=(await r)({dbName:e}),T={__state:{sharedState:{clientId:E(),dbBackend:l,dbName:e,runningState:c,eventsEmitter:j(),transactionsStates:{byId:{}},logFns:h},localState:{queriesMiddlewares:t||[],transactionState:{},suppressLog:Boolean(a)}},runInTransaction(n,d){return G(this,(d==null?void 0:d.type)||"deferred",n)},async runInAtomicTransaction(n,d){return await Y(this,(d==null?void 0:d.type)||"deferred",n)},async runQueries(n){return(await F(this,n)).result.map(({rows:f})=>f)},async runQuery(n){return(await this.runQueries([n]))[0]},runAfterTransactionCommitted(n){return q(this,(d,f,_)=>{d==="committed"&&n(f,_)})},runAfterTransactionRollbacked(n){q(T,(d,f,_)=>{d==="rollbacked"&&n(f,_)})}};let s=T;const u=()=>T.__state.sharedState.runningState.value;if(u()!=="running"||(await l.initialize(),u()!=="running"))return T;for(const n of i||[])s=n(s);return await T.__state.sharedState.eventsEmitter.emit("initialized",T),s},X=async e=>{e.__state.sharedState.runningState.value="stopping",await e.__state.sharedState.dbBackend.stop(),e.__state.sharedState.runningState.value="stopped",queueMicrotask(()=>{e.__state.sharedState.runningState.stop()})},D=e=>{const{current:i,queue:t}=e;return`current running job: ${JSON.stringify(i,null,2)}, queue: ${JSON.stringify(t,null,2)}`},Z=()=>R({queue:[],current:void 0},{label:"jobsState"}),Q=async(e,i)=>{const t=i!=null?i:E(),r={id:t},{current:a,queue:o}=e.value;if(a||o.length>0){const h=e.waitTill(c=>{var l;return((l=c.current)==null?void 0:l.id)===t});e.value={queue:[...o,r],current:a};try{await h}catch(c){throw c instanceof k?new k(`Timeout error while job acquire: '${c.message}'. Is it a dead lock? ${D(e.value)}, jobToAcquire: ${JSON.stringify(r,null,2)}`):c}}else e.value={queue:[],current:r};return r},I=(e,i)=>{const{current:t,queue:r}=e.value;if((t==null?void 0:t.id)!==i.id)throw new Error(`Can't release job that is not currently running, ${D(e.value)}, toRelease: ${JSON.stringify(i,null,2)}`);e.value={queue:r.slice(1),current:r[0]}},O=async e=>{try{return e.waitTill(({queue:i,current:t})=>i.length===0&&t===void 0,{timeout:3e4})}catch(i){throw i instanceof k?new k(`Timeout error while awaiting all jobs done: '${i.message}'. Is it a dead lock?`):i}},ee=(e,i)=>i({...e,__state:{...e.__state,localState:{...e.__state.localState,suppressLog:!0}}}),te=e=>({...e,__state:{...e.__state,localState:{...e.__state.localState,suppressLog:!0}}}),ie=async(e,i)=>{let t;return(!i||(i==null?void 0:i.containsTransactionStart))&&(t=await Q(e,i==null?void 0:i.transactionId)),i&&!i.containsTransactionStart&&await e.waitTill(r=>{var a;return((a=r.current)==null?void 0:a.id)===i.transactionId}),t},ae=(e,i,t)=>{i&&(!t||(t==null?void 0:t.containsTransactionFinish)||(t==null?void 0:t.containsTransactionRollback))&&I(e,i),!i&&t&&((t==null?void 0:t.containsTransactionRollback)||(t==null?void 0:t.containsTransactionFinish))&&I(e,{id:t.transactionId})};m.StoppedError=C,m.TimeoutError=k,m.acquireJob=Q,m.acquireWithTrJobOrWait=ie,m.getTime=v,m.initDbClient=H,m.initJobsState=Z,m.makeId=E,m.reactiveVar=R,m.releaseJob=I,m.releaseTrJobIfPossible=ae,m.stopDb=X,m.suppressLog=ee,m.whenAllJobsDone=O,m.withSuppressedLog=te;for(const e in g)e!=="default"&&!m.hasOwnProperty(e)&&Object.defineProperty(m,e,{enumerable:!0,get:()=>g[e]});Object.defineProperties(m,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}); | ||
(function(f,F){typeof exports=="object"&&typeof module<"u"?F(exports,require("fast-equals"),require("@kikko-land/boono-sql")):typeof define=="function"&&define.amd?define(["exports","fast-equals","@kikko-land/boono-sql"],F):(f=typeof globalThis<"u"?globalThis:f||self,F(f.core={},f.fastEquals,f.boonoSql))})(this,function(f,F,v){"use strict";const J=(e,t)=>{if(!e.__state.localState.transactionState.current)throw new Error("Not in transaction.");const a=e.__state.localState.transactionState.current,r=[],i=d=>(h,m)=>{if(a.id===m.id){t(d,h,a);for(const s of r)s()}};r.push(e.__state.sharedState.eventsEmitter.on("transactionCommitted",i("committed"))),r.push(e.__state.sharedState.eventsEmitter.on("transactionRollbacked",i("rollbacked")))};function G(){const e={};return{async emit(t,...a){const r=e[t]||[];for(const i of r)await i(...a)},on(t,a){return(e[t]=e[t]||[]).push(a),()=>{const r=e[t]||[];e[t]=r.filter(i=>i!==a)}}}}class k extends Error{}class x extends Error{}const I=(e,t)=>{const a=t.deduplicate===void 0?!0:t.deduplicate;return{__state:{subscriptions:[],value:e,isStopped:!1,onStop:[]},get isStopped(){return this.__state.isStopped},set value(r){if(this.isStopped)throw new Error(`reactiveVar ${t.label} is stopped!`);if(!(a&&F.deepEqual(this.__state.value,r))){this.__state.value=r;for(const i of this.__state.subscriptions)i(r)}},get value(){if(this.isStopped)throw new Error(`reactiveVar ${t.label} is stopped!`);return this.__state.value},subscribe(r,i=!0){if(this.isStopped)throw new Error(`reactiveVar ${t.label} is stopped!`);let d;const h=m=>{d&&d(),d=r(m)};return this.__state.subscriptions.push(h),i&&h(this.__state.value),()=>{this.__state.subscriptions=this.__state.subscriptions.filter(m=>m!==h)}},waitTill(r,i){const d=new x(`waitUntil for reactiveVar ${t.label} is stopped due to stop signal`),h=new k(`waitUntil for reactiveVar ${t.label} is timed out`),m=new x(`waitUntil for reactiveVar ${t.label} is stopped due to reactive var stop`);if(this.isStopped)throw new Error(`reactiveVar ${t.label} is stopped!`);return new Promise((o,p)=>{var l;const c=[],n=()=>{for(const u of c)u()};if(c.push(((l=i==null?void 0:i.stopIf)==null?void 0:l.subscribe(u=>{!u||(n(),p(d))},!0))||(()=>{})),c.push(this.subscribe(u=>{!r(u)||(n(),o())},!0)),(i==null?void 0:i.timeout)===void 0||typeof(i==null?void 0:i.timeout)=="number"){const u=setTimeout(()=>{n(),p(h)},(i==null?void 0:i.timeout)===void 0?12e4:i.timeout);c.push(()=>{clearTimeout(u)})}this.__state.onStop.push(()=>{n(),p(m)})})},stop(){if(this.isStopped)throw new Error(`reactiveVar ${t.label} is already stopped!`);this.__state.subscriptions=[];for(const r of this.__state.onStop)r();this.__state.isStopped=!0}}},y=typeof performance<"u"?()=>performance.now():()=>Date.now(),Q=(e,t)=>{const{__state:{sharedState:{runningState:a,dbName:r}}}=e;if(a.value!=="running")throw new Error(`Failed to start ${t()}, db ${r} is stopping`)};function C(){let e="";const t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",a=t.length;for(let r=0;r<32;r++)e+=t.charAt(Math.floor(Math.random()*a));return e}const Y=e=>e.filter(t=>t!==null),K=e=>e.reduce((t,a)=>t+a,0),N=e=>K(Y(e)),H=async({db:e,queries:t,transactionOpts:a})=>{var l,u,T,$,B,U,P,j,z;const{localState:{transactionState:r},sharedState:{dbBackend:i,logFns:d},sharedState:h}=e.__state;if(r.current||Q(e,()=>JSON.stringify(t)),a&&((l=r.current)==null?void 0:l.id)!==a.transactionId)throw new Error(`Cannot run queries in a transaction that is not the current one. Transaction opts: ${JSON.stringify(a)}, local transaction: ${JSON.stringify(r)}`);const m=y(),{result:s,performance:o,textQueries:p}=await(async()=>{const _=a||(r.current?{transactionId:r.current.id,containsTransactionStart:!1,containsTransactionFinish:!1,containsTransactionRollback:!1,rollbackOnFail:!1,isAtomic:!1}:void 0);if(t.type==="prepared"){const w=t.query.toSql();if(w._values.length!==0)throw new Error("You can't use prepared var through ${} for runPreparedQuery. Please, manually specify variables with '?'.");const S=w.preparedQuery.text;return{...await i.execPreparedQuery(w.preparedQuery,t.preparedValues,_),textQueries:[S]}}else{const w=t.values.map(S=>S.preparedQuery);return{...await i.execQueries(w,_),textQueries:w.map(S=>S.text)}}})(),c=y();if(!e.__state.localState.suppressLog){const _=(g,R)=>`${g}=${(R/1e3).toFixed(4)}`,w=(()=>{if(t.type==="prepared"){const g=s[0],R=[g.performance.prepareTime!==void 0?_("prepareTime",N(s.map(b=>b.performance.prepareTime))):"",g.performance.execTime!==void 0?_("execTime",N(s.map(b=>b.performance.execTime))):""].filter(b=>b.length!==0).join(" ");return[[p[0].slice(0,1e3),`for ${t.preparedValues.length} values`,R].filter(b=>b.length!==0).join(" ")]}else return s.map(({performance:g},R)=>{const b=[g.prepareTime!==void 0?_("prepareTime",g.prepareTime):"",g.execTime!==void 0?_("execTime",g.execTime):""].filter(q=>q.length!==0).join(" ");return[p[R].slice(0,1e3),b].filter(q=>q.length!==0).join(" ")})})(),S=(()=>w.length===1?w[0]:` | ||
`+w.map(g=>`{${g}}`).join(` | ||
`))(),ce=`%c[${e.__state.sharedState.dbName}] `+[(u=r.current)!=null&&u.id?`[tr_id=${(T=r.current)==null?void 0:T.id.substring(0,6)}]`:"",S,(o==null?void 0:o.sendTime)!==void 0?`sendTime=${(o.sendTime/1e3).toFixed(4)}`:"",(o==null?void 0:o.receiveTime)!==void 0?`receiveTime=${(o.receiveTime/1e3).toFixed(4)}`:"",(o==null?void 0:o.blockTime)!==void 0?`blockTime=${(o.blockTime/1e3).toFixed(4)}`:"",`totalTime=${((c-m)/1e3).toFixed(4)}`].filter(g=>g.length!==0).join(" "),le=(U=h.transactionsStates.byId[(B=($=r.current)==null?void 0:$.id)!=null?B:""])==null?void 0:U.i;d.logQuery(ce,le)}const n=(z=h.transactionsStates.byId[(j=(P=r.current)==null?void 0:P.id)!=null?j:""])==null?void 0:z.performance;return n&&(s.some(_=>_.performance.execTime!==void 0)&&(n.execTime===void 0&&(n.execTime=0),n.execTime+=s.reduce((_,w)=>{var S;return _+((S=w.performance.execTime)!=null?S:0)},0)),s.some(_=>_.performance.prepareTime!==void 0)&&(n.prepareTime===void 0&&(n.prepareTime=0),n.prepareTime+=s.reduce((_,w)=>{var S;return _+((S=w.performance.prepareTime)!=null?S:0)},0)),o.sendTime&&(n.sendTime||(n.sendTime=0),n.sendTime+=o.sendTime),o.receiveTime&&(n.receiveTime||(n.receiveTime=0),n.receiveTime+=o.receiveTime),o.blockTime&&(n.blockTime||(n.blockTime=0),n.blockTime+=o.blockTime)),{db:e,result:s,performance:o,queries:t}},E=async(e,t,a)=>{const r=[...e.__state.localState.queriesMiddlewares,H].reverse();let i=d=>Promise.resolve(d);for(const d of r){const h=i;i=m=>d({...m,next:h})}return await i({db:e,result:[],performance:{sendTime:void 0,receiveTime:void 0,totalTime:0},queries:t,transactionOpts:a})};let L=0;const D=(e,t,a)=>{const r=e.__state.sharedState.logFns;if(e.__state.localState.suppressLog)return;const i=[a.prepareTime===void 0?"":`prepareTime=${(a.prepareTime/1e3).toFixed(4)}`,a.execTime===void 0?"":`execTime=${(a.execTime/1e3).toFixed(4)}`,a.sendTime===void 0?"":`sendTime=${(a.sendTime/1e3).toFixed(4)}`,a.receiveTime===void 0?"":`receiveTime=${(a.receiveTime/1e3).toFixed(4)}`,a.blockTime===void 0?"":`blockTime=${(a.blockTime/1e3).toFixed(4)}`,`totalTime=${(a.totalTime/1e3).toFixed(4)}`].filter(d=>d.length!==0).join(" ");r.logTrFinish(`%c[${e.__state.sharedState.dbName}][tr_id=${t.slice(0,6)}] Transaction finished with ${i}`)},X=async(e,t,a)=>{const{localState:{transactionState:r},sharedState:{eventsEmitter:i,transactionsStates:d,dbBackend:h,logFns:m}}=e.__state;if(h.isUsualTransactionDisabled)throw new Error("Usual transactions are disabled for this type of backend. Please, use atomic transactions instead.");if(r.current)return await a(e);Q(e,()=>"transaction");const s={id:C(),type:"async"};e={...e,__state:{...e.__state,localState:{...e.__state.localState,transactionState:{current:s}}}};const o=y(),p={i:L++,current:s,performance:{prepareTime:0,execTime:0,freeTime:0,sendTime:0,receiveTime:0,totalTime:0,blockTime:0}};d.byId[s.id]=p;try{await i.emit("transactionWillStart",e,s),await E(e,{type:"usual",values:[v.sql`BEGIN ${v.sql.raw(t.toLocaleUpperCase())} TRANSACTION`]},{transactionId:s.id,containsTransactionStart:!0,containsTransactionFinish:!1,containsTransactionRollback:!1,rollbackOnFail:!1,isAtomic:!1}),await i.emit("transactionStarted",e,s);try{const c=await a(e);return await i.emit("transactionWillCommit",e,s),await E(e,{type:"usual",values:[v.sql`COMMIT`]},{transactionId:s.id,containsTransactionStart:!1,containsTransactionFinish:!0,containsTransactionRollback:!1,rollbackOnFail:!1,isAtomic:!1}),await i.emit("transactionCommitted",e,s),c}catch(c){m.logError("Rollback transaction",c),await i.emit("transactionWillRollback",e,s);try{await E(e,{type:"usual",values:[v.sql`ROLLBACK`]},{transactionId:s.id,containsTransactionStart:!1,containsTransactionFinish:!1,containsTransactionRollback:!0,rollbackOnFail:!1,isAtomic:!1})}catch(n){m.logError("Rollback transaction failed",n)}throw await i.emit("transactionRollbacked",e,s),c}}finally{p.performance.totalTime=y()-o,D(e,s.id,p.performance),delete d.byId[s.id]}},Z=()=>({__state:{queries:[],afterCommits:[],afterRollbacks:[]},addQuery(e){this.__state.queries.push(e)},afterCommit(e){this.__state.afterCommits.push(e)},afterRollback(e){this.__state.afterRollbacks.push(e)}}),O=async(e,t,a)=>{const{localState:{transactionState:r},sharedState:{eventsEmitter:i,transactionsStates:d,dbBackend:h,logFns:m}}=e.__state;if(r.current)throw new Error("You are running atomic transaction inside of a transaction. Consider moving atomic transaction call to runAfterTransaction callback.");const{inputQueries:s,afterCommits:o,afterRollbacks:p}=await(async()=>{if(Array.isArray(a))return{inputQueries:a,afterCommits:[],afterRollbacks:[]};{const T=Z();return await a(T),{inputQueries:T.__state.queries,afterCommits:T.__state.afterCommits,afterRollbacks:T.__state.afterRollbacks}}})(),c={id:C(),type:"atomic"},n={i:L++,current:c,performance:{prepareTime:0,execTime:0,freeTime:0,sendTime:0,receiveTime:0,totalTime:0,blockTime:0}};e={...e,__state:{...e.__state,localState:{...e.__state.localState,transactionState:{current:c}}}},d.byId[c.id]=n;const l=y(),u=[];h.isAtomicRollbackCommitDisabled||u.push(v.sql`BEGIN ${v.sql.raw(t.toUpperCase())} TRANSACTION`),u.push(...s.map(T=>T.toSql())),h.isAtomicRollbackCommitDisabled||u.push(v.sql`COMMIT`);try{await i.emit("transactionWillStart",e,c),await i.emit("transactionStarted",e,c),await E(e,{type:"usual",values:u},{transactionId:c.id,containsTransactionStart:!0,containsTransactionFinish:!0,containsTransactionRollback:!1,rollbackOnFail:!0,isAtomic:!0}),await i.emit("transactionWillCommit",e,c),await i.emit("transactionCommitted",e,c);try{for(const T of o)T()}catch(T){m.logError("Error in afterCommit callback",T)}}catch(T){m.logError("Rollback transaction",T),await i.emit("transactionWillRollback",e,c),await i.emit("transactionRollbacked",e,c);try{for(const $ of p)$()}catch($){m.logError("Error in afterRallback callback",$)}throw T}finally{n.performance.totalTime=y()-l,D(e,c.id,n.performance),delete d.byId[c.id]}},M=["yellow","cyan","magenta"],ee=async({dbName:e,plugins:t,queriesMiddlewares:a,dbBackend:r,suppressLog:i,logFns:d})=>{const h=d||{logQuery:(n,l)=>{const u=typeof l=="number"?M[l%M.length]:void 0;console.log(...u?[n,`color: ${u}; background-color: #202124; padding: 2px 4px; border-radius: 2px`]:[n,"padding: 0"])},logError:(n,l)=>{console.error(n,l)},logTrFinish:n=>{console.log(n,"color: #fff; background-color: #1da1f2; padding: 2px 4px; border-radius: 2px")}},m=I("running",{label:"runningState"}),s=(await r)({dbName:e}),o={__state:{sharedState:{clientId:C(),dbBackend:s,dbName:e,runningState:m,eventsEmitter:G(),transactionsStates:{byId:{}},logFns:h},localState:{queriesMiddlewares:a||[],transactionState:{},suppressLog:Boolean(i)}},runInTransaction(n,l){return X(this,(l==null?void 0:l.type)||"deferred",n)},async runInAtomicTransaction(n,l){return await O(this,(l==null?void 0:l.type)||"deferred",n)},async runQueries(n){return(await E(this,{type:"usual",values:n.map(u=>u.toSql())})).result.map(({rows:u})=>u)},async runQuery(n){return(await this.runQueries([n]))[0]},async runPreparedQuery(n,l){return(await E(this,{type:"prepared",query:n,preparedValues:l})).result.map(({rows:T})=>T)},runAfterTransactionCommitted(n){return J(this,(l,u,T)=>{l==="committed"&&n(u,T)})},runAfterTransactionRollbacked(n){J(o,(l,u,T)=>{l==="rollbacked"&&n(u,T)})}};let p=o;const c=()=>o.__state.sharedState.runningState.value;if(c()!=="running"||(await s.initialize(),c()!=="running"))return o;for(const n of t||[])p=n(p);return await o.__state.sharedState.eventsEmitter.emit("initialized",o),p},te=async e=>{e.__state.sharedState.runningState.value="stopping",await e.__state.sharedState.dbBackend.stop(),e.__state.sharedState.runningState.value="stopped",queueMicrotask(()=>{e.__state.sharedState.runningState.stop()})},V=e=>{const{current:t,queue:a}=e;return`current running job: ${JSON.stringify(t,null,2)}, queue: ${JSON.stringify(a,null,2)}`},ae=()=>I({queue:[],current:void 0},{label:"jobsState"}),W=async(e,t)=>{const a=t!=null?t:C(),r={id:a},{current:i,queue:d}=e.value;if(i||d.length>0){const h=e.waitTill(m=>{var s;return((s=m.current)==null?void 0:s.id)===a},{timeout:12e4});e.value={queue:[...d,r],current:i};try{await h}catch(m){throw m instanceof k?new k(`Timeout error while job acquire: '${m.message}'. Is it a dead lock? ${V(e.value)}, jobToAcquire: ${JSON.stringify(r,null,2)}`):m}}else e.value={queue:[],current:r};return r},A=(e,t)=>{const{current:a,queue:r}=e.value;if((a==null?void 0:a.id)!==t.id)throw new Error(`Can't release job that is not currently running, ${V(e.value)}, toRelease: ${JSON.stringify(t,null,2)}`);e.value={queue:r.slice(1),current:r[0]}},ie=async e=>{try{return e.waitTill(({queue:t,current:a})=>t.length===0&&a===void 0,{timeout:12e4})}catch(t){throw t instanceof k?new k(`Timeout error while awaiting all jobs done: '${t.message}'. Is it a dead lock?`):t}},re=(e,t)=>t({...e,__state:{...e.__state,localState:{...e.__state.localState,suppressLog:!0}}}),ne=e=>({...e,__state:{...e.__state,localState:{...e.__state.localState,suppressLog:!0}}}),se=async(e,t)=>{let a;return(!t||(t==null?void 0:t.containsTransactionStart))&&(a=await W(e,t==null?void 0:t.transactionId)),t&&!t.containsTransactionStart&&await e.waitTill(r=>{var i;return((i=r.current)==null?void 0:i.id)===t.transactionId}),a},oe=(e,t,a)=>{t&&(!a||(a==null?void 0:a.containsTransactionFinish)||(a==null?void 0:a.containsTransactionRollback))&&A(e,t),!t&&a&&((a==null?void 0:a.containsTransactionRollback)||(a==null?void 0:a.containsTransactionFinish))&&A(e,{id:a.transactionId})};f.StoppedError=x,f.TimeoutError=k,f.acquireJob=W,f.acquireWithTrJobOrWait=se,f.getTime=y,f.initDbClient=ee,f.initJobsState=ae,f.makeId=C,f.reactiveVar=I,f.releaseJob=A,f.releaseTrJobIfPossible=oe,f.stopDb=te,f.suppressLog=re,f.whenAllJobsDone=ie,f.withSuppressedLog=ne;for(const e in v)e!=="default"&&!f.hasOwnProperty(e)&&Object.defineProperty(f,e,{enumerable:!0,get:()=>v[e]});Object.defineProperties(f,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}); | ||
//# sourceMappingURL=index.umd.js.map |
@@ -1,3 +0,2 @@ | ||
import { ISqlAdapter } from "@kikko-land/boono-sql"; | ||
import { IDb, IQueriesMiddlewareState, ITransactionOpts } from "./types"; | ||
export declare const runQueries: (db: IDb, queries: ISqlAdapter[], transactionOpts?: ITransactionOpts) => Promise<IQueriesMiddlewareState>; | ||
import { IDb, IQueriesMiddlewareState, IQueriesToRun, ITransactionOpts } from "./types"; | ||
export declare const runQueries: (db: IDb, queries: IQueriesToRun, transactionOpts?: ITransactionOpts) => Promise<IQueriesMiddlewareState>; |
@@ -1,2 +0,2 @@ | ||
import { ISqlAdapter } from "@kikko-land/boono-sql"; | ||
import { IPrimitiveValue, ISql, ISqlAdapter } from "@kikko-land/boono-sql"; | ||
import { DeepReadonly } from "ts-essentials"; | ||
@@ -14,3 +14,2 @@ import { INanoEmitter } from "./createNanoEvents"; | ||
prepareTime?: number; | ||
freeTime?: number; | ||
}; | ||
@@ -39,3 +38,3 @@ export declare type IKikkoEvents = { | ||
}; | ||
queries: ISqlAdapter[]; | ||
queries: IQueriesToRun; | ||
transactionOpts?: ITransactionOpts; | ||
@@ -57,2 +56,10 @@ }; | ||
} | ||
export declare type IQueriesToRun = { | ||
type: "usual"; | ||
values: ISql[]; | ||
} | { | ||
type: "prepared"; | ||
query: ISql; | ||
preparedValues: IPrimitiveValue[][]; | ||
}; | ||
export interface IDb { | ||
@@ -71,2 +78,3 @@ __state: { | ||
runQuery<D extends Record<string, unknown>>(query: ISqlAdapter): Promise<D[]>; | ||
runPreparedQuery<D extends Record<string, unknown>>(query: ISql, preparedValues: IPrimitiveValue[][]): Promise<D[][]>; | ||
runAfterTransactionCommitted(func: (db: IDb, transaction: ITransaction) => void): void; | ||
@@ -93,2 +101,3 @@ runAfterTransactionRollbacked(func: (db: IDb, transaction: ITransaction) => void): void; | ||
execQueries(queries: IQuery[], transactionOpts?: ITransactionOpts): Promise<IExecQueriesResult>; | ||
execPreparedQuery(query: IQuery, preparedValues: IPrimitiveValue[][], transactionOpts?: ITransactionOpts): Promise<IExecQueriesResult>; | ||
stop(): Promise<void>; | ||
@@ -100,3 +109,2 @@ }; | ||
export declare type ITransactionPerformance = { | ||
freeTime?: number; | ||
sendTime?: number; | ||
@@ -103,0 +111,0 @@ receiveTime?: number; |
{ | ||
"name": "@kikko-land/kikko", | ||
"version": "0.10.0", | ||
"version": "0.11.0", | ||
"author": "Sergey Popov", | ||
@@ -5,0 +5,0 @@ "license": "MIT", |
@@ -1,2 +0,2 @@ | ||
import { ISqlAdapter } from "@kikko-land/boono-sql"; | ||
import { IPrimitiveValue, ISql, ISqlAdapter } from "@kikko-land/boono-sql"; | ||
@@ -51,3 +51,3 @@ import { runAfterTransaction } from "./afterTransaction"; | ||
] | ||
: [msg]) | ||
: [msg, `padding: 0`]) | ||
); | ||
@@ -110,3 +110,6 @@ }, | ||
): Promise<D[][]> { | ||
const res = await runQueries(this, queries); | ||
const res = await runQueries(this, { | ||
type: "usual", | ||
values: queries.map((q) => q.toSql()), | ||
}); | ||
return res.result.map(({ rows }) => rows) as D[][]; | ||
@@ -119,2 +122,14 @@ }, | ||
}, | ||
async runPreparedQuery<D extends Record<string, unknown>>( | ||
query: ISql, | ||
preparedValues: IPrimitiveValue[][] | ||
): Promise<D[][]> { | ||
const res = await runQueries(this, { | ||
type: "prepared", | ||
query, | ||
preparedValues, | ||
}); | ||
return res.result.map(({ rows }) => rows) as D[][]; | ||
}, | ||
runAfterTransactionCommitted( | ||
@@ -121,0 +136,0 @@ func: (db: IDb, transaction: ITransaction) => void |
@@ -48,3 +48,5 @@ import { DeepReadonly } from "ts-essentials"; | ||
if (current || queue.length > 0) { | ||
const promise = jobsState.waitTill((newVal) => newVal.current?.id === id); | ||
const promise = jobsState.waitTill((newVal) => newVal.current?.id === id, { | ||
timeout: 120_000, | ||
}); | ||
@@ -99,3 +101,3 @@ jobsState.value = { | ||
({ queue, current }) => queue.length === 0 && current === undefined, | ||
{ timeout: 30_000 } | ||
{ timeout: 120_000 } | ||
); | ||
@@ -102,0 +104,0 @@ } catch (e) { |
@@ -151,3 +151,3 @@ import { deepEqual } from "fast-equals"; | ||
}, | ||
opts?.timeout === undefined ? 60_000 : opts.timeout | ||
opts?.timeout === undefined ? 120_000 : opts.timeout | ||
); | ||
@@ -154,0 +154,0 @@ |
@@ -1,3 +0,1 @@ | ||
import { ISqlAdapter } from "@kikko-land/boono-sql"; | ||
import { getTime } from "./measurePerformance"; | ||
@@ -9,7 +7,13 @@ import { | ||
IQueriesMiddlewareState, | ||
IQueriesToRun, | ||
ITransactionOpts, | ||
} from "./types"; | ||
import { assureDbIsRunning, unwrapQueries } from "./utils"; | ||
import { assureDbIsRunning } from "./utils"; | ||
const colors = ["yellow", "cyan", "magenta"]; | ||
const compact = <T>(arr: (T | null | undefined)[]) => | ||
arr.filter((element): element is T => { | ||
return element !== null; | ||
}); | ||
const sum = (arr: number[]) => arr.reduce((partialSum, a) => partialSum + a, 0); | ||
const compactAndSum = (arr: (number | null | undefined)[]) => sum(compact(arr)); | ||
@@ -42,8 +46,9 @@ const runQueriesMiddleware: IQueriesMiddleware = async ({ | ||
const unwrappedQueries = unwrapQueries(queries.map((q) => q.toSql())); | ||
const startedAt = getTime(); | ||
const { result, performance: qPerformance } = await dbBackend.execQueries( | ||
unwrappedQueries, | ||
transactionOpts | ||
const { | ||
result, | ||
performance: qPerformance, | ||
textQueries, | ||
} = await (async () => { | ||
const opts = transactionOpts | ||
? transactionOpts | ||
@@ -59,27 +64,86 @@ : transactionsLocalState.current | ||
} | ||
: undefined | ||
); | ||
: undefined; | ||
if (queries.type === "prepared") { | ||
const q = queries.query.toSql(); | ||
if (q._values.length !== 0) { | ||
throw new Error( | ||
"You can't use prepared var through ${} for runPreparedQuery. Please, manually specify variables with '?'." | ||
); | ||
} | ||
const toExec = q.preparedQuery.text; | ||
return { | ||
...(await dbBackend.execPreparedQuery( | ||
q.preparedQuery, | ||
queries.preparedValues, | ||
opts | ||
)), | ||
textQueries: [toExec], | ||
}; | ||
} else { | ||
const toExec = queries.values.map((q) => q.preparedQuery); | ||
return { | ||
...(await dbBackend.execQueries(toExec, opts)), | ||
textQueries: toExec.map((q) => q.text), | ||
}; | ||
} | ||
})(); | ||
const endedAt = getTime(); | ||
if (!db.__state.localState.suppressLog) { | ||
const queriesTimings = result.map(({ performance }, i) => { | ||
const times = [ | ||
performance.prepareTime !== undefined | ||
? `prepareTime=${(performance.prepareTime / 1000).toFixed(4)}` | ||
: "", | ||
performance.execTime !== undefined | ||
? `execTime=${(performance.execTime / 1000).toFixed(4)}` | ||
: "", | ||
performance.freeTime !== undefined | ||
? `freeTime=${(performance.freeTime / 1000).toFixed(4)}` | ||
: "", | ||
] | ||
.filter((t) => t.length !== 0) | ||
.join(" "); | ||
const formatTime = (name: string, time: number) => { | ||
return `${name}=${(time / 1000).toFixed(4)}`; | ||
}; | ||
return [unwrappedQueries[i].text.slice(0, 1000), times] | ||
.filter((v) => v.length !== 0) | ||
.join(" "); | ||
}); | ||
const queriesTimings = (() => { | ||
if (queries.type === "prepared") { | ||
const firstResult = result[0]; | ||
const times = [ | ||
firstResult.performance.prepareTime !== undefined | ||
? formatTime( | ||
"prepareTime", | ||
compactAndSum(result.map((r) => r.performance.prepareTime)) | ||
) | ||
: "", | ||
firstResult.performance.execTime !== undefined | ||
? formatTime( | ||
"execTime", | ||
compactAndSum(result.map((r) => r.performance.execTime)) | ||
) | ||
: "", | ||
] | ||
.filter((t) => t.length !== 0) | ||
.join(" "); | ||
return [ | ||
[ | ||
textQueries[0].slice(0, 1000), | ||
`for ${queries.preparedValues.length} values`, | ||
times, | ||
] | ||
.filter((v) => v.length !== 0) | ||
.join(" "), | ||
]; | ||
} else { | ||
return result.map(({ performance }, i) => { | ||
const times = [ | ||
performance.prepareTime !== undefined | ||
? formatTime("prepareTime", performance.prepareTime) | ||
: "", | ||
performance.execTime !== undefined | ||
? formatTime("execTime", performance.execTime) | ||
: "", | ||
] | ||
.filter((t) => t.length !== 0) | ||
.join(" "); | ||
return [textQueries[i].slice(0, 1000), times] | ||
.filter((v) => v.length !== 0) | ||
.join(" "); | ||
}); | ||
} | ||
})(); | ||
const resultStr = (() => { | ||
@@ -139,13 +203,2 @@ if (queriesTimings.length === 1) { | ||
if (result.some((d) => d.performance.freeTime !== undefined)) { | ||
if (perfData.freeTime === undefined) { | ||
perfData.freeTime = 0; | ||
} | ||
perfData.freeTime += result.reduce( | ||
(partialSum, a) => partialSum + (a.performance.freeTime ?? 0), | ||
0 | ||
); | ||
} | ||
if (result.some((d) => d.performance.prepareTime !== undefined)) { | ||
@@ -192,3 +245,3 @@ if (perfData.prepareTime === undefined) { | ||
db: IDb, | ||
queries: ISqlAdapter[], | ||
queries: IQueriesToRun, | ||
transactionOpts?: ITransactionOpts | ||
@@ -218,5 +271,5 @@ ) => { | ||
}, | ||
queries: queries.map((q) => q.toSql()), | ||
queries, | ||
transactionOpts: transactionOpts, | ||
}); | ||
}; |
@@ -1,2 +0,2 @@ | ||
import { ISqlAdapter, sql } from "@kikko-land/boono-sql"; | ||
import { ISql, ISqlAdapter, sql } from "@kikko-land/boono-sql"; | ||
@@ -31,5 +31,2 @@ import { getTime } from "./measurePerformance"; | ||
: `execTime=${(performance.execTime / 1000).toFixed(4)}`, | ||
performance.freeTime === undefined | ||
? "" | ||
: `freeTime=${(performance.freeTime / 1000).toFixed(4)}`, | ||
performance.sendTime === undefined | ||
@@ -121,4 +118,12 @@ ? "" | ||
db, | ||
[sql`BEGIN ${sql.raw(transactionType.toLocaleUpperCase())} TRANSACTION`], | ||
{ | ||
type: "usual", | ||
values: [ | ||
sql`BEGIN ${sql.raw( | ||
transactionType.toLocaleUpperCase() | ||
)} TRANSACTION`, | ||
], | ||
}, | ||
{ | ||
transactionId: transaction.id, | ||
@@ -140,10 +145,14 @@ containsTransactionStart: true, | ||
await runQueries(db, [sql`COMMIT`], { | ||
transactionId: transaction.id, | ||
containsTransactionStart: false, | ||
containsTransactionFinish: true, | ||
containsTransactionRollback: false, | ||
rollbackOnFail: false, | ||
isAtomic: false, | ||
}); | ||
await runQueries( | ||
db, | ||
{ type: "usual", values: [sql`COMMIT`] }, | ||
{ | ||
transactionId: transaction.id, | ||
containsTransactionStart: false, | ||
containsTransactionFinish: true, | ||
containsTransactionRollback: false, | ||
rollbackOnFail: false, | ||
isAtomic: false, | ||
} | ||
); | ||
@@ -159,10 +168,14 @@ await eventsEmitter.emit("transactionCommitted", db, transaction); | ||
try { | ||
await runQueries(db, [sql`ROLLBACK`], { | ||
transactionId: transaction.id, | ||
containsTransactionStart: false, | ||
containsTransactionFinish: false, | ||
containsTransactionRollback: true, | ||
rollbackOnFail: false, | ||
isAtomic: false, | ||
}); | ||
await runQueries( | ||
db, | ||
{ type: "usual", values: [sql`ROLLBACK`] }, | ||
{ | ||
transactionId: transaction.id, | ||
containsTransactionStart: false, | ||
containsTransactionFinish: false, | ||
containsTransactionRollback: true, | ||
rollbackOnFail: false, | ||
isAtomic: false, | ||
} | ||
); | ||
} catch (e) { | ||
@@ -273,3 +286,3 @@ logFns.logError("Rollback transaction failed", e); | ||
const q: ISqlAdapter[] = []; | ||
const q: ISql[] = []; | ||
@@ -280,3 +293,3 @@ if (!dbBackend.isAtomicRollbackCommitDisabled) { | ||
q.push(...inputQueries); | ||
q.push(...inputQueries.map((q) => q.toSql())); | ||
@@ -291,10 +304,14 @@ if (!dbBackend.isAtomicRollbackCommitDisabled) { | ||
await runQueries(db, q, { | ||
transactionId: transaction.id, | ||
containsTransactionStart: true, | ||
containsTransactionFinish: true, | ||
containsTransactionRollback: false, | ||
rollbackOnFail: true, | ||
isAtomic: true, | ||
}); | ||
await runQueries( | ||
db, | ||
{ type: "usual", values: q }, | ||
{ | ||
transactionId: transaction.id, | ||
containsTransactionStart: true, | ||
containsTransactionFinish: true, | ||
containsTransactionRollback: false, | ||
rollbackOnFail: true, | ||
isAtomic: true, | ||
} | ||
); | ||
@@ -301,0 +318,0 @@ await eventsEmitter.emit("transactionWillCommit", db, transaction); |
@@ -1,2 +0,2 @@ | ||
import { ISqlAdapter } from "@kikko-land/boono-sql"; | ||
import { IPrimitiveValue, ISql, ISqlAdapter } from "@kikko-land/boono-sql"; | ||
import { DeepReadonly } from "ts-essentials"; | ||
@@ -17,3 +17,2 @@ | ||
prepareTime?: number; | ||
freeTime?: number; | ||
}; | ||
@@ -61,3 +60,3 @@ | ||
performance: ICmdPerformance & { unwrapQueriesTime?: number }; | ||
queries: ISqlAdapter[]; | ||
queries: IQueriesToRun; | ||
transactionOpts?: ITransactionOpts; | ||
@@ -87,2 +86,6 @@ }; | ||
export type IQueriesToRun = | ||
| { type: "usual"; values: ISql[] } | ||
| { type: "prepared"; query: ISql; preparedValues: IPrimitiveValue[][] }; | ||
export interface IDb { | ||
@@ -111,2 +114,6 @@ __state: { | ||
runQuery<D extends Record<string, unknown>>(query: ISqlAdapter): Promise<D[]>; | ||
runPreparedQuery<D extends Record<string, unknown>>( | ||
query: ISql, | ||
preparedValues: IPrimitiveValue[][] | ||
): Promise<D[][]>; | ||
@@ -141,2 +148,7 @@ runAfterTransactionCommitted( | ||
): Promise<IExecQueriesResult>; | ||
execPreparedQuery( | ||
query: IQuery, | ||
preparedValues: IPrimitiveValue[][], | ||
transactionOpts?: ITransactionOpts | ||
): Promise<IExecQueriesResult>; | ||
stop(): Promise<void>; | ||
@@ -147,3 +159,2 @@ }; | ||
export type ITransactionPerformance = { | ||
freeTime?: number; | ||
sendTime?: number; | ||
@@ -150,0 +161,0 @@ receiveTime?: number; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
197131
2318