@oneuptime/common 11.0.10 → 11.0.12
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/Models/DatabaseModels/CephCluster.ts +134 -0
- package/Models/DatabaseModels/CloudResource.ts +134 -0
- package/Models/DatabaseModels/DockerHost.ts +134 -0
- package/Models/DatabaseModels/DockerSwarmCluster.ts +134 -0
- package/Models/DatabaseModels/Host.ts +134 -0
- package/Models/DatabaseModels/KubernetesCluster.ts +134 -0
- package/Models/DatabaseModels/PodmanHost.ts +134 -0
- package/Models/DatabaseModels/ProxmoxCluster.ts +134 -0
- package/Models/DatabaseModels/RumApplication.ts +134 -0
- package/Models/DatabaseModels/ServerlessFunction.ts +134 -0
- package/Models/DatabaseModels/Service.ts +134 -0
- package/README.md +1 -1
- package/Scripts/generate-service-worker.js +46 -36
- package/Server/Infrastructure/Postgres/DataSourceOptions.ts +4 -2
- package/Server/Infrastructure/Postgres/SchemaMigrations/1782600000000-AddArchiveToResources.ts +331 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +2 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Readme.md +3 -3
- package/Server/Services/AIAgentService.ts +9 -4
- package/Server/Services/AnalyticsDatabaseService.ts +89 -56
- package/Server/Services/CephClusterService.ts +6 -4
- package/Server/Services/CloudResourceService.ts +6 -4
- package/Server/Services/DatabaseService.ts +126 -0
- package/Server/Services/DockerHostService.ts +6 -4
- package/Server/Services/DockerSwarmClusterService.ts +6 -4
- package/Server/Services/HostService.ts +6 -4
- package/Server/Services/KubernetesClusterService.ts +6 -4
- package/Server/Services/PodmanHostService.ts +6 -4
- package/Server/Services/ProbeService.ts +10 -4
- package/Server/Services/ProxmoxClusterService.ts +6 -4
- package/Server/Services/RumApplicationService.ts +6 -4
- package/Server/Services/ServerlessFunctionService.ts +6 -4
- package/Server/Services/ServiceService.ts +17 -4
- package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +1 -1
- package/Server/Utils/Monitor/MonitorResource.ts +24 -10
- package/Server/Utils/Telemetry/EntityRegistry.ts +10 -5
- package/Server/Utils/Workspace/Slack/app-manifest.json +86 -92
- package/Tests/Server/Services/UpdateColumnsByIdWithoutHooks.test.ts +154 -0
- package/Tests/Server/Utils/AnalyticsDatabase/StatementGenerator.test.ts +12 -9
- package/Tests/Types/DiskSize.test.ts +49 -0
- package/Types/Dashboard/DashboardComponents/DashboardTableComponent.ts +11 -0
- package/Types/Icon/IconProp.ts +1 -0
- package/Types/Monitor/MonitorType.ts +15 -31
- package/Types/Monitor/schema.json +32 -35
- package/UI/Components/BulkUpdate/BulkArchiveActions.tsx +150 -0
- package/UI/Components/Icon/Icon.tsx +42 -126
- package/UI/Components/Navbar/NavBarMenuModal.tsx +2 -5
- package/UI/esbuild-config.js +136 -110
- package/Utils/ClientAPI/README.md +1 -1
- package/build/dist/Models/DatabaseModels/CephCluster.js +136 -0
- package/build/dist/Models/DatabaseModels/CephCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CloudResource.js +136 -0
- package/build/dist/Models/DatabaseModels/CloudResource.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DockerHost.js +136 -0
- package/build/dist/Models/DatabaseModels/DockerHost.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DockerSwarmCluster.js +136 -0
- package/build/dist/Models/DatabaseModels/DockerSwarmCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Host.js +136 -0
- package/build/dist/Models/DatabaseModels/Host.js.map +1 -1
- package/build/dist/Models/DatabaseModels/KubernetesCluster.js +136 -0
- package/build/dist/Models/DatabaseModels/KubernetesCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/PodmanHost.js +136 -0
- package/build/dist/Models/DatabaseModels/PodmanHost.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ProxmoxCluster.js +136 -0
- package/build/dist/Models/DatabaseModels/ProxmoxCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/RumApplication.js +136 -0
- package/build/dist/Models/DatabaseModels/RumApplication.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServerlessFunction.js +136 -0
- package/build/dist/Models/DatabaseModels/ServerlessFunction.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Service.js +136 -0
- package/build/dist/Models/DatabaseModels/Service.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/DataSourceOptions.js +4 -2
- package/build/dist/Server/Infrastructure/Postgres/DataSourceOptions.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1782600000000-AddArchiveToResources.js +120 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1782600000000-AddArchiveToResources.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +2 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/AIAgentService.js +9 -4
- package/build/dist/Server/Services/AIAgentService.js.map +1 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js +52 -17
- package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
- package/build/dist/Server/Services/CephClusterService.js +6 -4
- package/build/dist/Server/Services/CephClusterService.js.map +1 -1
- package/build/dist/Server/Services/CloudResourceService.js +6 -4
- package/build/dist/Server/Services/CloudResourceService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +101 -0
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/DockerHostService.js +6 -4
- package/build/dist/Server/Services/DockerHostService.js.map +1 -1
- package/build/dist/Server/Services/DockerSwarmClusterService.js +6 -4
- package/build/dist/Server/Services/DockerSwarmClusterService.js.map +1 -1
- package/build/dist/Server/Services/HostService.js +6 -4
- package/build/dist/Server/Services/HostService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesClusterService.js +6 -4
- package/build/dist/Server/Services/KubernetesClusterService.js.map +1 -1
- package/build/dist/Server/Services/PodmanHostService.js +6 -4
- package/build/dist/Server/Services/PodmanHostService.js.map +1 -1
- package/build/dist/Server/Services/ProbeService.js +10 -4
- package/build/dist/Server/Services/ProbeService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxClusterService.js +6 -4
- package/build/dist/Server/Services/ProxmoxClusterService.js.map +1 -1
- package/build/dist/Server/Services/RumApplicationService.js +6 -4
- package/build/dist/Server/Services/RumApplicationService.js.map +1 -1
- package/build/dist/Server/Services/ServerlessFunctionService.js +6 -4
- package/build/dist/Server/Services/ServerlessFunctionService.js.map +1 -1
- package/build/dist/Server/Services/ServiceService.js +17 -4
- package/build/dist/Server/Services/ServiceService.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorResource.js +24 -10
- package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js +10 -5
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/Slack/app-manifest.json +3 -9
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardTableComponent.js.map +1 -1
- package/build/dist/Types/Icon/IconProp.js +1 -0
- package/build/dist/Types/Icon/IconProp.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorType.js +15 -31
- package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
- package/build/dist/UI/Components/BulkUpdate/BulkArchiveActions.js +96 -0
- package/build/dist/UI/Components/BulkUpdate/BulkArchiveActions.js.map +1 -0
- package/build/dist/UI/Components/Icon/Icon.js +17 -41
- package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
- package/build/dist/UI/Components/Navbar/NavBarMenuModal.js +2 -3
- package/build/dist/UI/Components/Navbar/NavBarMenuModal.js.map +1 -1
- package/jest.config.json +47 -66
- package/package.json +1 -1
- package/tsconfig.json +109 -113
|
@@ -1005,16 +1005,14 @@ export default class AnalyticsDatabaseService<
|
|
|
1005
1005
|
if (countBy.groupBy && Object.keys(countBy.groupBy).length > 0) {
|
|
1006
1006
|
const groupByKey: string = Object.keys(countBy.groupBy)[0] as string;
|
|
1007
1007
|
|
|
1008
|
-
statement.append(
|
|
1009
|
-
SQL`DISTINCT ${groupByKey}`
|
|
1010
|
-
);
|
|
1008
|
+
statement.append(SQL`DISTINCT ${groupByKey}`);
|
|
1011
1009
|
}
|
|
1012
1010
|
|
|
1013
1011
|
statement
|
|
1014
1012
|
.append(
|
|
1015
1013
|
SQL`) as count
|
|
1016
1014
|
FROM ${databaseName}.${this.model.tableName}
|
|
1017
|
-
WHERE TRUE
|
|
1015
|
+
WHERE TRUE `,
|
|
1018
1016
|
)
|
|
1019
1017
|
.append(whereStatement)
|
|
1020
1018
|
.append(this.getRetentionReadFilter());
|
|
@@ -1052,8 +1050,12 @@ export default class AnalyticsDatabaseService<
|
|
|
1052
1050
|
}),
|
|
1053
1051
|
);
|
|
1054
1052
|
|
|
1055
|
-
logger.debug(`${this.model.tableName} Count Statement`, {
|
|
1056
|
-
|
|
1053
|
+
logger.debug(`${this.model.tableName} Count Statement`, {
|
|
1054
|
+
tableName: this.model.tableName,
|
|
1055
|
+
} as LogAttributes);
|
|
1056
|
+
logger.debug(statement, {
|
|
1057
|
+
tableName: this.model.tableName,
|
|
1058
|
+
} as LogAttributes);
|
|
1057
1059
|
|
|
1058
1060
|
return statement;
|
|
1059
1061
|
}
|
|
@@ -1092,8 +1094,12 @@ export default class AnalyticsDatabaseService<
|
|
|
1092
1094
|
|
|
1093
1095
|
statement.append(getQuerySettings({ maxExecutionTimeInSeconds: 45 }));
|
|
1094
1096
|
|
|
1095
|
-
logger.debug(`${this.model.tableName} Exists Statement`, {
|
|
1096
|
-
|
|
1097
|
+
logger.debug(`${this.model.tableName} Exists Statement`, {
|
|
1098
|
+
tableName: this.model.tableName,
|
|
1099
|
+
} as LogAttributes);
|
|
1100
|
+
logger.debug(statement, {
|
|
1101
|
+
tableName: this.model.tableName,
|
|
1102
|
+
} as LogAttributes);
|
|
1097
1103
|
|
|
1098
1104
|
return statement;
|
|
1099
1105
|
}
|
|
@@ -1112,11 +1118,11 @@ export default class AnalyticsDatabaseService<
|
|
|
1112
1118
|
this.statementGenerator.toAggregateSelectStatement(aggregateBy);
|
|
1113
1119
|
|
|
1114
1120
|
const whereStatement: Statement = this.statementGenerator.toWhereStatement(
|
|
1115
|
-
aggregateBy.query
|
|
1121
|
+
aggregateBy.query,
|
|
1116
1122
|
);
|
|
1117
1123
|
|
|
1118
1124
|
const sortStatement: Statement = this.statementGenerator.toSortStatement(
|
|
1119
|
-
aggregateBy.sort
|
|
1125
|
+
aggregateBy.sort!,
|
|
1120
1126
|
);
|
|
1121
1127
|
|
|
1122
1128
|
const statement: Statement = SQL``;
|
|
@@ -1136,7 +1142,7 @@ export default class AnalyticsDatabaseService<
|
|
|
1136
1142
|
statement
|
|
1137
1143
|
.append(SQL` , `)
|
|
1138
1144
|
.append(
|
|
1139
|
-
this.statementGenerator.toGroupByStatement(aggregateBy.groupBy)
|
|
1145
|
+
this.statementGenerator.toGroupByStatement(aggregateBy.groupBy),
|
|
1140
1146
|
);
|
|
1141
1147
|
}
|
|
1142
1148
|
|
|
@@ -1146,7 +1152,7 @@ export default class AnalyticsDatabaseService<
|
|
|
1146
1152
|
SQL` LIMIT ${{
|
|
1147
1153
|
value: Number(aggregateBy.limit),
|
|
1148
1154
|
type: TableColumnType.Number,
|
|
1149
|
-
}}
|
|
1155
|
+
}}`,
|
|
1150
1156
|
);
|
|
1151
1157
|
|
|
1152
1158
|
statement.append(SQL` OFFSET ${{
|
|
@@ -1182,8 +1188,12 @@ export default class AnalyticsDatabaseService<
|
|
|
1182
1188
|
}),
|
|
1183
1189
|
);
|
|
1184
1190
|
|
|
1185
|
-
logger.debug(`${this.model.tableName} Aggregate Statement`, {
|
|
1186
|
-
|
|
1191
|
+
logger.debug(`${this.model.tableName} Aggregate Statement`, {
|
|
1192
|
+
tableName: this.model.tableName,
|
|
1193
|
+
} as LogAttributes);
|
|
1194
|
+
logger.debug(statement, {
|
|
1195
|
+
tableName: this.model.tableName,
|
|
1196
|
+
} as LogAttributes);
|
|
1187
1197
|
|
|
1188
1198
|
return { statement, columns: select.columns };
|
|
1189
1199
|
}
|
|
@@ -1206,7 +1216,7 @@ export default class AnalyticsDatabaseService<
|
|
|
1206
1216
|
};
|
|
1207
1217
|
|
|
1208
1218
|
groupByStatement = this.statementGenerator.toGroupByStatement(
|
|
1209
|
-
findBy.groupBy
|
|
1219
|
+
findBy.groupBy,
|
|
1210
1220
|
);
|
|
1211
1221
|
}
|
|
1212
1222
|
|
|
@@ -1214,11 +1224,11 @@ export default class AnalyticsDatabaseService<
|
|
|
1214
1224
|
this.statementGenerator.toSelectStatement(findBy.select!);
|
|
1215
1225
|
|
|
1216
1226
|
const whereStatement: Statement = this.statementGenerator.toWhereStatement(
|
|
1217
|
-
findBy.query
|
|
1227
|
+
findBy.query,
|
|
1218
1228
|
);
|
|
1219
1229
|
|
|
1220
1230
|
const sortStatement: Statement = this.statementGenerator.toSortStatement(
|
|
1221
|
-
findBy.sort
|
|
1231
|
+
findBy.sort!,
|
|
1222
1232
|
);
|
|
1223
1233
|
|
|
1224
1234
|
const statement: Statement = SQL``;
|
|
@@ -1240,7 +1250,7 @@ export default class AnalyticsDatabaseService<
|
|
|
1240
1250
|
SQL` LIMIT ${{
|
|
1241
1251
|
value: Number(findBy.limit),
|
|
1242
1252
|
type: TableColumnType.Number,
|
|
1243
|
-
}}
|
|
1253
|
+
}}`,
|
|
1244
1254
|
);
|
|
1245
1255
|
|
|
1246
1256
|
statement.append(SQL` OFFSET ${{
|
|
@@ -1263,8 +1273,12 @@ export default class AnalyticsDatabaseService<
|
|
|
1263
1273
|
}),
|
|
1264
1274
|
);
|
|
1265
1275
|
|
|
1266
|
-
logger.debug(`${this.model.tableName} Find Statement`, {
|
|
1267
|
-
|
|
1276
|
+
logger.debug(`${this.model.tableName} Find Statement`, {
|
|
1277
|
+
tableName: this.model.tableName,
|
|
1278
|
+
} as LogAttributes);
|
|
1279
|
+
logger.debug(statement, {
|
|
1280
|
+
tableName: this.model.tableName,
|
|
1281
|
+
} as LogAttributes);
|
|
1268
1282
|
|
|
1269
1283
|
return { statement, columns: select.columns };
|
|
1270
1284
|
}
|
|
@@ -1276,7 +1290,7 @@ export default class AnalyticsDatabaseService<
|
|
|
1276
1290
|
|
|
1277
1291
|
const databaseName: string = this.database.getDatasourceOptions().database!;
|
|
1278
1292
|
const whereStatement: Statement = this.statementGenerator.toWhereStatement(
|
|
1279
|
-
deleteBy.query
|
|
1293
|
+
deleteBy.query,
|
|
1280
1294
|
);
|
|
1281
1295
|
|
|
1282
1296
|
/*
|
|
@@ -1294,15 +1308,19 @@ export default class AnalyticsDatabaseService<
|
|
|
1294
1308
|
DELETE FROM ${databaseName}.${this.model.tableName}
|
|
1295
1309
|
WHERE TRUE `.append(whereStatement);
|
|
1296
1310
|
|
|
1297
|
-
logger.debug(`${this.model.tableName} Delete Statement`, {
|
|
1298
|
-
|
|
1311
|
+
logger.debug(`${this.model.tableName} Delete Statement`, {
|
|
1312
|
+
tableName: this.model.tableName,
|
|
1313
|
+
} as LogAttributes);
|
|
1314
|
+
logger.debug(statement, {
|
|
1315
|
+
tableName: this.model.tableName,
|
|
1316
|
+
} as LogAttributes);
|
|
1299
1317
|
|
|
1300
1318
|
return statement;
|
|
1301
1319
|
}
|
|
1302
1320
|
|
|
1303
1321
|
@CaptureSpan()
|
|
1304
1322
|
public async findOneBy(
|
|
1305
|
-
findOneBy: FindOneBy<TBaseModel
|
|
1323
|
+
findOneBy: FindOneBy<TBaseModel>,
|
|
1306
1324
|
): Promise<TBaseModel | null> {
|
|
1307
1325
|
const findBy: FindBy<TBaseModel> = findOneBy as FindBy<TBaseModel>;
|
|
1308
1326
|
findBy.limit = new PositiveNumber(1);
|
|
@@ -1332,7 +1350,7 @@ export default class AnalyticsDatabaseService<
|
|
|
1332
1350
|
beforeDeleteBy.query = await ModelPermission.checkDeletePermission(
|
|
1333
1351
|
this.modelType,
|
|
1334
1352
|
beforeDeleteBy.query,
|
|
1335
|
-
deleteBy.props
|
|
1353
|
+
deleteBy.props,
|
|
1336
1354
|
);
|
|
1337
1355
|
|
|
1338
1356
|
const select: Select<TBaseModel> = {};
|
|
@@ -1348,8 +1366,12 @@ export default class AnalyticsDatabaseService<
|
|
|
1348
1366
|
|
|
1349
1367
|
await this.execute(deleteStatement);
|
|
1350
1368
|
|
|
1351
|
-
logger.debug(`${this.model.tableName} Delete Statement executed`, {
|
|
1352
|
-
|
|
1369
|
+
logger.debug(`${this.model.tableName} Delete Statement executed`, {
|
|
1370
|
+
tableName: this.model.tableName,
|
|
1371
|
+
} as LogAttributes);
|
|
1372
|
+
logger.debug(deleteStatement, {
|
|
1373
|
+
tableName: this.model.tableName,
|
|
1374
|
+
} as LogAttributes);
|
|
1353
1375
|
} catch (error) {
|
|
1354
1376
|
await this.onDeleteError(error as Exception);
|
|
1355
1377
|
throw this.getException(error as Exception);
|
|
@@ -1358,7 +1380,7 @@ export default class AnalyticsDatabaseService<
|
|
|
1358
1380
|
|
|
1359
1381
|
@CaptureSpan()
|
|
1360
1382
|
public async findOneById(
|
|
1361
|
-
findOneById: FindOneByID<TBaseModel
|
|
1383
|
+
findOneById: FindOneByID<TBaseModel>,
|
|
1362
1384
|
): Promise<TBaseModel | null> {
|
|
1363
1385
|
if (!findOneById.id) {
|
|
1364
1386
|
throw new BadDataException("findOneById.id is required");
|
|
@@ -1390,7 +1412,7 @@ export default class AnalyticsDatabaseService<
|
|
|
1390
1412
|
this.modelType,
|
|
1391
1413
|
beforeUpdateBy.query,
|
|
1392
1414
|
beforeUpdateBy.data,
|
|
1393
|
-
beforeUpdateBy.props
|
|
1415
|
+
beforeUpdateBy.props,
|
|
1394
1416
|
);
|
|
1395
1417
|
|
|
1396
1418
|
const select: Select<TBaseModel> = {};
|
|
@@ -1407,8 +1429,12 @@ export default class AnalyticsDatabaseService<
|
|
|
1407
1429
|
|
|
1408
1430
|
await this.execute(statement);
|
|
1409
1431
|
|
|
1410
|
-
logger.debug(`${this.model.tableName} Update Statement executed`, {
|
|
1411
|
-
|
|
1432
|
+
logger.debug(`${this.model.tableName} Update Statement executed`, {
|
|
1433
|
+
tableName: this.model.tableName,
|
|
1434
|
+
} as LogAttributes);
|
|
1435
|
+
logger.debug(statement, {
|
|
1436
|
+
tableName: this.model.tableName,
|
|
1437
|
+
} as LogAttributes);
|
|
1412
1438
|
} catch (error) {
|
|
1413
1439
|
await this.onUpdateError(error as Exception);
|
|
1414
1440
|
throw this.getException(error as Exception);
|
|
@@ -1437,7 +1463,7 @@ export default class AnalyticsDatabaseService<
|
|
|
1437
1463
|
@CaptureSpan()
|
|
1438
1464
|
public async execute(
|
|
1439
1465
|
statement: Statement | string,
|
|
1440
|
-
options?: ClickhouseExecuteOptions
|
|
1466
|
+
options?: ClickhouseExecuteOptions,
|
|
1441
1467
|
): Promise<ExecResult<Stream>> {
|
|
1442
1468
|
const client: ClickhouseClient = this.getDatabaseClient();
|
|
1443
1469
|
|
|
@@ -1459,7 +1485,7 @@ export default class AnalyticsDatabaseService<
|
|
|
1459
1485
|
@CaptureSpan()
|
|
1460
1486
|
public async executeQuery(
|
|
1461
1487
|
statement: Statement | string,
|
|
1462
|
-
options?: ClickhouseExecuteOptions
|
|
1488
|
+
options?: ClickhouseExecuteOptions,
|
|
1463
1489
|
): Promise<ResultSet<"JSON">> {
|
|
1464
1490
|
const client: ClickhouseClient = this.getDatabaseClient();
|
|
1465
1491
|
|
|
@@ -1523,7 +1549,7 @@ export default class AnalyticsDatabaseService<
|
|
|
1523
1549
|
|
|
1524
1550
|
protected async onUpdateSuccess(
|
|
1525
1551
|
onUpdate: OnUpdate<TBaseModel>,
|
|
1526
|
-
_updatedItemIds: Array<ObjectID
|
|
1552
|
+
_updatedItemIds: Array<ObjectID>,
|
|
1527
1553
|
): Promise<OnUpdate<TBaseModel>> {
|
|
1528
1554
|
// A place holder method used for overriding.
|
|
1529
1555
|
return Promise.resolve(onUpdate);
|
|
@@ -1536,7 +1562,7 @@ export default class AnalyticsDatabaseService<
|
|
|
1536
1562
|
|
|
1537
1563
|
protected async onDeleteSuccess(
|
|
1538
1564
|
onDelete: OnDelete<TBaseModel>,
|
|
1539
|
-
_itemIdsBeforeDelete: Array<ObjectID
|
|
1565
|
+
_itemIdsBeforeDelete: Array<ObjectID>,
|
|
1540
1566
|
): Promise<OnDelete<TBaseModel>> {
|
|
1541
1567
|
// A place holder method used for overriding.
|
|
1542
1568
|
return Promise.resolve(onDelete);
|
|
@@ -1549,7 +1575,7 @@ export default class AnalyticsDatabaseService<
|
|
|
1549
1575
|
|
|
1550
1576
|
protected async onFindSuccess(
|
|
1551
1577
|
onFind: OnFind<TBaseModel>,
|
|
1552
|
-
items: Array<TBaseModel
|
|
1578
|
+
items: Array<TBaseModel>,
|
|
1553
1579
|
): Promise<OnFind<TBaseModel>> {
|
|
1554
1580
|
// A place holder method used for overriding.
|
|
1555
1581
|
return Promise.resolve({ ...onFind, carryForward: items });
|
|
@@ -1561,7 +1587,7 @@ export default class AnalyticsDatabaseService<
|
|
|
1561
1587
|
}
|
|
1562
1588
|
|
|
1563
1589
|
protected async onCountSuccess(
|
|
1564
|
-
count: PositiveNumber
|
|
1590
|
+
count: PositiveNumber,
|
|
1565
1591
|
): Promise<PositiveNumber> {
|
|
1566
1592
|
// A place holder method used for overriding.
|
|
1567
1593
|
return Promise.resolve(count);
|
|
@@ -1574,14 +1600,14 @@ export default class AnalyticsDatabaseService<
|
|
|
1574
1600
|
|
|
1575
1601
|
protected async onCreateSuccess(
|
|
1576
1602
|
_onCreate: OnCreate<TBaseModel>,
|
|
1577
|
-
createdItem: TBaseModel
|
|
1603
|
+
createdItem: TBaseModel,
|
|
1578
1604
|
): Promise<TBaseModel> {
|
|
1579
1605
|
// A place holder method used for overriding.
|
|
1580
1606
|
return Promise.resolve(createdItem);
|
|
1581
1607
|
}
|
|
1582
1608
|
|
|
1583
1609
|
protected async onBeforeCreate(
|
|
1584
|
-
createBy: CreateBy<TBaseModel
|
|
1610
|
+
createBy: CreateBy<TBaseModel>,
|
|
1585
1611
|
): Promise<OnCreate<TBaseModel>> {
|
|
1586
1612
|
// A place holder method used for overriding.
|
|
1587
1613
|
return Promise.resolve({
|
|
@@ -1591,7 +1617,7 @@ export default class AnalyticsDatabaseService<
|
|
|
1591
1617
|
}
|
|
1592
1618
|
|
|
1593
1619
|
private async _onBeforeCreate(
|
|
1594
|
-
createBy: CreateBy<TBaseModel
|
|
1620
|
+
createBy: CreateBy<TBaseModel>,
|
|
1595
1621
|
): Promise<OnCreate<TBaseModel>> {
|
|
1596
1622
|
// Private method that runs before create.
|
|
1597
1623
|
const projectIdColumn: string | null =
|
|
@@ -1606,7 +1632,7 @@ export default class AnalyticsDatabaseService<
|
|
|
1606
1632
|
|
|
1607
1633
|
@CaptureSpan()
|
|
1608
1634
|
public async createMany(
|
|
1609
|
-
createBy: CreateManyBy<TBaseModel
|
|
1635
|
+
createBy: CreateManyBy<TBaseModel>,
|
|
1610
1636
|
): Promise<Array<TBaseModel>> {
|
|
1611
1637
|
// add tenantId if present.
|
|
1612
1638
|
const tenantColumnName: string | null =
|
|
@@ -1654,7 +1680,7 @@ export default class AnalyticsDatabaseService<
|
|
|
1654
1680
|
ModelPermission.checkCreatePermissions(
|
|
1655
1681
|
this.modelType,
|
|
1656
1682
|
data,
|
|
1657
|
-
createBy.props
|
|
1683
|
+
createBy.props,
|
|
1658
1684
|
);
|
|
1659
1685
|
|
|
1660
1686
|
items.push(data);
|
|
@@ -1662,13 +1688,17 @@ export default class AnalyticsDatabaseService<
|
|
|
1662
1688
|
|
|
1663
1689
|
try {
|
|
1664
1690
|
const insertStatement: string = this.statementGenerator.toCreateStatement(
|
|
1665
|
-
{ item: items }
|
|
1691
|
+
{ item: items },
|
|
1666
1692
|
);
|
|
1667
1693
|
|
|
1668
1694
|
await this.execute(insertStatement);
|
|
1669
1695
|
|
|
1670
|
-
logger.debug(`${this.model.tableName} Create Statement executed`, {
|
|
1671
|
-
|
|
1696
|
+
logger.debug(`${this.model.tableName} Create Statement executed`, {
|
|
1697
|
+
tableName: this.model.tableName,
|
|
1698
|
+
} as LogAttributes);
|
|
1699
|
+
logger.debug(insertStatement, {
|
|
1700
|
+
tableName: this.model.tableName,
|
|
1701
|
+
} as LogAttributes);
|
|
1672
1702
|
|
|
1673
1703
|
if (!createBy.props.ignoreHooks) {
|
|
1674
1704
|
for (let i: number = 0; i < items.length; i++) {
|
|
@@ -1684,7 +1714,7 @@ export default class AnalyticsDatabaseService<
|
|
|
1684
1714
|
},
|
|
1685
1715
|
carryForward: carryForwards[i],
|
|
1686
1716
|
},
|
|
1687
|
-
items[i]
|
|
1717
|
+
items[i]!,
|
|
1688
1718
|
);
|
|
1689
1719
|
}
|
|
1690
1720
|
}
|
|
@@ -1696,7 +1726,7 @@ export default class AnalyticsDatabaseService<
|
|
|
1696
1726
|
for (const item of items) {
|
|
1697
1727
|
if (!tenantId && this.getModel().getTenantColumn()) {
|
|
1698
1728
|
tenantId = item.getColumnValue<ObjectID>(
|
|
1699
|
-
this.getModel().getTenantColumn()!.key
|
|
1729
|
+
this.getModel().getTenantColumn()!.key,
|
|
1700
1730
|
);
|
|
1701
1731
|
}
|
|
1702
1732
|
|
|
@@ -1727,7 +1757,7 @@ export default class AnalyticsDatabaseService<
|
|
|
1727
1757
|
tenantId: tenantId,
|
|
1728
1758
|
eventType: ModelEventType.Create,
|
|
1729
1759
|
modelType: this.modelType,
|
|
1730
|
-
})
|
|
1760
|
+
}),
|
|
1731
1761
|
);
|
|
1732
1762
|
}
|
|
1733
1763
|
|
|
@@ -1766,7 +1796,7 @@ export default class AnalyticsDatabaseService<
|
|
|
1766
1796
|
}
|
|
1767
1797
|
|
|
1768
1798
|
private sanitizeCreate<TBaseModel extends AnalyticsBaseModel>(
|
|
1769
|
-
data: TBaseModel
|
|
1799
|
+
data: TBaseModel,
|
|
1770
1800
|
): TBaseModel {
|
|
1771
1801
|
if (!data.id) {
|
|
1772
1802
|
data.id = ObjectID.generateTimeOrdered();
|
|
@@ -1798,7 +1828,7 @@ export default class AnalyticsDatabaseService<
|
|
|
1798
1828
|
public async onTrigger(
|
|
1799
1829
|
id: ObjectID,
|
|
1800
1830
|
projectId: ObjectID,
|
|
1801
|
-
triggerType: DatabaseTriggerType
|
|
1831
|
+
triggerType: DatabaseTriggerType,
|
|
1802
1832
|
): Promise<void> {
|
|
1803
1833
|
if (this.getModel().enableWorkflowOn) {
|
|
1804
1834
|
API.post({
|
|
@@ -1807,9 +1837,9 @@ export default class AnalyticsDatabaseService<
|
|
|
1807
1837
|
WorkflowHostname,
|
|
1808
1838
|
new Route(
|
|
1809
1839
|
`/${WorkflowRoute.toString()}/analytics-model/${projectId.toString()}/${Text.pascalCaseToDashes(
|
|
1810
|
-
this.getModel().tableName
|
|
1811
|
-
)}/${triggerType}
|
|
1812
|
-
)
|
|
1840
|
+
this.getModel().tableName!,
|
|
1841
|
+
)}/${triggerType}`,
|
|
1842
|
+
),
|
|
1813
1843
|
),
|
|
1814
1844
|
data: {
|
|
1815
1845
|
_id: id.toString(),
|
|
@@ -1818,7 +1848,10 @@ export default class AnalyticsDatabaseService<
|
|
|
1818
1848
|
...ClusterKeyAuthorization.getClusterKeyHeaders(),
|
|
1819
1849
|
},
|
|
1820
1850
|
}).catch((error: Error) => {
|
|
1821
|
-
logger.error(error, {
|
|
1851
|
+
logger.error(error, {
|
|
1852
|
+
projectId: projectId?.toString(),
|
|
1853
|
+
tableName: this.getModel().tableName,
|
|
1854
|
+
} as LogAttributes);
|
|
1822
1855
|
});
|
|
1823
1856
|
}
|
|
1824
1857
|
}
|
|
@@ -1836,7 +1869,7 @@ export default class AnalyticsDatabaseService<
|
|
|
1836
1869
|
) {
|
|
1837
1870
|
data.setColumnValue(
|
|
1838
1871
|
requiredField,
|
|
1839
|
-
data.getDefaultValueForColumn(requiredField)
|
|
1872
|
+
data.getDefaultValueForColumn(requiredField),
|
|
1840
1873
|
);
|
|
1841
1874
|
} else {
|
|
1842
1875
|
throw new BadDataException(`${requiredField} is required`);
|
|
@@ -1849,7 +1882,7 @@ export default class AnalyticsDatabaseService<
|
|
|
1849
1882
|
// add default value.
|
|
1850
1883
|
data.setColumnValue(
|
|
1851
1884
|
requiredField,
|
|
1852
|
-
data.getDefaultValueForColumn(requiredField)
|
|
1885
|
+
data.getDefaultValueForColumn(requiredField),
|
|
1853
1886
|
);
|
|
1854
1887
|
} else if (
|
|
1855
1888
|
((data as any)[requiredField] === null ||
|
|
@@ -269,12 +269,14 @@ export class Service extends DatabaseService<Model> {
|
|
|
269
269
|
data.capacityUsedPercent = extra.capacityUsedPercent;
|
|
270
270
|
}
|
|
271
271
|
|
|
272
|
-
|
|
272
|
+
/*
|
|
273
|
+
* Heartbeat write: a single-statement UPDATE with no hooks and no
|
|
274
|
+
* `version` bump, avoiding the hot-row Postgres lock convoy that the
|
|
275
|
+
* full updateOneById pipeline causes. See ServiceService.updateLastSeen.
|
|
276
|
+
*/
|
|
277
|
+
await this.updateColumnsByIdWithoutHooks({
|
|
273
278
|
id: clusterId,
|
|
274
279
|
data: data,
|
|
275
|
-
props: {
|
|
276
|
-
isRoot: true,
|
|
277
|
-
},
|
|
278
280
|
});
|
|
279
281
|
}
|
|
280
282
|
|
|
@@ -226,12 +226,14 @@ export class Service extends DatabaseService<Model> {
|
|
|
226
226
|
data.runtimeVersion = extra.runtimeVersion;
|
|
227
227
|
}
|
|
228
228
|
|
|
229
|
-
|
|
229
|
+
/*
|
|
230
|
+
* Heartbeat write: a single-statement UPDATE with no hooks and no
|
|
231
|
+
* `version` bump, avoiding the hot-row Postgres lock convoy that the
|
|
232
|
+
* full updateOneById pipeline causes. See ServiceService.updateLastSeen.
|
|
233
|
+
*/
|
|
234
|
+
await this.updateColumnsByIdWithoutHooks({
|
|
230
235
|
id: cloudResourceId,
|
|
231
236
|
data: data,
|
|
232
|
-
props: {
|
|
233
|
-
isRoot: true,
|
|
234
|
-
},
|
|
235
237
|
});
|
|
236
238
|
}
|
|
237
239
|
|
|
@@ -46,6 +46,7 @@ import PartialEntity from "../../Types/Database/PartialEntity";
|
|
|
46
46
|
import { TableColumnMetadata } from "../../Types/Database/TableColumn";
|
|
47
47
|
import TableColumnType from "../../Types/Database/TableColumnType";
|
|
48
48
|
import { getUniqueColumnsBy } from "../../Types/Database/UniqueColumnBy";
|
|
49
|
+
import OneUptimeDate from "../../Types/Date";
|
|
49
50
|
import Dictionary from "../../Types/Dictionary";
|
|
50
51
|
import BadDataException from "../../Types/Exception/BadDataException";
|
|
51
52
|
import DatabaseNotConnectedException from "../../Types/Exception/DatabaseNotConnectedException";
|
|
@@ -62,10 +63,14 @@ import API from "../../Utils/API";
|
|
|
62
63
|
import Slug from "../../Utils/Slug";
|
|
63
64
|
import {
|
|
64
65
|
DataSource,
|
|
66
|
+
Driver,
|
|
65
67
|
EntityManager,
|
|
66
68
|
Repository,
|
|
67
69
|
SelectQueryBuilder,
|
|
68
70
|
} from "typeorm";
|
|
71
|
+
import { ColumnMetadata } from "typeorm/metadata/ColumnMetadata";
|
|
72
|
+
import { EntityMetadata } from "typeorm/metadata/EntityMetadata";
|
|
73
|
+
import { ObjectLiteral } from "typeorm/common/ObjectLiteral";
|
|
69
74
|
import { FindWhere } from "../../Types/BaseDatabase/Query";
|
|
70
75
|
import Realtime from "../Utils/Realtime";
|
|
71
76
|
import ModelEventType from "../../Types/Realtime/ModelEventType";
|
|
@@ -578,6 +583,28 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
|
|
|
578
583
|
(data as any)["createdByUserId"] = props.userId;
|
|
579
584
|
}
|
|
580
585
|
|
|
586
|
+
/*
|
|
587
|
+
* Stamp archive audit fields when a resource is being (un)archived.
|
|
588
|
+
* The client only ever sends `isArchived`; we stamp `archivedAt` and
|
|
589
|
+
* `archivedByUserId` here — which runs after column update-permission
|
|
590
|
+
* checks — so these audit fields are server-controlled and cannot be
|
|
591
|
+
* spoofed, exactly like `createdByUserId` above.
|
|
592
|
+
*/
|
|
593
|
+
if (isUpdate && (data as any)["isArchived"] !== undefined) {
|
|
594
|
+
const isArchivedValue: boolean = Boolean((data as any)["isArchived"]);
|
|
595
|
+
|
|
596
|
+
if (this.model.hasColumn("archivedAt")) {
|
|
597
|
+
(data as any)["archivedAt"] = isArchivedValue
|
|
598
|
+
? OneUptimeDate.getCurrentDate()
|
|
599
|
+
: null;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
if (this.model.hasColumn("archivedByUserId")) {
|
|
603
|
+
(data as any)["archivedByUserId"] =
|
|
604
|
+
isArchivedValue && props.userId ? props.userId : null;
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
|
|
581
608
|
return data;
|
|
582
609
|
}
|
|
583
610
|
|
|
@@ -1968,6 +1995,105 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
|
|
|
1968
1995
|
});
|
|
1969
1996
|
}
|
|
1970
1997
|
|
|
1998
|
+
/*
|
|
1999
|
+
* Fast, side-effect-free single-statement column update by id.
|
|
2000
|
+
*
|
|
2001
|
+
* `updateOneById` is heavy: an access-control pre-check SELECT, then
|
|
2002
|
+
* `_updateBy` (a `_findBy` SELECT to load the row, `getRepository().save()`,
|
|
2003
|
+
* then workflow / realtime / audit-log hooks). That is several round
|
|
2004
|
+
* trips, each holding the row's write lock and pinning a pool connection.
|
|
2005
|
+
* On a hot row written on every ingest batch — e.g. a telemetry
|
|
2006
|
+
* liveness/heartbeat timestamp — that pipeline becomes the head of a
|
|
2007
|
+
* Postgres lock convoy: one slow writer (or a save() transaction left open
|
|
2008
|
+
* across other async work) blocks every other writer of the same row, and
|
|
2009
|
+
* the waiters each pin a pool connection until the whole pool is starved.
|
|
2010
|
+
*
|
|
2011
|
+
* This issues exactly ONE auto-committed UPDATE (raw parameterized SQL).
|
|
2012
|
+
* The row's write lock is held only for that statement, so the write can
|
|
2013
|
+
* never head a convoy and never spans other async work. It deliberately
|
|
2014
|
+
* runs NO hooks, workflow triggers, realtime events, audit-log writes, or
|
|
2015
|
+
* access-control checks, and does NOT bump the optimistic-lock `version`
|
|
2016
|
+
* column. (We can't use the entity-aware QueryBuilder for the
|
|
2017
|
+
* no-version-bump part: TypeORM resolves even a table-name string back to
|
|
2018
|
+
* the entity metadata, whose UpdateQueryBuilder branch always appends
|
|
2019
|
+
* `version = version + 1`.) `updatedAt` is refreshed to preserve the
|
|
2020
|
+
* behaviour of the normal update path.
|
|
2021
|
+
*
|
|
2022
|
+
* Column and table identifiers are taken from entity metadata (never from
|
|
2023
|
+
* the caller), and every value is bound as a parameter, so this is not an
|
|
2024
|
+
* injection surface. Use ONLY for trusted, internal, side-effect-free
|
|
2025
|
+
* column writes where the full pipeline is pure overhead.
|
|
2026
|
+
*/
|
|
2027
|
+
@CaptureSpan()
|
|
2028
|
+
public async updateColumnsByIdWithoutHooks(input: {
|
|
2029
|
+
id: ObjectID;
|
|
2030
|
+
data: PartialEntity<TBaseModel>;
|
|
2031
|
+
}): Promise<void> {
|
|
2032
|
+
if (!input.id) {
|
|
2033
|
+
throw new BadDataException("id is required");
|
|
2034
|
+
}
|
|
2035
|
+
|
|
2036
|
+
const repository: Repository<TBaseModel> = this.getRepository();
|
|
2037
|
+
const metadata: EntityMetadata = repository.metadata;
|
|
2038
|
+
const driver: Driver = repository.manager.connection.driver;
|
|
2039
|
+
|
|
2040
|
+
const setClauses: Array<string> = [];
|
|
2041
|
+
const params: Array<unknown> = [];
|
|
2042
|
+
|
|
2043
|
+
for (const [propertyName, value] of Object.entries(
|
|
2044
|
+
input.data as ObjectLiteral,
|
|
2045
|
+
)) {
|
|
2046
|
+
const column: ColumnMetadata | undefined =
|
|
2047
|
+
metadata.findColumnWithPropertyName(propertyName);
|
|
2048
|
+
if (!column) {
|
|
2049
|
+
throw new BadDataException(
|
|
2050
|
+
`updateColumnsByIdWithoutHooks: unknown column "${propertyName}" on "${metadata.tableName}"`,
|
|
2051
|
+
);
|
|
2052
|
+
}
|
|
2053
|
+
/*
|
|
2054
|
+
* PartialEntity permits `() => string` SQL-expression values, but this
|
|
2055
|
+
* raw bind path can only parameterize literals (and the save()-based
|
|
2056
|
+
* updateOneById it replaces doesn't support expressions either). Fail
|
|
2057
|
+
* loudly rather than binding a function object.
|
|
2058
|
+
*/
|
|
2059
|
+
if (typeof value === "function") {
|
|
2060
|
+
throw new BadDataException(
|
|
2061
|
+
`updateColumnsByIdWithoutHooks: SQL-expression values are not supported (column "${propertyName}"); pass a literal value.`,
|
|
2062
|
+
);
|
|
2063
|
+
}
|
|
2064
|
+
/*
|
|
2065
|
+
* Run the value through the driver's persist path so column
|
|
2066
|
+
* transformers (e.g. ObjectID <-> uuid), JSON stringification, and
|
|
2067
|
+
* boolean/date coercion are applied exactly as getRepository().save()
|
|
2068
|
+
* would. Without this, the raw bind below would write an ObjectID
|
|
2069
|
+
* object (or a raw JS object) straight to Postgres.
|
|
2070
|
+
*/
|
|
2071
|
+
params.push(driver.preparePersistentValue(value, column));
|
|
2072
|
+
setClauses.push(`"${column.databaseName}" = $${params.length}`);
|
|
2073
|
+
}
|
|
2074
|
+
|
|
2075
|
+
if (setClauses.length === 0) {
|
|
2076
|
+
return;
|
|
2077
|
+
}
|
|
2078
|
+
|
|
2079
|
+
// The raw path has no entity machinery to touch updateDate — do it here.
|
|
2080
|
+
if (metadata.updateDateColumn) {
|
|
2081
|
+
setClauses.push(
|
|
2082
|
+
`"${metadata.updateDateColumn.databaseName}" = CURRENT_TIMESTAMP`,
|
|
2083
|
+
);
|
|
2084
|
+
}
|
|
2085
|
+
|
|
2086
|
+
const primaryColumnName: string =
|
|
2087
|
+
metadata.primaryColumns[0]?.databaseName || "_id";
|
|
2088
|
+
params.push(input.id.toString());
|
|
2089
|
+
|
|
2090
|
+
const sql: string = `UPDATE "${metadata.tableName}" SET ${setClauses.join(
|
|
2091
|
+
", ",
|
|
2092
|
+
)} WHERE "${primaryColumnName}" = $${params.length}`;
|
|
2093
|
+
|
|
2094
|
+
await repository.manager.query(sql, params);
|
|
2095
|
+
}
|
|
2096
|
+
|
|
1971
2097
|
@CaptureSpan()
|
|
1972
2098
|
protected async atomicIncrementColumnValueByOne(data: {
|
|
1973
2099
|
id: ObjectID;
|
|
@@ -236,12 +236,14 @@ export class Service extends DatabaseService<Model> {
|
|
|
236
236
|
data.agentVersion = extra.agentVersion;
|
|
237
237
|
}
|
|
238
238
|
|
|
239
|
-
|
|
239
|
+
/*
|
|
240
|
+
* Heartbeat write: a single-statement UPDATE with no hooks and no
|
|
241
|
+
* `version` bump, avoiding the hot-row Postgres lock convoy that the
|
|
242
|
+
* full updateOneById pipeline causes. See ServiceService.updateLastSeen.
|
|
243
|
+
*/
|
|
244
|
+
await this.updateColumnsByIdWithoutHooks({
|
|
240
245
|
id: hostId,
|
|
241
246
|
data: data,
|
|
242
|
-
props: {
|
|
243
|
-
isRoot: true,
|
|
244
|
-
},
|
|
245
247
|
});
|
|
246
248
|
}
|
|
247
249
|
|
|
@@ -271,12 +271,14 @@ export class Service extends DatabaseService<Model> {
|
|
|
271
271
|
data.networkCount = extra.networkCount;
|
|
272
272
|
}
|
|
273
273
|
|
|
274
|
-
|
|
274
|
+
/*
|
|
275
|
+
* Heartbeat write: a single-statement UPDATE with no hooks and no
|
|
276
|
+
* `version` bump, avoiding the hot-row Postgres lock convoy that the
|
|
277
|
+
* full updateOneById pipeline causes. See ServiceService.updateLastSeen.
|
|
278
|
+
*/
|
|
279
|
+
await this.updateColumnsByIdWithoutHooks({
|
|
275
280
|
id: clusterId,
|
|
276
281
|
data: data,
|
|
277
|
-
props: {
|
|
278
|
-
isRoot: true,
|
|
279
|
-
},
|
|
280
282
|
});
|
|
281
283
|
}
|
|
282
284
|
|
|
@@ -309,12 +309,14 @@ export class Service extends DatabaseService<Model> {
|
|
|
309
309
|
data.cloudAccountId = extra.cloudAccountId;
|
|
310
310
|
}
|
|
311
311
|
|
|
312
|
-
|
|
312
|
+
/*
|
|
313
|
+
* Heartbeat write: a single-statement UPDATE with no hooks and no
|
|
314
|
+
* `version` bump, avoiding the hot-row Postgres lock convoy that the
|
|
315
|
+
* full updateOneById pipeline causes. See ServiceService.updateLastSeen.
|
|
316
|
+
*/
|
|
317
|
+
await this.updateColumnsByIdWithoutHooks({
|
|
313
318
|
id: hostId,
|
|
314
319
|
data: data,
|
|
315
|
-
props: {
|
|
316
|
-
isRoot: true,
|
|
317
|
-
},
|
|
318
320
|
});
|
|
319
321
|
}
|
|
320
322
|
|