@morlay/session-rdb 0.1.1 → 0.1.3
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/README.md +17 -166
- package/dist/artifact.d.mts +2 -2
- package/dist/artifact.mjs +3 -2
- package/dist/{branch-D4nVzQQM.mjs → branch-aiXPmnKC.mjs} +1 -8
- package/dist/deletion.d.mts +3 -4
- package/dist/deletion.mjs +2 -1
- package/dist/export.d.mts +3 -5
- package/dist/export.mjs +1 -4
- package/dist/gc.d.mts +3 -5
- package/dist/gc.mjs +1 -3
- package/dist/import.d.mts +7 -8
- package/dist/import.mjs +2 -7
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +4 -3
- package/dist/invariant.d.mts +4 -5
- package/dist/{log-BWVFYAh5.mjs → log-DYxdjJ-l.mjs} +1 -52
- package/dist/{log-CUjKQbOR.d.mts → log-DYyxRh7j.d.mts} +2216 -294
- package/dist/rolldown-runtime-EAsCxrDo.mjs +14 -0
- package/dist/routes-DGBlBE_I.mjs +10 -0
- package/dist/{sqlite-SCiSnwaz.mjs → sqlite-YCr2-Fov.mjs} +24 -62
- package/dist/{src-BZ1tffd5.mjs → src-BmogreEz.mjs} +59 -97
- package/dist/storage.d.mts +6 -26
- package/dist/storage.mjs +1 -1
- package/dist/testing.d.mts +7 -7
- package/dist/testing.mjs +2 -4
- package/dist/usage.d.mts +1 -1
- package/dist/usage.mjs +1 -17
- package/package.json +2 -2
- package/src/backend.ts +35 -54
- package/src/branch.ts +3 -5
- package/src/deletion.ts +2 -1
- package/src/entities/v3/event-usage.ts +3 -6
- package/src/entities/v3/session-counts.ts +3 -5
- package/src/entities/v3/session-usage.ts +3 -5
- package/src/export.ts +5 -4
- package/src/gc.ts +4 -3
- package/src/import.ts +5 -6
- package/src/index.ts +47 -45
- package/src/legacy.ts +3 -5
- package/src/log.ts +28 -53
- package/src/postgres.ts +70 -61
- package/src/routes.ts +16 -0
- package/src/rows.ts +11 -15
- package/src/session-query.ts +3 -7
- package/src/sqlite.ts +70 -58
- package/src/storage-takeover/projection-cache.ts +6 -8
- package/src/storage-takeover/repository.ts +2 -2
- package/src/storage-takeover/types.ts +1 -1
- package/src/usage.ts +22 -34
- package/src/write-guard.ts +1 -1
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//#region \0rolldown/runtime.js
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
|
|
4
|
+
var __exportAll = (all, no_symbols) => {
|
|
5
|
+
let target = {};
|
|
6
|
+
for (var name in all) __defProp(target, name, {
|
|
7
|
+
get: all[name],
|
|
8
|
+
enumerable: true
|
|
9
|
+
});
|
|
10
|
+
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
11
|
+
return target;
|
|
12
|
+
};
|
|
13
|
+
//#endregion
|
|
14
|
+
export { __exportAll as n, __commonJSMin as t };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
//#region src/routes.ts
|
|
2
|
+
const MORLAY_SESSION_API_PREFIX = "/api/morlay/v1/session";
|
|
3
|
+
const SESSION_ROWS_PATH = `${MORLAY_SESSION_API_PREFIX}/rows`;
|
|
4
|
+
const SESSION_EXPORT_PATH = `${MORLAY_SESSION_API_PREFIX}/export`;
|
|
5
|
+
const SESSION_IMPORT_PATH = `${MORLAY_SESSION_API_PREFIX}/import`;
|
|
6
|
+
const SESSION_DELETE_PATH = `${MORLAY_SESSION_API_PREFIX}/delete`;
|
|
7
|
+
const SESSION_GC_PATH = `${MORLAY_SESSION_API_PREFIX}/gc`;
|
|
8
|
+
const SESSION_USAGE_PATH = `${MORLAY_SESSION_API_PREFIX}/usage`;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { SESSION_ROWS_PATH as a, SESSION_IMPORT_PATH as i, SESSION_EXPORT_PATH as n, SESSION_USAGE_PATH as o, SESSION_GC_PATH as r, SESSION_DELETE_PATH as t };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { COUNTED_EVENT_TYPES, addActivityTotals, addTokenTotals, addTotals, emptyTotals, localDayKey } from "./usage.mjs";
|
|
2
|
-
import { _ as sessionConflictRow, b as titleOfEventData, v as sessionInsertRow } from "./log-
|
|
2
|
+
import { _ as sessionConflictRow, b as titleOfEventData, v as sessionInsertRow } from "./log-DYxdjJ-l.mjs";
|
|
3
3
|
import { randomUUID } from "node:crypto";
|
|
4
4
|
import { SESSION_FORMAT_VERSION, SessionId, SessionLogOffset, SessionSeq } from "@deepseek-ai/dsh-session";
|
|
5
5
|
import { and, desc, eq, gte, inArray, isNotNull, lt, notInArray, sql } from "drizzle-orm";
|
|
@@ -17,7 +17,6 @@ var WriteGuard = class {
|
|
|
17
17
|
confirmHead(id, head) {
|
|
18
18
|
this.headSeqs.set(id, head);
|
|
19
19
|
}
|
|
20
|
-
/** 本实例有没有这条会话的 head 记录(迁移重写用它决定是"登记基准"还是"严格比较")。 */
|
|
21
20
|
has(id) {
|
|
22
21
|
return this.headSeqs.has(id);
|
|
23
22
|
}
|
|
@@ -452,12 +451,6 @@ const sessionProjcacheRows = {
|
|
|
452
451
|
};
|
|
453
452
|
//#endregion
|
|
454
453
|
//#region src/entities/v3/event-usage.ts
|
|
455
|
-
/**
|
|
456
|
-
* 用量日志:一条 `assistant/message` 事件一行(按事件行唯一,fork 共享行不重复)。
|
|
457
|
-
* 读侧维度全部物化在行上——本地日、是否被会话引用、是否被子代理会话引用——统计因此不做
|
|
458
|
-
* `EXISTS` 判定、也不回连事件表;事件行本身仍留在 `t_events`。
|
|
459
|
-
* 取舍见 ADR-统计衍生表物化归属与汇总。
|
|
460
|
-
*/
|
|
461
454
|
const eventUsage = {
|
|
462
455
|
name: "t_event_usage",
|
|
463
456
|
columns: {
|
|
@@ -520,11 +513,6 @@ const eventUsage = {
|
|
|
520
513
|
};
|
|
521
514
|
//#endregion
|
|
522
515
|
//#region src/entities/v3/session-usage.ts
|
|
523
|
-
/**
|
|
524
|
-
* 会话 × 本地日 × 模型的 token 汇总(派生统计表):**按会话的行**读它,因此保住
|
|
525
|
-
* 「fork 子会话含继承前缀」的口径(各会话行之和 ≥ 总量)而不回连事件表。
|
|
526
|
-
* 旁路累加、可按会话重建,读侧只读;取舍见 ADR-统计衍生表物化归属与汇总。
|
|
527
|
-
*/
|
|
528
516
|
const sessionUsage = {
|
|
529
517
|
name: "t_session_usage",
|
|
530
518
|
columns: {
|
|
@@ -586,11 +574,6 @@ const sessionUsage = {
|
|
|
586
574
|
};
|
|
587
575
|
//#endregion
|
|
588
576
|
//#region src/entities/v3/session-counts.ts
|
|
589
|
-
/**
|
|
590
|
-
* 会话 × 本地日的活动计数(派生统计表):轮次 / 步骤 / 用户输入 / 工具调用四列直接读,
|
|
591
|
-
* 不再存事件类型、也不在读取时折。旁路累加、可按会话重建,读侧只读;
|
|
592
|
-
* 取舍见 ADR-统计衍生表物化归属与汇总。
|
|
593
|
-
*/
|
|
594
577
|
const sessionCounts = {
|
|
595
578
|
name: "t_session_counts",
|
|
596
579
|
columns: {
|
|
@@ -1096,22 +1079,16 @@ function createStorageRepository(host) {
|
|
|
1096
1079
|
}
|
|
1097
1080
|
//#endregion
|
|
1098
1081
|
//#region src/sqlite.ts
|
|
1099
|
-
/** 用量行的「被引用」物化表达式(`%EVENT%` 换成事件 id 列)。 */
|
|
1100
1082
|
const EVENT_REFERENCED_SQL = `EXISTS (SELECT 1 FROM t_session_events rb
|
|
1101
1083
|
WHERE rb.f_event_id = %EVENT%)`;
|
|
1102
|
-
/** 用量行的「被 subagent 会话引用」物化表达式(`%EVENT%` 换成事件 id 列)。 */
|
|
1103
1084
|
const EVENT_SUBAGENT_SQL = `EXISTS (SELECT 1 FROM t_session_events sb
|
|
1104
1085
|
JOIN t_sessions ss ON ss.f_session_id = sb.f_session_id
|
|
1105
1086
|
WHERE sb.f_event_id = %EVENT% AND ss.f_origin = 'subagent')`;
|
|
1106
|
-
/** `IN (...)` 用的类型字面量(与 `COUNTED_EVENT_TYPES` 同源)。 */
|
|
1107
1087
|
const COUNTED_EVENT_TYPE_SQL = COUNTED_EVENT_TYPES.map((type) => `'${type}'`).join(", ");
|
|
1088
|
+
const REFRESH_FLAG_CHUNK = 400;
|
|
1108
1089
|
function withEvent(expression, column) {
|
|
1109
1090
|
return expression.replace("%EVENT%", column);
|
|
1110
1091
|
}
|
|
1111
|
-
/**
|
|
1112
|
-
* 派生统计表的回填:任一表为空即按事件表全量重算(幂等;迁移删表重建后、手动清空后都靠它自愈)。
|
|
1113
|
-
* 顺序有依赖:用量行(带物化列)先落,两张会话汇总表再从它 / 事件表重算。
|
|
1114
|
-
*/
|
|
1115
1092
|
function backfillUsageTables(db) {
|
|
1116
1093
|
backfillEventUsage(db);
|
|
1117
1094
|
backfillSessionUsage(db);
|
|
@@ -1120,7 +1097,6 @@ function backfillUsageTables(db) {
|
|
|
1120
1097
|
function tableIsEmpty(db, table) {
|
|
1121
1098
|
return db.prepare(`SELECT count(*) AS n FROM ${table}`).get().n === 0;
|
|
1122
1099
|
}
|
|
1123
|
-
/** 用量行:一条 `assistant/message` 事件行一行,物化本地日与两个归属标记。 */
|
|
1124
1100
|
function backfillEventUsage(db) {
|
|
1125
1101
|
if (!tableIsEmpty(db, "t_event_usage")) return;
|
|
1126
1102
|
db.exec(`INSERT OR IGNORE INTO t_event_usage (
|
|
@@ -1149,7 +1125,6 @@ function backfillEventUsage(db) {
|
|
|
1149
1125
|
AND (json_extract(e.f_data, '$.data.usage') IS NOT NULL
|
|
1150
1126
|
OR json_extract(e.f_data, '$.usage') IS NOT NULL)`);
|
|
1151
1127
|
}
|
|
1152
|
-
/** 会话 × 本地日 × 模型的 token 汇总:从桥接行 × 用量行重算(含 fork 继承前缀)。 */
|
|
1153
1128
|
function backfillSessionUsage(db) {
|
|
1154
1129
|
if (!tableIsEmpty(db, "t_session_usage")) return;
|
|
1155
1130
|
db.exec(`INSERT OR IGNORE INTO t_session_usage (
|
|
@@ -1162,7 +1137,6 @@ function backfillSessionUsage(db) {
|
|
|
1162
1137
|
JOIN t_event_usage u ON u.f_event_id = b.f_event_id
|
|
1163
1138
|
GROUP BY b.f_session_id, u.f_day, coalesce(u.f_provider, ''), coalesce(u.f_model, '')`);
|
|
1164
1139
|
}
|
|
1165
|
-
/** 会话 × 本地日的活动计数:从桥接行 × 事件类型重算。 */
|
|
1166
1140
|
function backfillSessionCounts(db) {
|
|
1167
1141
|
if (!tableIsEmpty(db, "t_session_counts")) return;
|
|
1168
1142
|
db.exec(`INSERT OR IGNORE INTO t_session_counts (
|
|
@@ -1191,7 +1165,6 @@ function sessionListRowOf(row) {
|
|
|
1191
1165
|
workspace: typeof row["workspace"] === "string" ? row["workspace"] : null
|
|
1192
1166
|
};
|
|
1193
1167
|
}
|
|
1194
|
-
/** SQL 的缺失求和是 NULL:没有 usage 字段的行使该字段计 0。 */
|
|
1195
1168
|
function tokenTotalsOf(row) {
|
|
1196
1169
|
return {
|
|
1197
1170
|
inputTokens: row.input_tokens ?? 0,
|
|
@@ -1201,7 +1174,6 @@ function tokenTotalsOf(row) {
|
|
|
1201
1174
|
totalTokens: row.total_tokens ?? 0
|
|
1202
1175
|
};
|
|
1203
1176
|
}
|
|
1204
|
-
/** `t_session_counts` 的原始行(列名是 SQL 别名)折成四项活动计数。 */
|
|
1205
1177
|
function activityTotalsOf(row) {
|
|
1206
1178
|
return {
|
|
1207
1179
|
turns: row.turns ?? 0,
|
|
@@ -1210,7 +1182,6 @@ function activityTotalsOf(row) {
|
|
|
1210
1182
|
toolCalls: row.tool_calls ?? 0
|
|
1211
1183
|
};
|
|
1212
1184
|
}
|
|
1213
|
-
/** 一行的整套指标:token 用量 + 活动计数(轮次 / 步骤 / 用户输入 / 工具调用)。 */
|
|
1214
1185
|
function emptyActivity() {
|
|
1215
1186
|
return {
|
|
1216
1187
|
turns: 0,
|
|
@@ -1219,7 +1190,6 @@ function emptyActivity() {
|
|
|
1219
1190
|
toolCalls: 0
|
|
1220
1191
|
};
|
|
1221
1192
|
}
|
|
1222
|
-
/** 有 token 用量的会话:活动计数与列表都限定在这一批会话里,口径一致(读汇总表,几百行)。 */
|
|
1223
1193
|
function hasUsageSession(column) {
|
|
1224
1194
|
return `EXISTS (SELECT 1 FROM t_session_usage ub WHERE ub.f_session_id = ${column})`;
|
|
1225
1195
|
}
|
|
@@ -1482,7 +1452,7 @@ var SqliteBackend = class SqliteBackend {
|
|
|
1482
1452
|
}).where(eq(tSessions.fSessionId, id)).run();
|
|
1483
1453
|
}
|
|
1484
1454
|
async deleteBridgeTail(id, fromSequence) {
|
|
1485
|
-
this.db.
|
|
1455
|
+
return this.db.$client.prepare("DELETE FROM t_session_events WHERE f_session_id = ? AND f_sequence >= ? RETURNING f_event_id").all(id, fromSequence).map((row) => row.f_event_id);
|
|
1486
1456
|
}
|
|
1487
1457
|
async getPrevBridge(id, sequence) {
|
|
1488
1458
|
return this.db.select({
|
|
@@ -1491,19 +1461,18 @@ var SqliteBackend = class SqliteBackend {
|
|
|
1491
1461
|
}).from(tSessionEvents).where(and(eq(tSessionEvents.fSessionId, id), eq(tSessionEvents.fSequence, sequence))).get();
|
|
1492
1462
|
}
|
|
1493
1463
|
async deleteSession(id) {
|
|
1494
|
-
this.db.
|
|
1464
|
+
const rows = this.db.$client.prepare("DELETE FROM t_session_events WHERE f_session_id = ? RETURNING f_event_id").all(id);
|
|
1495
1465
|
this.db.delete(tWorkspaceSessions).where(eq(tWorkspaceSessions.fSessionId, id)).run();
|
|
1496
1466
|
this.db.delete(tSessionProjcacheRows).where(eq(tSessionProjcacheRows.fSessionId, id)).run();
|
|
1497
1467
|
this.db.delete(tSessions).where(eq(tSessions.fSessionId, id)).run();
|
|
1468
|
+
return rows.map((row) => row.f_event_id);
|
|
1498
1469
|
}
|
|
1499
|
-
/** 事件行可能被多个会话共享(fork 派生),所以孤儿只能在全库范围内判定。 */
|
|
1500
1470
|
async collectOrphans() {
|
|
1501
1471
|
const referenced = this.db.select({ fEventId: tSessionEvents.fEventId }).from(tSessionEvents);
|
|
1502
1472
|
const info = this.db.delete(tEvents).where(notInArray(tEvents.fEventId, referenced)).run();
|
|
1503
1473
|
this.db.delete(tEventUsage).where(notInArray(tEventUsage.fEventId, this.db.select({ fEventId: tEvents.fEventId }).from(tEvents))).run();
|
|
1504
1474
|
return Number(info.changes);
|
|
1505
1475
|
}
|
|
1506
|
-
/** 父会话被删后留下的 subagent 会话:父已不在表里,或本来就没有父。 */
|
|
1507
1476
|
async listOrphanSubagentSessions() {
|
|
1508
1477
|
return this.db.$client.prepare(`SELECT f_session_id AS id FROM t_sessions
|
|
1509
1478
|
WHERE f_origin = 'subagent'
|
|
@@ -1511,18 +1480,20 @@ var SqliteBackend = class SqliteBackend {
|
|
|
1511
1480
|
OR f_parent_session NOT IN (SELECT f_session_id FROM t_sessions))`).all().map((row) => row.id);
|
|
1512
1481
|
}
|
|
1513
1482
|
async deleteSessions(ids) {
|
|
1514
|
-
if (ids.length === 0) return
|
|
1515
|
-
|
|
1483
|
+
if (ids.length === 0) return {
|
|
1484
|
+
deleted: 0,
|
|
1485
|
+
eventIds: []
|
|
1486
|
+
};
|
|
1487
|
+
const placeholders = ids.map(() => "?").join(", ");
|
|
1488
|
+
const rows = this.db.$client.prepare(`DELETE FROM t_session_events WHERE f_session_id IN (${placeholders}) RETURNING f_event_id`).all(...ids);
|
|
1516
1489
|
this.db.delete(tWorkspaceSessions).where(inArray(tWorkspaceSessions.fSessionId, ids)).run();
|
|
1517
1490
|
this.db.delete(tSessionProjcacheRows).where(inArray(tSessionProjcacheRows.fSessionId, ids)).run();
|
|
1518
1491
|
const info = this.db.delete(tSessions).where(inArray(tSessions.fSessionId, ids)).run();
|
|
1519
|
-
return
|
|
1492
|
+
return {
|
|
1493
|
+
deleted: Number(info.changes),
|
|
1494
|
+
eventIds: rows.map((row) => row.f_event_id)
|
|
1495
|
+
};
|
|
1520
1496
|
}
|
|
1521
|
-
/**
|
|
1522
|
-
* 用量聚合:token 用量沿 `t_event_usage` 的用量行,活动计数(轮次 / 步骤 / 用户输入 / 工具调用)
|
|
1523
|
-
* 沿 `t_events` 的事件类型数——两者限定在**有 token 用量的会话**里,时间范围各自按自己的
|
|
1524
|
-
* `f_created_at`(同一时刻写入,口径一致)。
|
|
1525
|
-
*/
|
|
1526
1497
|
async listSessionRows(query = {}) {
|
|
1527
1498
|
const needle = query.query?.trim().toLowerCase() ?? "";
|
|
1528
1499
|
const like = `%${needle}%`;
|
|
@@ -1562,12 +1533,6 @@ var SqliteBackend = class SqliteBackend {
|
|
|
1562
1533
|
total: Number(counted.n)
|
|
1563
1534
|
};
|
|
1564
1535
|
}
|
|
1565
|
-
/**
|
|
1566
|
-
* 用量聚合:只读三张派生统计表——事件级用量行给去重口径的总量与「天 × 模型」桶,
|
|
1567
|
-
* `t_session_usage` / `t_session_counts` 给按会话的行(含 fork 继承前缀)。
|
|
1568
|
-
* 归属、本地日与「是否被引用」都是物化列,这里不再现算、也不回连事件表。
|
|
1569
|
-
* 事件级按毫秒时间戳过滤、汇总表按本地日过滤——`sinceMs` 对齐到本地零点时两者等价。
|
|
1570
|
-
*/
|
|
1571
1536
|
async usageReport(sinceMs) {
|
|
1572
1537
|
const usageSince = sinceMs === void 0 ? "" : " AND f_created_at >= ?";
|
|
1573
1538
|
const params = sinceMs === void 0 ? [] : [sinceMs];
|
|
@@ -1653,7 +1618,6 @@ var SqliteBackend = class SqliteBackend {
|
|
|
1653
1618
|
}))
|
|
1654
1619
|
};
|
|
1655
1620
|
}
|
|
1656
|
-
/** token 用量旁路累加:派生表 `t_session_usage`,不在写事务里(失败可丢,表可销毁重建)。 */
|
|
1657
1621
|
async incrementSessionUsage(id, buckets) {
|
|
1658
1622
|
if (buckets.length === 0) return;
|
|
1659
1623
|
const statement = this.db.$client.prepare(`INSERT INTO t_session_usage (f_session_id, f_day, f_provider, f_model,
|
|
@@ -1667,7 +1631,6 @@ var SqliteBackend = class SqliteBackend {
|
|
|
1667
1631
|
f_total_tokens = f_total_tokens + excluded.f_total_tokens`);
|
|
1668
1632
|
for (const bucket of buckets) statement.run(id, bucket.day, bucket.provider ?? "", bucket.model ?? "", bucket.inputTokens, bucket.outputTokens, bucket.cacheReadTokens, bucket.reasoningTokens, bucket.totalTokens);
|
|
1669
1633
|
}
|
|
1670
|
-
/** 活动计数旁路累加:派生表 `t_session_counts`,同上(四项计数一次落)。 */
|
|
1671
1634
|
async incrementSessionCounts(id, buckets) {
|
|
1672
1635
|
if (buckets.length === 0) return;
|
|
1673
1636
|
const statement = this.db.$client.prepare(`INSERT INTO t_session_counts (f_session_id, f_day, f_turns, f_steps, f_user_inputs, f_tool_calls)
|
|
@@ -1679,7 +1642,6 @@ var SqliteBackend = class SqliteBackend {
|
|
|
1679
1642
|
f_tool_calls = f_tool_calls + excluded.f_tool_calls`);
|
|
1680
1643
|
for (const bucket of buckets) statement.run(id, bucket.day, bucket.turns, bucket.steps, bucket.userInputs, bucket.toolCalls);
|
|
1681
1644
|
}
|
|
1682
|
-
/** 按会话重算两张汇总表(rewind / fork 之后):先删该会话的行,再从事件表重算。 */
|
|
1683
1645
|
async rebuildSessionStats(id) {
|
|
1684
1646
|
this.db.$client.prepare("DELETE FROM t_session_usage WHERE f_session_id = ?").run(id);
|
|
1685
1647
|
this.db.$client.prepare(`INSERT INTO t_session_usage (
|
|
@@ -1706,15 +1668,15 @@ var SqliteBackend = class SqliteBackend {
|
|
|
1706
1668
|
WHERE b.f_session_id = ? AND e.f_type IN (${COUNTED_EVENT_TYPE_SQL})
|
|
1707
1669
|
GROUP BY b.f_session_id, 2`).run(id);
|
|
1708
1670
|
}
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1671
|
+
async refreshEventUsageFlags(eventIds) {
|
|
1672
|
+
for (let at = 0; at < eventIds.length; at += REFRESH_FLAG_CHUNK) {
|
|
1673
|
+
const chunk = eventIds.slice(at, at + REFRESH_FLAG_CHUNK);
|
|
1674
|
+
const placeholders = chunk.map(() => "?").join(", ");
|
|
1675
|
+
this.db.$client.prepare(`UPDATE t_event_usage SET
|
|
1676
|
+
f_referenced = ${withEvent(EVENT_REFERENCED_SQL, "f_event_id")},
|
|
1677
|
+
f_subagent = ${withEvent(EVENT_SUBAGENT_SQL, "f_event_id")}
|
|
1678
|
+
WHERE f_event_id IN (${placeholders})`).run(...chunk);
|
|
1679
|
+
}
|
|
1718
1680
|
}
|
|
1719
1681
|
async deleteSessionStats(id) {
|
|
1720
1682
|
this.db.$client.prepare("DELETE FROM t_session_usage WHERE f_session_id = ?").run(id);
|