@twin.org/entity-storage-connector-mysql 0.9.1-next.7 → 0.9.1-next.8

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.
@@ -1 +1 @@
1
- {"version":3,"file":"IMySqlEntityStorageConnectorConfig.js","sourceRoot":"","sources":["../../../src/models/IMySqlEntityStorageConnectorConfig.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\n\n/**\n * Configuration for the MySql Entity Storage Connector.\n */\nexport interface IMySqlEntityStorageConnectorConfig {\n\t/**\n\t * The host for the MySql instance.\n\t */\n\thost: string;\n\n\t/**\n\t * The port for the MySql instance.\n\t */\n\tport?: number;\n\n\t/**\n\t * The user for the MySql instance.\n\t */\n\tuser: string;\n\n\t/**\n\t * The password for the MySql instance.\n\t */\n\tpassword: string;\n\n\t/**\n\t * The name of the database to be used.\n\t */\n\tdatabase: string;\n\n\t/**\n\t * The name of the table to be used.\n\t */\n\ttableName: string;\n\n\t/**\n\t * Optional connection pool configuration.\n\t */\n\tpool?: {\n\t\t/**\n\t\t * Maximum number of connections in pool.\n\t\t * @default 10\n\t\t */\n\t\tconnectionLimit?: number;\n\n\t\t/**\n\t\t * Maximum number of idle connections.\n\t\t * @default 10\n\t\t */\n\t\tmaxIdle?: number;\n\n\t\t/**\n\t\t * Time in ms before removing idle connection.\n\t\t * @default 60000 (1 minute)\n\t\t */\n\t\tidleTimeout?: number;\n\n\t\t/**\n\t\t * Enable TCP keep-alive.\n\t\t * @default true\n\t\t */\n\t\tenableKeepAlive?: boolean;\n\n\t\t/**\n\t\t * Wait for available connection when pool is full.\n\t\t * @default true\n\t\t */\n\t\twaitForConnections?: boolean;\n\n\t\t/**\n\t\t * Maximum queued requests (0 = unlimited).\n\t\t * @default 0\n\t\t */\n\t\tqueueLimit?: number;\n\t};\n}\n"]}
1
+ {"version":3,"file":"IMySqlEntityStorageConnectorConfig.js","sourceRoot":"","sources":["../../../src/models/IMySqlEntityStorageConnectorConfig.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\n\n/**\n * Configuration for the MySql Entity Storage Connector.\n */\nexport interface IMySqlEntityStorageConnectorConfig {\n\t/**\n\t * The host for the MySql instance.\n\t */\n\thost: string;\n\n\t/**\n\t * The port for the MySql instance.\n\t */\n\tport?: number;\n\n\t/**\n\t * The user for the MySql instance.\n\t */\n\tuser: string;\n\n\t/**\n\t * The password for the MySql instance.\n\t */\n\tpassword: string;\n\n\t/**\n\t * The name of the database to be used.\n\t */\n\tdatabase: string;\n\n\t/**\n\t * The name of the table to be used.\n\t */\n\ttableName: string;\n\n\t/**\n\t * Optional connection pool configuration.\n\t */\n\tpool?: {\n\t\t/**\n\t\t * Maximum number of connections in pool.\n\t\t * @default 10\n\t\t */\n\t\tconnectionLimit?: number;\n\n\t\t/**\n\t\t * Maximum number of idle connections.\n\t\t * @default 10\n\t\t */\n\t\tmaxIdle?: number;\n\n\t\t/**\n\t\t * Time in ms before removing idle connection.\n\t\t * @default 60000 (1 minute)\n\t\t */\n\t\tidleTimeout?: number;\n\n\t\t/**\n\t\t * Enable TCP keep-alive.\n\t\t * @default true\n\t\t */\n\t\tenableKeepAlive?: boolean;\n\n\t\t/**\n\t\t * Wait for available connection when pool is full.\n\t\t * @default true\n\t\t */\n\t\twaitForConnections?: boolean;\n\n\t\t/**\n\t\t * Maximum queued requests (0 = unlimited).\n\t\t * @default 0\n\t\t */\n\t\tqueueLimit?: number;\n\t};\n\n\t/**\n\t * Maximum milliseconds to wait for the per-directory write lock before throwing.\n\t */\n\tmutexTimeoutMs?: number;\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  // Copyright 2024 IOTA Stiftung.
2
2
  // SPDX-License-Identifier: Apache-2.0.
3
3
  import { ContextIdHelper, ContextIdStore } from "@twin.org/context";
4
- import { BaseError, Coerce, ComponentFactory, GeneralError, Guards, HealthStatus, Is, ObjectHelper, SharedStore, Validation } from "@twin.org/core";
4
+ import { BaseError, Coerce, ComponentFactory, GeneralError, Guards, HealthStatus, Is, Mutex, ObjectHelper, SharedStore, Validation } from "@twin.org/core";
5
5
  import { ComparisonOperator, EntitySchemaFactory, EntitySchemaHelper, EntitySchemaPropertyType, LogicalOperator, SortDirection } from "@twin.org/entity";
6
6
  import { EntityStorageHelper } from "@twin.org/entity-storage-models";
7
7
  import { createPool } from "mysql2/promise";
@@ -58,6 +58,11 @@ export class MySqlEntityStorageConnector {
58
58
  * @internal
59
59
  */
60
60
  _primaryKeyProperty;
61
+ /**
62
+ * Milliseconds to wait for the directory lock before throwing.
63
+ * @internal
64
+ */
65
+ _mutexTimeoutMs;
61
66
  /**
62
67
  * Create a new instance of MySqlEntityStorageConnector.
63
68
  * @param options The options for the connector.
@@ -76,6 +81,7 @@ export class MySqlEntityStorageConnector {
76
81
  this._partitionContextIds = options.partitionContextIds;
77
82
  this._primaryKeyProperty = EntitySchemaHelper.getPrimaryKey(this._entitySchema);
78
83
  this._config = options.config;
84
+ this._mutexTimeoutMs = Coerce.integer(options.config.mutexTimeoutMs);
79
85
  }
80
86
  /**
81
87
  * Returns the class name of the component.
@@ -90,7 +96,8 @@ export class MySqlEntityStorageConnector {
90
96
  */
91
97
  async health() {
92
98
  try {
93
- await this.getPool().query(`SELECT 1 FROM \`${this._config.database}\`.\`${this._config.tableName}\` LIMIT 0`);
99
+ const pool = await this.getPool();
100
+ await pool.query(`SELECT 1 FROM \`${this._config.database}\`.\`${this._config.tableName}\` LIMIT 0`);
94
101
  return [
95
102
  {
96
103
  source: MySqlEntityStorageConnector.CLASS_NAME,
@@ -127,7 +134,7 @@ export class MySqlEntityStorageConnector {
127
134
  async bootstrap(nodeLoggingComponentType) {
128
135
  const nodeLogging = ComponentFactory.getIfExists(nodeLoggingComponentType);
129
136
  try {
130
- const pool = this.getPool();
137
+ const pool = await this.getPool();
131
138
  const databaseExists = await this.databaseExists();
132
139
  if (!databaseExists) {
133
140
  await nodeLogging?.log({
@@ -203,20 +210,30 @@ export class MySqlEntityStorageConnector {
203
210
  if (this._pool) {
204
211
  const poolConfig = this.createPoolConfig();
205
212
  const poolId = `${poolConfig.host}|${poolConfig.port}|${poolConfig.user}`;
206
- const sharedPools = SharedStore.get("mySqlPools", () => ({}));
207
- if (sharedPools[poolId]) {
208
- // Decrease the use counter and close the pool if no longer used
209
- sharedPools[poolId].useCounter--;
210
- if (sharedPools[poolId].useCounter <= 0) {
211
- await sharedPools[poolId].pool.end();
212
- delete sharedPools[poolId];
213
+ try {
214
+ await Mutex.lock(`mySqlPools:${poolId}`, {
215
+ throwOnTimeout: true,
216
+ timeoutMs: this._mutexTimeoutMs
217
+ });
218
+ const sharedPools = SharedStore.get("mySqlPools", () => ({}));
219
+ if (sharedPools[poolId]) {
220
+ // Decrease the use counter and close the pool if no longer used
221
+ sharedPools[poolId].useCounter--;
222
+ if (sharedPools[poolId].useCounter <= 0) {
223
+ const poolInstance = sharedPools[poolId].pool;
224
+ await poolInstance.end();
225
+ delete sharedPools[poolId];
226
+ this._pool = undefined;
227
+ }
228
+ SharedStore.set("mySqlPools", sharedPools);
229
+ }
230
+ else {
231
+ // Pool was already ended by another connector; clear our stale reference.
213
232
  this._pool = undefined;
214
233
  }
215
- SharedStore.set("mySqlPools", sharedPools);
216
234
  }
217
- else {
218
- // Pool was already ended by another connector; clear our stale reference.
219
- this._pool = undefined;
235
+ finally {
236
+ Mutex.unlock(`mySqlPools:${poolId}`);
220
237
  }
221
238
  }
222
239
  }
@@ -233,7 +250,7 @@ export class MySqlEntityStorageConnector {
233
250
  const contextIds = await ContextIdStore.getContextIds();
234
251
  const partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);
235
252
  try {
236
- const pool = this.getPool();
253
+ const pool = await this.getPool();
237
254
  const whereClauses = [];
238
255
  const values = [];
239
256
  whereClauses.push(`\`${MySqlEntityStorageConnector._PARTITION_KEY}\` = ?`);
@@ -317,7 +334,7 @@ export class MySqlEntityStorageConnector {
317
334
  sql += ` (${keys.map(key => `\`${key}\``).join(", ")})`;
318
335
  sql += ` VALUES (${values.map(() => "?").join(", ")})`;
319
336
  sql += ` ON DUPLICATE KEY UPDATE ${keys.map(key => `\`${key}\` = VALUES(\`${key}\`)`).join(", ")};`;
320
- const pool = this.getPool();
337
+ const pool = await this.getPool();
321
338
  await pool.query(sql, values);
322
339
  }
323
340
  catch (err) {
@@ -366,7 +383,7 @@ export class MySqlEntityStorageConnector {
366
383
  sql += ` (${keys.map(key => `\`${key}\``).join(", ")})`;
367
384
  sql += ` VALUES ${entities.map(() => rowPlaceholder).join(", ")}`;
368
385
  sql += ` ON DUPLICATE KEY UPDATE ${keys.map(key => `\`${key}\` = VALUES(\`${key}\`)`).join(", ")};`;
369
- const pool = this.getPool();
386
+ const pool = await this.getPool();
370
387
  await pool.query(sql, allValues);
371
388
  }
372
389
  catch (err) {
@@ -381,7 +398,7 @@ export class MySqlEntityStorageConnector {
381
398
  const contextIds = await ContextIdStore.getContextIds();
382
399
  const partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);
383
400
  try {
384
- const pool = this.getPool();
401
+ const pool = await this.getPool();
385
402
  await pool.query(`DELETE FROM \`${this._config.database}\`.\`${this._config.tableName}\` WHERE \`${MySqlEntityStorageConnector._PARTITION_KEY}\` = ?`, [partitionKey ?? MySqlEntityStorageConnector._PARTITION_KEY_VALUE]);
386
403
  }
387
404
  catch (err) {
@@ -400,7 +417,7 @@ export class MySqlEntityStorageConnector {
400
417
  const contextIds = await ContextIdStore.getContextIds();
401
418
  const partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);
402
419
  try {
403
- const pool = this.getPool();
420
+ const pool = await this.getPool();
404
421
  const itemData = await this.get(id, undefined, conditions);
405
422
  if (Is.notEmpty(itemData)) {
406
423
  const values = [];
@@ -441,7 +458,7 @@ export class MySqlEntityStorageConnector {
441
458
  });
442
459
  try {
443
460
  if (await this.tableExists()) {
444
- const pool = this.getPool();
461
+ const pool = await this.getPool();
445
462
  await pool.query(`DROP TABLE \`${this._config.database}\`.\`${this._config.tableName}\`;`);
446
463
  await this.waitForTableNotExists();
447
464
  }
@@ -475,7 +492,7 @@ export class MySqlEntityStorageConnector {
475
492
  const contextIds = await ContextIdStore.getContextIds();
476
493
  const partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);
477
494
  try {
478
- const pool = this.getPool();
495
+ const pool = await this.getPool();
479
496
  const sql = `DELETE FROM \`${this._config.database}\`.\`${this._config.tableName}\` WHERE \`${MySqlEntityStorageConnector._PARTITION_KEY}\` = ? AND \`${String(this._primaryKeyProperty.property)}\` IN (?)`;
480
497
  await pool.query(sql, [
481
498
  partitionKey ?? MySqlEntityStorageConnector._PARTITION_KEY_VALUE,
@@ -526,7 +543,7 @@ export class MySqlEntityStorageConnector {
526
543
  sql += ` WHERE ${whereClauses.join(" AND ")}`;
527
544
  }
528
545
  sql += ` ${orderByClause} LIMIT ${returnSize + 1} OFFSET ${startIndex}`;
529
- const pool = this.getPool();
546
+ const pool = await this.getPool();
530
547
  const [rows] = (await pool.query(sql, values)) ?? [];
531
548
  const hasMore = Is.array(rows) && rows.length > returnSize;
532
549
  const resultRows = hasMore ? rows.slice(0, returnSize) : rows;
@@ -555,7 +572,7 @@ export class MySqlEntityStorageConnector {
555
572
  EntityStorageHelper.validateConditionProperties(this._entitySchema, conditions);
556
573
  let sql;
557
574
  try {
558
- const pool = this.getPool();
575
+ const pool = await this.getPool();
559
576
  const contextIds = await ContextIdStore.getContextIds();
560
577
  const partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);
561
578
  const { whereClauses, values } = this.buildWhereClause(conditions, partitionKey);
@@ -579,7 +596,7 @@ export class MySqlEntityStorageConnector {
579
596
  return [];
580
597
  }
581
598
  try {
582
- const pool = this.getPool();
599
+ const pool = await this.getPool();
583
600
  const [rows] = await pool.query(`SELECT DISTINCT \`${MySqlEntityStorageConnector._PARTITION_KEY}\` FROM \`${this._config.database}\`.\`${this._config.tableName}\``);
584
601
  return rows
585
602
  .map(row => row[MySqlEntityStorageConnector._PARTITION_KEY])
@@ -617,7 +634,7 @@ export class MySqlEntityStorageConnector {
617
634
  // Teardown the existing table with the original name to free up the name for the new table
618
635
  await this.teardown(loggingComponentType);
619
636
  // RENAME TABLE is an atomic metadata-only operation in MySQL — no data copying needed.
620
- const pool = this.getPool();
637
+ const pool = await this.getPool();
621
638
  await pool.query(`RENAME TABLE \`${targetConnector._config.database}\`.\`${targetConnector._config.tableName}\` TO \`${this._config.database}\`.\`${this._config.tableName}\``);
622
639
  const finalConnector = new MySqlEntityStorageConnector({
623
640
  entitySchema: targetConnector._entitySchemaName,
@@ -647,7 +664,7 @@ export class MySqlEntityStorageConnector {
647
664
  */
648
665
  async databaseExists() {
649
666
  try {
650
- const pool = this.getPool();
667
+ const pool = await this.getPool();
651
668
  const [rows] = await pool.query("SHOW DATABASES LIKE ?;", [this._config.database]);
652
669
  return Is.arrayValue(rows);
653
670
  }
@@ -692,7 +709,7 @@ export class MySqlEntityStorageConnector {
692
709
  */
693
710
  async tableExists() {
694
711
  try {
695
- const pool = this.getPool();
712
+ const pool = await this.getPool();
696
713
  const [rows] = await pool.query("SHOW TABLES FROM ?? LIKE ?", [
697
714
  this._config.database,
698
715
  this._config.tableName
@@ -736,22 +753,31 @@ export class MySqlEntityStorageConnector {
736
753
  * @returns The MySql connection pool.
737
754
  * @internal
738
755
  */
739
- getPool() {
756
+ async getPool() {
740
757
  if (!this._pool) {
741
758
  const poolConfig = this.createPoolConfig();
742
759
  const poolId = `${poolConfig.host}|${poolConfig.port}|${poolConfig.user}`;
743
- const sharedPools = SharedStore.get("mySqlPools", () => ({}));
744
- // If there is no pool for the id, create it
745
- if (!sharedPools[poolId]) {
746
- sharedPools[poolId] = {
747
- pool: createPool(poolConfig),
748
- useCounter: 0
749
- };
750
- SharedStore.set("mySqlPools", sharedPools);
760
+ try {
761
+ await Mutex.lock(`mySqlPools:${poolId}`, {
762
+ throwOnTimeout: true,
763
+ timeoutMs: this._mutexTimeoutMs
764
+ });
765
+ const sharedPools = SharedStore.get("mySqlPools", () => ({}));
766
+ // If there is no pool for the id, create it
767
+ if (!sharedPools[poolId]) {
768
+ sharedPools[poolId] = {
769
+ pool: createPool(poolConfig),
770
+ useCounter: 0
771
+ };
772
+ SharedStore.set("mySqlPools", sharedPools);
773
+ }
774
+ // Increase the use counter and return the pool
775
+ sharedPools[poolId].useCounter++;
776
+ this._pool = sharedPools[poolId].pool;
777
+ }
778
+ finally {
779
+ Mutex.unlock(`mySqlPools:${poolId}`);
751
780
  }
752
- // Increase the use counter and return the pool
753
- sharedPools[poolId].useCounter++;
754
- this._pool = sharedPools[poolId].pool;
755
781
  }
756
782
  return this._pool;
757
783
  }
@@ -1 +1 @@
1
- {"version":3,"file":"mysqlEntityStorageConnector.js","sourceRoot":"","sources":["../../src/mysqlEntityStorageConnector.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { ContextIdHelper, ContextIdStore, type IContextIds } from \"@twin.org/context\";\nimport {\n\tBaseError,\n\tCoerce,\n\tComponentFactory,\n\tGeneralError,\n\tGuards,\n\tHealthStatus,\n\ttype IHealth,\n\tIs,\n\ttype IValidationFailure,\n\tObjectHelper,\n\tSharedStore,\n\tValidation\n} from \"@twin.org/core\";\nimport {\n\tComparisonOperator,\n\ttype EntityCondition,\n\tEntitySchemaFactory,\n\tEntitySchemaHelper,\n\tEntitySchemaPropertyType,\n\ttype IComparator,\n\ttype IEntitySchema,\n\ttype IEntitySchemaProperty,\n\tLogicalOperator,\n\tSortDirection\n} from \"@twin.org/entity\";\nimport {\n\tEntityStorageHelper,\n\ttype IEntityStorageConnector,\n\ttype IEntityStorageMigrationConnector,\n\ttype IMigrationOptions\n} from \"@twin.org/entity-storage-models\";\nimport type { ILoggingComponent } from \"@twin.org/logging-models\";\nimport { nameof } from \"@twin.org/nameof\";\nimport { type Pool, type PoolOptions, createPool } from \"mysql2/promise\";\nimport type { IMySqlEntityStorageConnectorConfig } from \"./models/IMySqlEntityStorageConnectorConfig.js\";\nimport type { IMySqlEntityStorageConnectorConstructorOptions } from \"./models/IMySqlEntityStorageConnectorConstructorOptions.js\";\n\n/**\n * Class for performing entity storage operations using MySql.\n */\nexport class MySqlEntityStorageConnector<\n\tT = unknown\n> implements IEntityStorageMigrationConnector<T> {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<MySqlEntityStorageConnector>();\n\n\t/**\n\t * Limit the number of entities when finding.\n\t * @internal\n\t */\n\tprivate static readonly _DEFAULT_LIMIT: number = 40;\n\n\t/**\n\t * Partition id field name.\n\t * @internal\n\t */\n\tprivate static readonly _PARTITION_KEY: string = \"partitionId\";\n\n\t/**\n\t * Partition id field value.\n\t * @internal\n\t */\n\tprivate static readonly _PARTITION_KEY_VALUE: string = \"root\";\n\n\t/**\n\t * The name for the schema.\n\t * @internal\n\t */\n\tprivate readonly _entitySchemaName: string;\n\n\t/**\n\t * The schema for the entity.\n\t * @internal\n\t */\n\tprivate readonly _entitySchema: IEntitySchema<T>;\n\n\t/**\n\t * The keys to use from the context ids to create partitions.\n\t * @internal\n\t */\n\tprivate readonly _partitionContextIds?: string[];\n\n\t/**\n\t * The configuration for the connector.\n\t * @internal\n\t */\n\tprivate readonly _config: IMySqlEntityStorageConnectorConfig;\n\n\t/**\n\t * The connection pool for MySql.\n\t * @internal\n\t */\n\tprivate _pool?: Pool;\n\n\t/**\n\t * The primary key property.\n\t * @internal\n\t */\n\tprivate readonly _primaryKeyProperty: IEntitySchemaProperty<T>;\n\n\t/**\n\t * Create a new instance of MySqlEntityStorageConnector.\n\t * @param options The options for the connector.\n\t */\n\tconstructor(options: IMySqlEntityStorageConnectorConstructorOptions) {\n\t\tGuards.object(MySqlEntityStorageConnector.CLASS_NAME, nameof(options), options);\n\t\tGuards.stringValue(\n\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.entitySchema),\n\t\t\toptions.entitySchema\n\t\t);\n\t\tGuards.object<IMySqlEntityStorageConnectorConfig>(\n\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config),\n\t\t\toptions.config\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.host),\n\t\t\toptions.config.host\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.user),\n\t\t\toptions.config.user\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.password),\n\t\t\toptions.config.password\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.database),\n\t\t\toptions.config.database\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.tableName),\n\t\t\toptions.config.tableName\n\t\t);\n\n\t\tthis._entitySchemaName = options.entitySchema;\n\t\tthis._entitySchema = EntitySchemaFactory.get(options.entitySchema);\n\t\tthis._partitionContextIds = options.partitionContextIds;\n\t\tthis._primaryKeyProperty = EntitySchemaHelper.getPrimaryKey(this._entitySchema);\n\n\t\tthis._config = options.config;\n\t}\n\n\t/**\n\t * Returns the class name of the component.\n\t * @returns The class name of the component.\n\t */\n\tpublic className(): string {\n\t\treturn MySqlEntityStorageConnector.CLASS_NAME;\n\t}\n\n\t/**\n\t * Get the health of the component.\n\t * @returns The health of the component.\n\t */\n\tpublic async health(): Promise<IHealth[]> {\n\t\ttry {\n\t\t\tawait this.getPool().query(\n\t\t\t\t`SELECT 1 FROM \\`${this._config.database}\\`.\\`${this._config.tableName}\\` LIMIT 0`\n\t\t\t);\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tsource: MySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\tstatus: HealthStatus.Ok,\n\t\t\t\t\tdescription: \"healthDescription\",\n\t\t\t\t\tdata: { database: this._config.database, tableName: this._config.tableName }\n\t\t\t\t}\n\t\t\t];\n\t\t} catch {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tsource: MySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\tstatus: HealthStatus.Error,\n\t\t\t\t\tdescription: \"healthDescription\",\n\t\t\t\t\tmessage: \"connectionFailed\",\n\t\t\t\t\tdata: { database: this._config.database, tableName: this._config.tableName }\n\t\t\t\t}\n\t\t\t];\n\t\t}\n\t}\n\n\t/**\n\t * Get the schema for the entities.\n\t * @returns The schema for the entities.\n\t */\n\tpublic getSchema(): IEntitySchema {\n\t\treturn this._entitySchema as IEntitySchema;\n\t}\n\n\t/**\n\t * Initialize the MySql environment.\n\t * @param nodeLoggingComponentType Optional type of the logging component.\n\t * @returns A promise that resolves to a boolean indicating success.\n\t */\n\tpublic async bootstrap(nodeLoggingComponentType?: string): Promise<boolean> {\n\t\tconst nodeLogging = ComponentFactory.getIfExists<ILoggingComponent>(nodeLoggingComponentType);\n\n\t\ttry {\n\t\t\tconst pool = this.getPool();\n\n\t\t\tconst databaseExists = await this.databaseExists();\n\t\t\tif (!databaseExists) {\n\t\t\t\tawait nodeLogging?.log({\n\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\tsource: MySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\tmessage: \"databaseCreating\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tdatabaseName: this._config.database\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tawait pool.query(`CREATE DATABASE IF NOT EXISTS \\`${this._config.database}\\``);\n\n\t\t\t\tawait this.waitForDatabaseExists();\n\t\t\t} else {\n\t\t\t\tawait nodeLogging?.log({\n\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\tsource: MySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\tmessage: \"databaseExists\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tdatabaseName: this._config.database\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst tableExists = await this.tableExists();\n\t\t\tif (!tableExists) {\n\t\t\t\tawait nodeLogging?.log({\n\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\tsource: MySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\tmessage: \"tableCreating\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\ttableName: this._config.tableName\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tawait pool.query(\n\t\t\t\t\t`CREATE TABLE IF NOT EXISTS \\`${this._config.database}\\`.\\`${this._config.tableName}\\` (${this.mapMySqlProperties()})`\n\t\t\t\t);\n\n\t\t\t\tawait this.waitForTableExists();\n\t\t\t} else {\n\t\t\t\tawait nodeLogging?.log({\n\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\tsource: MySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\tmessage: \"tableExists\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\ttableName: this._config.tableName\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tawait nodeLogging?.log({\n\t\t\t\tlevel: \"error\",\n\t\t\t\tsource: MySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\tts: Date.now(),\n\t\t\t\tmessage: \"databaseCreateFailed\",\n\t\t\t\terror: BaseError.fromError(error),\n\t\t\t\tdata: {\n\t\t\t\t\tdatabaseName: this._config.database\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * The component needs to be stopped when the node is closed.\n\t * @param nodeLoggingComponentType The node logging component type.\n\t * @returns Nothing.\n\t */\n\tpublic async stop(nodeLoggingComponentType?: string): Promise<void> {\n\t\tif (this._pool) {\n\t\t\tconst poolConfig = this.createPoolConfig();\n\t\t\tconst poolId = `${poolConfig.host}|${poolConfig.port}|${poolConfig.user}`;\n\n\t\t\tconst sharedPools = SharedStore.get<{ [id: string]: { pool: Pool; useCounter: number } }>(\n\t\t\t\t\"mySqlPools\",\n\t\t\t\t() => ({})\n\t\t\t);\n\t\t\tif (sharedPools[poolId]) {\n\t\t\t\t// Decrease the use counter and close the pool if no longer used\n\t\t\t\tsharedPools[poolId].useCounter--;\n\t\t\t\tif (sharedPools[poolId].useCounter <= 0) {\n\t\t\t\t\tawait sharedPools[poolId].pool.end();\n\t\t\t\t\tdelete sharedPools[poolId];\n\t\t\t\t\tthis._pool = undefined;\n\t\t\t\t}\n\t\t\t\tSharedStore.set(\"mySqlPools\", sharedPools);\n\t\t\t} else {\n\t\t\t\t// Pool was already ended by another connector; clear our stale reference.\n\t\t\t\tthis._pool = undefined;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Get an entity from MySql.\n\t * @param id The id of the entity to get, or the index value if secondaryIndex is set.\n\t * @param secondaryIndex Get the item using a secondary index.\n\t * @param conditions The optional conditions to match for the entities.\n\t * @returns The object if it can be found or undefined.\n\t */\n\tpublic async get(\n\t\tid: string,\n\t\tsecondaryIndex?: keyof T,\n\t\tconditions?: { property: keyof T; value: unknown }[]\n\t): Promise<T | undefined> {\n\t\tGuards.stringValue(MySqlEntityStorageConnector.CLASS_NAME, nameof(id), id);\n\n\t\tEntityStorageHelper.validateConditions(this._entitySchema, conditions);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\ttry {\n\t\t\tconst pool = this.getPool();\n\n\t\t\tconst whereClauses: string[] = [];\n\t\t\tconst values: unknown[] = [];\n\n\t\t\twhereClauses.push(`\\`${MySqlEntityStorageConnector._PARTITION_KEY}\\` = ?`);\n\t\t\tvalues.push(partitionKey ?? MySqlEntityStorageConnector._PARTITION_KEY_VALUE);\n\n\t\t\tif (secondaryIndex) {\n\t\t\t\twhereClauses.push(`\\`${String(secondaryIndex)}\\` = ?`);\n\t\t\t} else {\n\t\t\t\twhereClauses.push(`\\`${String(this._primaryKeyProperty.property)}\\` = ?`);\n\t\t\t}\n\t\t\tvalues.push(id);\n\n\t\t\tif (Is.arrayValue(conditions)) {\n\t\t\t\tfor (const condition of conditions) {\n\t\t\t\t\twhereClauses.push(`\\`${String(condition.property)}\\` = ?`);\n\t\t\t\t\tvalues.push(condition.value);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst query = `SELECT * FROM \\`${this._config.database}\\`.\\`${this._config.tableName}\\` WHERE ${whereClauses.join(\" AND \")} LIMIT 1`;\n\t\t\tconst [rows] = await pool.query(query, values);\n\n\t\t\tif (Is.array(rows) && rows.length === 1) {\n\t\t\t\tconst item = EntityStorageHelper.unPrepareEntity<T>(rows[0] as T, [\n\t\t\t\t\tMySqlEntityStorageConnector._PARTITION_KEY\n\t\t\t\t]);\n\t\t\t\treturn this.coerceEntityTypes(item) as T;\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"getFailed\",\n\t\t\t\t{\n\t\t\t\t\tid\n\t\t\t\t},\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Set an entity.\n\t * @param entity The entity to set.\n\t * @param conditions The optional conditions to match for the entities.\n\t * @returns The id of the entity.\n\t */\n\tpublic async set(entity: T, conditions?: { property: keyof T; value: unknown }[]): Promise<void> {\n\t\tGuards.object<T>(MySqlEntityStorageConnector.CLASS_NAME, nameof(entity), entity);\n\t\tEntityStorageHelper.validateConditions(this._entitySchema, conditions);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tconst prepared = EntityStorageHelper.prepareEntity(\n\t\t\tentity,\n\t\t\tthis._entitySchema,\n\t\t\t[\n\t\t\t\t{\n\t\t\t\t\tproperty: MySqlEntityStorageConnector._PARTITION_KEY,\n\t\t\t\t\tvalue: partitionKey ?? MySqlEntityStorageConnector._PARTITION_KEY_VALUE\n\t\t\t\t}\n\t\t\t],\n\t\t\t{ nullBehavior: \"nullify\" }\n\t\t);\n\n\t\tconst id = prepared[this._primaryKeyProperty.property] as unknown as string;\n\n\t\ttry {\n\t\t\tif (Is.arrayValue(conditions)) {\n\t\t\t\tconst itemData = await this.get(id);\n\t\t\t\tif (Is.notEmpty(itemData) && !this.verifyConditions(conditions, itemData as T)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst props = [...(this._entitySchema.properties ?? [])];\n\t\t\tprops.unshift({\n\t\t\t\tproperty: MySqlEntityStorageConnector._PARTITION_KEY as keyof T,\n\t\t\t\ttype: EntitySchemaPropertyType.String\n\t\t\t});\n\n\t\t\tconst keys: string[] = [];\n\t\t\tconst values = [];\n\n\t\t\tfor (const prop of props) {\n\t\t\t\tkeys.push(prop.property as string);\n\t\t\t\tconst val = prepared[prop.property];\n\t\t\t\tif (val === null || val === undefined) {\n\t\t\t\t\tvalues.push(null);\n\t\t\t\t} else if (\n\t\t\t\t\tprop.type === EntitySchemaPropertyType.Object ||\n\t\t\t\t\tprop.type === EntitySchemaPropertyType.Array\n\t\t\t\t) {\n\t\t\t\t\tvalues.push(JSON.stringify(val));\n\t\t\t\t} else {\n\t\t\t\t\tvalues.push(val);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet sql = `INSERT INTO \\`${this._config.database}\\`.\\`${this._config.tableName}\\``;\n\t\t\tsql += ` (${keys.map(key => `\\`${key}\\``).join(\", \")})`;\n\t\t\tsql += ` VALUES (${values.map(() => \"?\").join(\", \")})`;\n\t\t\tsql += ` ON DUPLICATE KEY UPDATE ${keys.map(key => `\\`${key}\\` = VALUES(\\`${key}\\`)`).join(\", \")};`;\n\n\t\t\tconst pool = this.getPool();\n\t\t\tawait pool.query(sql, values);\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"setFailed\",\n\t\t\t\t{\n\t\t\t\t\tid\n\t\t\t\t},\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Set multiple entities in a batch.\n\t * @param entities The entities to set.\n\t * @returns Nothing.\n\t */\n\tpublic async setBatch(entities: T[]): Promise<void> {\n\t\tGuards.arrayValue(MySqlEntityStorageConnector.CLASS_NAME, nameof(entities), entities);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tconst preparedEntities = entities.map(entity =>\n\t\t\tEntityStorageHelper.prepareEntity(\n\t\t\t\tentity,\n\t\t\t\tthis._entitySchema,\n\t\t\t\t[\n\t\t\t\t\t{\n\t\t\t\t\t\tproperty: MySqlEntityStorageConnector._PARTITION_KEY,\n\t\t\t\t\t\tvalue: partitionKey ?? MySqlEntityStorageConnector._PARTITION_KEY_VALUE\n\t\t\t\t\t}\n\t\t\t\t],\n\t\t\t\t{ nullBehavior: \"nullify\" }\n\t\t\t)\n\t\t);\n\n\t\ttry {\n\t\t\tconst props = [...(this._entitySchema.properties ?? [])];\n\t\t\tprops.unshift({\n\t\t\t\tproperty: MySqlEntityStorageConnector._PARTITION_KEY as keyof T,\n\t\t\t\ttype: EntitySchemaPropertyType.String\n\t\t\t});\n\n\t\t\tconst keys = props.map(p => p.property as string);\n\t\t\tconst allValues: unknown[] = [];\n\n\t\t\tfor (const prepared of preparedEntities) {\n\t\t\t\tfor (const prop of props) {\n\t\t\t\t\tconst val = prepared[prop.property];\n\t\t\t\t\tif (\n\t\t\t\t\t\tprop.type === EntitySchemaPropertyType.Object ||\n\t\t\t\t\t\tprop.type === EntitySchemaPropertyType.Array\n\t\t\t\t\t) {\n\t\t\t\t\t\tallValues.push(Is.empty(val) ? null : JSON.stringify(val));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tallValues.push(Is.empty(val) ? null : val);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst rowPlaceholder = `(${keys.map(() => \"?\").join(\", \")})`;\n\t\t\tlet sql = `INSERT INTO \\`${this._config.database}\\`.\\`${this._config.tableName}\\``;\n\t\t\tsql += ` (${keys.map(key => `\\`${key}\\``).join(\", \")})`;\n\t\t\tsql += ` VALUES ${entities.map(() => rowPlaceholder).join(\", \")}`;\n\t\t\tsql += ` ON DUPLICATE KEY UPDATE ${keys.map(key => `\\`${key}\\` = VALUES(\\`${key}\\`)`).join(\", \")};`;\n\n\t\t\tconst pool = this.getPool();\n\t\t\tawait pool.query(sql, allValues);\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"setBatchFailed\",\n\t\t\t\tundefined,\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Empty the entity storage.\n\t * @returns Nothing.\n\t */\n\tpublic async empty(): Promise<void> {\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\ttry {\n\t\t\tconst pool = this.getPool();\n\t\t\tawait pool.query(\n\t\t\t\t`DELETE FROM \\`${this._config.database}\\`.\\`${this._config.tableName}\\` WHERE \\`${MySqlEntityStorageConnector._PARTITION_KEY}\\` = ?`,\n\t\t\t\t[partitionKey ?? MySqlEntityStorageConnector._PARTITION_KEY_VALUE]\n\t\t\t);\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(MySqlEntityStorageConnector.CLASS_NAME, \"emptyFailed\", undefined, err);\n\t\t}\n\t}\n\n\t/**\n\t * Remove the entity.\n\t * @param id The id of the entity to remove.\n\t * @param conditions The optional conditions to match for the entities.\n\t * @returns Nothing.\n\t */\n\tpublic async remove(\n\t\tid: string,\n\t\tconditions?: { property: keyof T; value: unknown }[]\n\t): Promise<void> {\n\t\tGuards.stringValue(MySqlEntityStorageConnector.CLASS_NAME, nameof(id), id);\n\n\t\tEntityStorageHelper.validateConditions(this._entitySchema, conditions);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\ttry {\n\t\t\tconst pool = this.getPool();\n\n\t\t\tconst itemData = await this.get(id, undefined, conditions);\n\t\t\tif (Is.notEmpty(itemData)) {\n\t\t\t\tconst values: unknown[] = [];\n\t\t\t\tconst whereClauses: string[] = [];\n\n\t\t\t\twhereClauses.push(`\\`${this._primaryKeyProperty.property as string}\\` = ?`);\n\t\t\t\tvalues.push(id);\n\n\t\t\t\twhereClauses.push(`\\`${MySqlEntityStorageConnector._PARTITION_KEY}\\` = ?`);\n\t\t\t\tvalues.push(partitionKey ?? MySqlEntityStorageConnector._PARTITION_KEY_VALUE);\n\n\t\t\t\tif (Is.arrayValue(conditions)) {\n\t\t\t\t\twhereClauses.push(\n\t\t\t\t\t\t...conditions.map(condition => {\n\t\t\t\t\t\t\tvalues.push(condition.value);\n\t\t\t\t\t\t\treturn `\\`${String(condition.property)}\\` = ?`;\n\t\t\t\t\t\t})\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tconst query = `DELETE FROM \\`${this._config.database}\\`.\\`${this._config.tableName}\\` WHERE ${whereClauses.join(\" AND \")}`;\n\t\t\t\tawait pool.query(query, values);\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"removeFailed\",\n\t\t\t\t{\n\t\t\t\t\tid\n\t\t\t\t},\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Teardown the entity storage by dropping the table.\n\t * @param nodeLoggingComponentType The node logging component type.\n\t * @returns True if the teardown process was successful.\n\t */\n\tpublic async teardown(nodeLoggingComponentType?: string): Promise<boolean> {\n\t\tconst nodeLogging = ComponentFactory.getIfExists<ILoggingComponent>(nodeLoggingComponentType);\n\n\t\tawait nodeLogging?.log({\n\t\t\tlevel: \"info\",\n\t\t\tsource: MySqlEntityStorageConnector.CLASS_NAME,\n\t\t\tts: Date.now(),\n\t\t\tmessage: \"tableDropping\",\n\t\t\tdata: { tableName: this._config.tableName }\n\t\t});\n\n\t\ttry {\n\t\t\tif (await this.tableExists()) {\n\t\t\t\tconst pool = this.getPool();\n\t\t\t\tawait pool.query(`DROP TABLE \\`${this._config.database}\\`.\\`${this._config.tableName}\\`;`);\n\t\t\t\tawait this.waitForTableNotExists();\n\t\t\t}\n\n\t\t\tawait nodeLogging?.log({\n\t\t\t\tlevel: \"info\",\n\t\t\t\tsource: MySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\tts: Date.now(),\n\t\t\t\tmessage: \"tableDropped\",\n\t\t\t\tdata: { tableName: this._config.tableName }\n\t\t\t});\n\n\t\t\treturn true;\n\t\t} catch (err) {\n\t\t\tawait nodeLogging?.log({\n\t\t\t\tlevel: \"error\",\n\t\t\t\tsource: MySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\tts: Date.now(),\n\t\t\t\tmessage: \"teardownFailed\",\n\t\t\t\terror: BaseError.fromError(err)\n\t\t\t});\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Remove multiple entities by their primary key IDs.\n\t * @param ids The ids of the entities to remove.\n\t * @returns Nothing.\n\t */\n\tpublic async removeBatch(ids: string[]): Promise<void> {\n\t\tGuards.arrayValue(MySqlEntityStorageConnector.CLASS_NAME, nameof(ids), ids);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\ttry {\n\t\t\tconst pool = this.getPool();\n\t\t\tconst sql = `DELETE FROM \\`${this._config.database}\\`.\\`${this._config.tableName}\\` WHERE \\`${MySqlEntityStorageConnector._PARTITION_KEY}\\` = ? AND \\`${String(this._primaryKeyProperty.property)}\\` IN (?)`;\n\t\t\tawait pool.query(sql, [\n\t\t\t\tpartitionKey ?? MySqlEntityStorageConnector._PARTITION_KEY_VALUE,\n\t\t\t\tids\n\t\t\t]);\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"removeBatchFailed\",\n\t\t\t\tundefined,\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Find all the entities which match the conditions.\n\t * @param conditions The conditions to match for the entities.\n\t * @param sortProperties The optional sort order.\n\t * @param properties The optional properties to return, defaults to all.\n\t * @param cursor The cursor to request the next chunk of entities.\n\t * @param limit The suggested number of entities to return in each chunk, in some scenarios can return a different amount.\n\t * @returns All the entities for the storage matching the conditions,\n\t * and a cursor which can be used to request more entities.\n\t */\n\tpublic async query(\n\t\tconditions?: EntityCondition<T>,\n\t\tsortProperties?: { property: keyof T; sortDirection: SortDirection }[],\n\t\tproperties?: (keyof T)[],\n\t\tcursor?: string,\n\t\tlimit?: number\n\t): Promise<{ entities: Partial<T>[]; cursor?: string }> {\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tEntityStorageHelper.validateSortProperties(this._entitySchema, sortProperties);\n\t\tEntityStorageHelper.validateProperties(this._entitySchema, properties);\n\t\tEntityStorageHelper.validateConditionProperties(this._entitySchema, conditions);\n\n\t\tif (!Is.empty(limit)) {\n\t\t\tconst validationFailures: IValidationFailure[] = [];\n\t\t\tValidation.integer(nameof(limit), limit, validationFailures, undefined, { minValue: 1 });\n\t\t\tValidation.asValidationError(\n\t\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"query\",\n\t\t\t\tvalidationFailures\n\t\t\t);\n\t\t}\n\n\t\tlet sql = \"\";\n\t\ttry {\n\t\t\tconst returnSize = limit ?? MySqlEntityStorageConnector._DEFAULT_LIMIT;\n\n\t\t\tlet orderByClause: string = \"\";\n\t\t\tif (Is.array(sortProperties)) {\n\t\t\t\tconst orderClauses: string[] = [];\n\t\t\t\tfor (const sortProperty of sortProperties) {\n\t\t\t\t\tconst direction = sortProperty.sortDirection === SortDirection.Ascending ? \"ASC\" : \"DESC\";\n\t\t\t\t\torderClauses.push(`\\`${String(sortProperty.property)}\\` ${direction}`);\n\t\t\t\t}\n\t\t\t\torderByClause = `ORDER BY ${orderClauses.join(\", \")}`;\n\t\t\t}\n\n\t\t\tconst { whereClauses, values } = this.buildWhereClause(conditions, partitionKey);\n\n\t\t\tconst startIndex = Coerce.number(cursor) ?? 0;\n\n\t\t\tsql = `SELECT ${properties ? properties.map(p => `\\`${String(p)}\\``).join(\", \") : \"*\"} FROM \\`${this._config.database}\\`.\\`${this._config.tableName}\\``;\n\t\t\tif (whereClauses.length > 0) {\n\t\t\t\tsql += ` WHERE ${whereClauses.join(\" AND \")}`;\n\t\t\t}\n\t\t\tsql += ` ${orderByClause} LIMIT ${returnSize + 1} OFFSET ${startIndex}`;\n\n\t\t\tconst pool = this.getPool();\n\t\t\tconst [rows] = (await pool.query(sql, values)) ?? [];\n\n\t\t\tconst hasMore = Is.array(rows) && rows.length > returnSize;\n\t\t\tconst resultRows = hasMore ? (rows as unknown[]).slice(0, returnSize) : rows;\n\t\t\tconst entities = resultRows as Partial<T>[];\n\t\t\tfor (let i = 0; i < entities.length; i++) {\n\t\t\t\tentities[i] = EntityStorageHelper.unPrepareEntity(entities[i], [\n\t\t\t\t\tMySqlEntityStorageConnector._PARTITION_KEY\n\t\t\t\t]);\n\t\t\t\tentities[i] = this.coerceEntityTypes(entities[i]);\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tentities,\n\t\t\t\tcursor: hasMore ? Coerce.string(startIndex + returnSize) : undefined\n\t\t\t};\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(MySqlEntityStorageConnector.CLASS_NAME, \"queryFailed\", { sql }, err);\n\t\t}\n\t}\n\n\t/**\n\t * Count all the entities which match the conditions.\n\t * @param conditions The optional conditions to match for the entities.\n\t * @returns The total count of entities in the storage.\n\t */\n\tpublic async count(conditions?: EntityCondition<T>): Promise<number> {\n\t\tEntityStorageHelper.validateConditionProperties(this._entitySchema, conditions);\n\n\t\tlet sql: string | undefined;\n\t\ttry {\n\t\t\tconst pool = this.getPool();\n\n\t\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\t\tconst partitionKey = ContextIdHelper.combinedContextKey(\n\t\t\t\tcontextIds,\n\t\t\t\tthis._partitionContextIds\n\t\t\t);\n\n\t\t\tconst { whereClauses, values } = this.buildWhereClause(conditions, partitionKey);\n\n\t\t\tsql = `SELECT COUNT(*) AS count FROM \\`${this._config.database}\\`.\\`${this._config.tableName}\\``;\n\t\t\tif (whereClauses.length > 0) {\n\t\t\t\tsql += ` WHERE ${whereClauses.join(\" AND \")}`;\n\t\t\t}\n\n\t\t\tconst [rows] = await pool.query(sql, values);\n\t\t\treturn Number((rows as { count: number }[])[0].count);\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(MySqlEntityStorageConnector.CLASS_NAME, \"countFailed\", { sql }, err);\n\t\t}\n\t}\n\n\t/**\n\t * Get all unique partition context ids present in the table.\n\t * @returns An array of context id objects, one per unique partition.\n\t */\n\tpublic async getPartitionContextIds(): Promise<IContextIds[]> {\n\t\tif (!Is.arrayValue(this._partitionContextIds)) {\n\t\t\treturn [];\n\t\t}\n\n\t\ttry {\n\t\t\tconst pool = this.getPool();\n\t\t\tconst [rows] = await pool.query(\n\t\t\t\t`SELECT DISTINCT \\`${MySqlEntityStorageConnector._PARTITION_KEY}\\` FROM \\`${this._config.database}\\`.\\`${this._config.tableName}\\``\n\t\t\t);\n\t\t\treturn (rows as { [key: string]: string }[])\n\t\t\t\t.map(row => row[MySqlEntityStorageConnector._PARTITION_KEY])\n\t\t\t\t.filter((id): id is string => Is.stringValue(id))\n\t\t\t\t.map(id => ContextIdHelper.shortSplit(this._partitionContextIds ?? [], id));\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"getPartitionContextIdsFailed\",\n\t\t\t\tundefined,\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Create the target connector for performing the migration using a temporary table.\n\t * @param newEntitySchema The name of the new entity schema to create the connector for.\n\t * @returns Connector for performing the migration.\n\t */\n\tpublic async createTargetConnector<U>(\n\t\tnewEntitySchema: string\n\t): Promise<IEntityStorageConnector<U>> {\n\t\tconst migrationTableName = `${this._config.tableName}Migration${Date.now()}`;\n\t\treturn new MySqlEntityStorageConnector<U>({\n\t\t\tentitySchema: newEntitySchema,\n\t\t\tconfig: {\n\t\t\t\t...this._config,\n\t\t\t\ttableName: migrationTableName\n\t\t\t},\n\t\t\tpartitionContextIds: this._partitionContextIds\n\t\t});\n\t}\n\n\t/**\n\t * Finalize the migration by dropping the source table and renaming the migration table to the original name.\n\t * @param targetConnector The connector holding the migrated data in a temporary table.\n\t * @param options The options to control how the migration is finalized.\n\t * @param loggingComponentType The logging component type to use during finalization.\n\t * @returns The final connector using the original table name with the new schema.\n\t */\n\tpublic async finalizeMigration<U>(\n\t\ttargetConnector: MySqlEntityStorageConnector<U>,\n\t\toptions?: IMigrationOptions,\n\t\tloggingComponentType?: string\n\t): Promise<MySqlEntityStorageConnector<U>> {\n\t\t// Teardown the existing table with the original name to free up the name for the new table\n\t\tawait this.teardown(loggingComponentType);\n\n\t\t// RENAME TABLE is an atomic metadata-only operation in MySQL — no data copying needed.\n\t\tconst pool = this.getPool();\n\t\tawait pool.query(\n\t\t\t`RENAME TABLE \\`${targetConnector._config.database}\\`.\\`${targetConnector._config.tableName}\\` TO \\`${this._config.database}\\`.\\`${this._config.tableName}\\``\n\t\t);\n\n\t\tconst finalConnector = new MySqlEntityStorageConnector<U>({\n\t\t\tentitySchema: targetConnector._entitySchemaName,\n\t\t\tconfig: this._config,\n\t\t\tpartitionContextIds: this._partitionContextIds\n\t\t});\n\n\t\tif (await finalConnector.bootstrap(loggingComponentType)) {\n\t\t\tawait targetConnector.stop();\n\t\t\treturn finalConnector;\n\t\t}\n\n\t\tthrow new GeneralError(\n\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\"finalizeMigrationFailedBootstrap\",\n\t\t\tundefined\n\t\t);\n\t}\n\n\t/**\n\t * Cleanup a failed or aborted migration by dropping the temporary migration table.\n\t * @param targetConnector The target connector to cleanup.\n\t * @param options The options to control how the migration is cleaned up.\n\t * @param loggingComponentType The optional component type to use for logging.\n\t * @returns A promise that resolves when the cleanup is complete.\n\t */\n\tpublic async cleanupMigration<U>(\n\t\ttargetConnector: IEntityStorageConnector<U> | undefined,\n\t\toptions?: IMigrationOptions,\n\t\tloggingComponentType?: string\n\t): Promise<void> {\n\t\t// If something failed the only thing to cleanup is the migration table\n\t\tawait targetConnector?.teardown?.(loggingComponentType);\n\t}\n\n\t/**\n\t * Check if the database exists.\n\t * @returns True if the database exists, false otherwise.\n\t */\n\tpublic async databaseExists(): Promise<boolean> {\n\t\ttry {\n\t\t\tconst pool = this.getPool();\n\t\t\tconst [rows] = await pool.query(\"SHOW DATABASES LIKE ?;\", [this._config.database]);\n\t\t\treturn Is.arrayValue(rows);\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Coerce MySQL raw row values back to proper TypeScript types based on the entity schema.\n\t * MySQL returns TINYINT(1) as 0/1 rather than false/true; this method converts those.\n\t * @param entity The raw entity row from MySQL.\n\t * @returns The entity with schema-correct types.\n\t * @internal\n\t */\n\tprivate coerceEntityTypes(entity: Partial<T>): Partial<T> {\n\t\tfor (const prop of this._entitySchema.properties ?? []) {\n\t\t\tconst value = entity[prop.property];\n\t\t\tif (prop.type === EntitySchemaPropertyType.Boolean && !Is.empty(value)) {\n\t\t\t\tObjectHelper.propertySet(entity, prop.property as string, Boolean(value));\n\t\t\t}\n\t\t}\n\t\treturn entity;\n\t}\n\n\t/**\n\t * Wait for a database to exist.\n\t * @returns Nothing.\n\t * @internal\n\t */\n\tprivate async waitForDatabaseExists(): Promise<void> {\n\t\tfor (let attempt = 0; attempt < 20; attempt++) {\n\t\t\tconst databaseExists = await this.databaseExists();\n\t\t\tif (databaseExists) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tawait new Promise(resolve => setTimeout(resolve, 250));\n\t\t}\n\t}\n\n\t/**\n\t * Check if the table exists.\n\t * @returns True if the table exists, false otherwise.\n\t * @internal\n\t */\n\tprivate async tableExists(): Promise<boolean> {\n\t\ttry {\n\t\t\tconst pool = this.getPool();\n\t\t\tconst [rows] = await pool.query(\"SHOW TABLES FROM ?? LIKE ?\", [\n\t\t\t\tthis._config.database,\n\t\t\t\tthis._config.tableName\n\t\t\t]);\n\t\t\treturn Is.arrayValue(rows);\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Wait for a table to exist.\n\t * @returns Nothing.\n\t * @internal\n\t */\n\tprivate async waitForTableExists(): Promise<void> {\n\t\tfor (let attempt = 0; attempt < 20; attempt++) {\n\t\t\tconst tableExists = await this.tableExists();\n\t\t\tif (tableExists) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tawait new Promise(resolve => setTimeout(resolve, 250));\n\t\t}\n\t}\n\n\t/**\n\t * Wait for a table to not exist.\n\t * @returns Nothing.\n\t * @internal\n\t */\n\tprivate async waitForTableNotExists(): Promise<void> {\n\t\tfor (let attempt = 0; attempt < 20; attempt++) {\n\t\t\tconst tableExists = await this.tableExists();\n\t\t\tif (!tableExists) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tawait new Promise(resolve => setTimeout(resolve, 250));\n\t\t}\n\t}\n\n\t/**\n\t * Get or create the connection pool.\n\t * @returns The MySql connection pool.\n\t * @internal\n\t */\n\tprivate getPool(): Pool {\n\t\tif (!this._pool) {\n\t\t\tconst poolConfig = this.createPoolConfig();\n\t\t\tconst poolId = `${poolConfig.host}|${poolConfig.port}|${poolConfig.user}`;\n\n\t\t\tconst sharedPools = SharedStore.get<{ [id: string]: { pool: Pool; useCounter: number } }>(\n\t\t\t\t\"mySqlPools\",\n\t\t\t\t() => ({})\n\t\t\t);\n\n\t\t\t// If there is no pool for the id, create it\n\t\t\tif (!sharedPools[poolId]) {\n\t\t\t\tsharedPools[poolId] = {\n\t\t\t\t\tpool: createPool(poolConfig),\n\t\t\t\t\tuseCounter: 0\n\t\t\t\t};\n\t\t\t\tSharedStore.set(\"mySqlPools\", sharedPools);\n\t\t\t}\n\t\t\t// Increase the use counter and return the pool\n\t\t\tsharedPools[poolId].useCounter++;\n\t\t\tthis._pool = sharedPools[poolId].pool;\n\t\t}\n\t\treturn this._pool;\n\t}\n\n\t/**\n\t * Create the connection pool configuration.\n\t * @returns The MySql pool configuration.\n\t * @internal\n\t */\n\tprivate createPoolConfig(): PoolOptions {\n\t\tconst poolConfig = this._config.pool ?? {};\n\n\t\treturn {\n\t\t\thost: this._config.host,\n\t\t\tport: this._config.port ?? 3306,\n\t\t\tuser: this._config.user,\n\t\t\tpassword: this._config.password,\n\n\t\t\tconnectionLimit: poolConfig.connectionLimit ?? 10,\n\t\t\tmaxIdle: poolConfig.maxIdle ?? 10,\n\t\t\tidleTimeout: poolConfig.idleTimeout ?? 60000,\n\t\t\tenableKeepAlive: poolConfig.enableKeepAlive ?? true,\n\t\t\tkeepAliveInitialDelay: 0,\n\t\t\twaitForConnections: poolConfig.waitForConnections ?? true,\n\t\t\tqueueLimit: poolConfig.queueLimit ?? 0\n\t\t};\n\t}\n\n\t/**\n\t * Build where clause arrays for a query, combining partition key and optional conditions.\n\t * @param conditions The optional entity conditions to include.\n\t * @param partitionKey The partition key value.\n\t * @returns The where clauses and bound values.\n\t * @internal\n\t */\n\tprivate buildWhereClause(\n\t\tconditions: EntityCondition<T> | undefined,\n\t\tpartitionKey: string | undefined\n\t): { whereClauses: string[]; values: unknown[] } {\n\t\tconst whereClauses: string[] = [];\n\t\tconst values: unknown[] = [];\n\n\t\tconst finalConditions: EntityCondition<T> = {\n\t\t\tconditions: [],\n\t\t\tlogicalOperator: LogicalOperator.And\n\t\t};\n\n\t\tfinalConditions.conditions.push({\n\t\t\tproperty: MySqlEntityStorageConnector._PARTITION_KEY,\n\t\t\tcomparison: ComparisonOperator.Equals,\n\t\t\tvalue: partitionKey ?? MySqlEntityStorageConnector._PARTITION_KEY_VALUE\n\t\t});\n\n\t\tif (!Is.empty(conditions)) {\n\t\t\tfinalConditions.conditions.push(conditions);\n\t\t}\n\n\t\tthis.buildQueryParameters(\"\", finalConditions, whereClauses, values);\n\n\t\treturn { whereClauses, values };\n\t}\n\n\t/**\n\t * Create an SQL condition clause.\n\t * @param objectPath The path for the nested object.\n\t * @param condition The conditions to create the query from.\n\t * @param whereClauses The where clauses to use in the query.\n\t * @param values The values to use in the query.\n\t * @internal\n\t */\n\tprivate buildQueryParameters(\n\t\tobjectPath: string,\n\t\tcondition: EntityCondition<T> | undefined,\n\t\twhereClauses: string[],\n\t\tvalues: unknown[]\n\t): void {\n\t\tif (Is.undefined(condition)) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (\"conditions\" in condition) {\n\t\t\tif (condition.conditions.length === 0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst joinConditions: string[] = condition.conditions.map(c => {\n\t\t\t\tconst subWhereClauses: string[] = [];\n\t\t\t\tconst subValues: unknown[] = [];\n\t\t\t\tthis.buildQueryParameters(objectPath, c, subWhereClauses, subValues);\n\t\t\t\tvalues.push(...subValues);\n\t\t\t\treturn subWhereClauses.join(\" AND \");\n\t\t\t});\n\n\t\t\tconst logicalOperator = this.mapConditionalOperator(condition.logicalOperator);\n\t\t\tconst queryClause = joinConditions.filter(j => j.length > 0).join(` ${logicalOperator} `);\n\n\t\t\tif (queryClause.length > 0) {\n\t\t\t\twhereClauses.push(`(${queryClause})`);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tconst schemaProp = this._entitySchema.properties?.find(p => p.property === condition.property);\n\t\tconst comparison = this.mapComparisonOperator(objectPath, condition, schemaProp?.type, values);\n\t\twhereClauses.push(comparison);\n\t}\n\n\t/**\n\t * Map the framework comparison operators to those in MySQL.\n\t * @param objectPath The prefix to use for the condition.\n\t * @param comparator The operator to map.\n\t * @param type The type of the property.\n\t * @param values The values to use in the query.\n\t * @returns The comparison expression.\n\t * @throws GeneralError if the comparison operator is not supported.\n\t * @internal\n\t */\n\tprivate mapComparisonOperator(\n\t\tobjectPath: string,\n\t\tcomparator: IComparator,\n\t\ttype: EntitySchemaPropertyType | undefined,\n\t\tvalues: unknown[]\n\t): string {\n\t\tlet prop = objectPath;\n\t\tif (prop.length > 0) {\n\t\t\tprop += \".\";\n\t\t}\n\n\t\tprop += comparator.property;\n\n\t\tif (comparator.comparison === ComparisonOperator.In) {\n\t\t\tconst inValues = Is.array(comparator.value) ? comparator.value : [comparator.value];\n\t\t\tif (inValues.length === 0) {\n\t\t\t\t// MySQL rejects `IN ()` as a syntax error — short-circuit to a condition\n\t\t\t\t// that is always false so the query returns zero rows cleanly (#141).\n\t\t\t\treturn \"1 = 0\";\n\t\t\t}\n\t\t\tvalues.push(...inValues.map(val => this.propertyToDbValue(val, type)));\n\t\t\tconst placeholders = inValues.map(() => \"?\").join(\", \");\n\t\t\treturn `\\`${prop}\\` IN (${placeholders})`;\n\t\t}\n\n\t\t// null/undefined must use IS NULL / IS NOT NULL — never a parameterised placeholder.\n\t\t// Passing undefined through propertyToDbValue() coerces it to NaN for number fields\n\t\t// (Number(undefined) === NaN), and null coerces to 0 (Number(null) === 0), both of\n\t\t// which produce semantically wrong or invalid SQL.\n\t\tif (comparator.value === null || comparator.value === undefined) {\n\t\t\tif (\n\t\t\t\tcomparator.comparison === ComparisonOperator.Equals ||\n\t\t\t\tcomparator.comparison === ComparisonOperator.NotEquals\n\t\t\t) {\n\t\t\t\tconst nullCheck =\n\t\t\t\t\tcomparator.comparison === ComparisonOperator.Equals ? \"IS NULL\" : \"IS NOT NULL\";\n\n\t\t\t\tif (comparator.property.split(\".\").length > 1) {\n\t\t\t\t\tconst rootProp = comparator.property.split(\".\")[0];\n\t\t\t\t\tconst nestedPath = comparator.property.split(\".\").slice(1).join(\".\");\n\t\t\t\t\tconst rootSchema = this._entitySchema.properties?.find(p => p.property === rootProp);\n\t\t\t\t\tconst isArray = rootSchema?.type === EntitySchemaPropertyType.Array;\n\t\t\t\t\tconst jsonPath = isArray ? `$[*].${nestedPath}` : `$.${nestedPath}`;\n\t\t\t\t\tconst jsonExpr = `JSON_UNQUOTE(JSON_EXTRACT(\\`${rootProp}\\`, '${jsonPath}'))`;\n\t\t\t\t\treturn `${jsonExpr} ${nullCheck}`;\n\t\t\t\t}\n\t\t\t\treturn `\\`${prop}\\` ${nullCheck}`;\n\t\t\t}\n\t\t}\n\n\t\tconst dbValue = this.propertyToDbValue(comparator.value, type);\n\t\tvalues.push(dbValue);\n\n\t\tif (comparator.property.split(\".\").length > 1) {\n\t\t\tconst rootProp = comparator.property.split(\".\")[0];\n\t\t\tconst nestedPath = comparator.property.split(\".\").slice(1).join(\".\");\n\t\t\tconst rootSchema = this._entitySchema.properties?.find(p => p.property === rootProp);\n\t\t\tconst isArray = rootSchema?.type === EntitySchemaPropertyType.Array;\n\t\t\tconst jsonPath = isArray ? `$[*].${nestedPath}` : `$.${nestedPath}`;\n\t\t\tconst jsonExpr = `JSON_UNQUOTE(JSON_EXTRACT(\\`${rootProp}\\`, '${jsonPath}'))`;\n\n\t\t\tswitch (comparator.comparison) {\n\t\t\t\tcase ComparisonOperator.Includes: {\n\t\t\t\t\tvalues.pop();\n\t\t\t\t\tvalues.push(`%${String(comparator.value).toLowerCase()}%`);\n\t\t\t\t\treturn `LOWER(${jsonExpr}) LIKE ?`;\n\t\t\t\t}\n\t\t\t\tcase ComparisonOperator.NotEquals:\n\t\t\t\t\treturn `${jsonExpr} <> ?`;\n\t\t\t\tcase ComparisonOperator.GreaterThan:\n\t\t\t\t\treturn `${jsonExpr} > ?`;\n\t\t\t\tcase ComparisonOperator.LessThan:\n\t\t\t\t\treturn `${jsonExpr} < ?`;\n\t\t\t\tcase ComparisonOperator.GreaterThanOrEqual:\n\t\t\t\t\treturn `${jsonExpr} >= ?`;\n\t\t\t\tcase ComparisonOperator.LessThanOrEqual:\n\t\t\t\t\treturn `${jsonExpr} <= ?`;\n\t\t\t\tdefault:\n\t\t\t\t\treturn `${jsonExpr} = ?`;\n\t\t\t}\n\t\t}\n\n\t\tswitch (comparator.comparison) {\n\t\t\tcase ComparisonOperator.Equals:\n\t\t\t\tif (Is.object(comparator.value) || Is.array(comparator.value)) {\n\t\t\t\t\treturn `JSON_CONTAINS(\\`${prop}\\`, ?)`;\n\t\t\t\t}\n\t\t\t\treturn `\\`${prop}\\` = ?`;\n\t\t\tcase ComparisonOperator.NotEquals:\n\t\t\t\tif (Is.object(comparator.value) || Is.array(comparator.value)) {\n\t\t\t\t\treturn `NOT JSON_CONTAINS(\\`${prop}\\`, ?)`;\n\t\t\t\t}\n\t\t\t\treturn `\\`${prop}\\` <> ?`;\n\t\t\tcase ComparisonOperator.GreaterThan:\n\t\t\t\treturn `\\`${prop}\\` > ?`;\n\t\t\tcase ComparisonOperator.LessThan:\n\t\t\t\treturn `\\`${prop}\\` < ?`;\n\t\t\tcase ComparisonOperator.GreaterThanOrEqual:\n\t\t\t\treturn `\\`${prop}\\` >= ?`;\n\t\t\tcase ComparisonOperator.LessThanOrEqual:\n\t\t\t\treturn `\\`${prop}\\` <= ?`;\n\t\t\tcase ComparisonOperator.Includes: {\n\t\t\t\tif (type === EntitySchemaPropertyType.String) {\n\t\t\t\t\tvalues.pop();\n\t\t\t\t\tvalues.push(`%${String(comparator.value).toLowerCase()}%`);\n\t\t\t\t\treturn `LOWER(\\`${prop}\\`) LIKE ?`;\n\t\t\t\t}\n\t\t\t\tvalues.pop();\n\t\t\t\tvalues.push(JSON.stringify(comparator.value));\n\t\t\t\treturn `JSON_CONTAINS(\\`${prop}\\`, ?)`;\n\t\t\t}\n\t\t\tcase ComparisonOperator.NotIncludes: {\n\t\t\t\tif (type === EntitySchemaPropertyType.String) {\n\t\t\t\t\tvalues.pop();\n\t\t\t\t\tvalues.push(`%${String(comparator.value).toLowerCase()}%`);\n\t\t\t\t\treturn `LOWER(\\`${prop}\\`) NOT LIKE ?`;\n\t\t\t\t}\n\t\t\t\tvalues.pop();\n\t\t\t\tvalues.push(JSON.stringify(comparator.value));\n\t\t\t\treturn `NOT JSON_CONTAINS(\\`${prop}\\`, ?)`;\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\tthrow new GeneralError(MySqlEntityStorageConnector.CLASS_NAME, \"comparisonNotSupported\", {\n\t\t\t\t\tcomparison: comparator.comparison\n\t\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Format a value to insert into DB.\n\t * @param value The value to format.\n\t * @param type The type for the property.\n\t * @returns The value after conversion.\n\t * @internal\n\t */\n\tprivate propertyToDbValue(value: unknown, type?: EntitySchemaPropertyType): unknown {\n\t\tif (Is.object(value)) {\n\t\t\treturn JSON.stringify(value);\n\t\t}\n\n\t\tif (type === \"string\") {\n\t\t\treturn String(value);\n\t\t} else if (type === \"number\") {\n\t\t\treturn Number(value);\n\t\t} else if (type === \"boolean\") {\n\t\t\treturn value ? 1 : 0;\n\t\t}\n\n\t\treturn value;\n\t}\n\n\t/**\n\t * Map the framework conditional operators to those in MySQL.\n\t * @param operator The operator to map.\n\t * @returns The conditional operator.\n\t * @throws GeneralError if the conditional operator is not supported.\n\t * @internal\n\t */\n\tprivate mapConditionalOperator(operator?: LogicalOperator): string {\n\t\tif ((operator ?? LogicalOperator.And) === LogicalOperator.And) {\n\t\t\treturn \"AND\";\n\t\t} else if (operator === LogicalOperator.Or) {\n\t\t\treturn \"OR\";\n\t\t}\n\n\t\tthrow new GeneralError(MySqlEntityStorageConnector.CLASS_NAME, \"conditionalNotSupported\", {\n\t\t\toperator\n\t\t});\n\t}\n\n\t/**\n\t * Verify the conditions for the entity.\n\t * @param conditions The conditions to verify.\n\t * @param obj The object to verify the conditions against.\n\t * @returns True if all conditions are met, false otherwise.\n\t * @internal\n\t */\n\tprivate verifyConditions(\n\t\tconditions: { property: keyof T; value: unknown }[],\n\t\tobj: { [key in keyof T]: unknown }\n\t): boolean {\n\t\treturn conditions.every(\n\t\t\tcondition => ObjectHelper.propertyGet(obj, condition.property as string) === condition.value\n\t\t);\n\t}\n\n\t/**\n\t * Map entity schema properties to SQL properties.\n\t * @param schema The schema to use, defaults to the connector's own schema.\n\t * @returns The SQL properties as a string.\n\t * @throws GeneralError if the entity properties do not exist.\n\t * @internal\n\t */\n\tprivate mapMySqlProperties(schema?: IEntitySchema<T>): string {\n\t\tconst entitySchema = schema ?? this._entitySchema;\n\n\t\tconst sqlTypeMap: { [key in EntitySchemaPropertyType]: string } = {\n\t\t\t[EntitySchemaPropertyType.String]: \"LONGTEXT\",\n\t\t\t[EntitySchemaPropertyType.Number]: \"FLOAT\",\n\t\t\t[EntitySchemaPropertyType.Integer]: \"INT\",\n\t\t\t[EntitySchemaPropertyType.Object]: \"JSON\",\n\t\t\t[EntitySchemaPropertyType.Array]: \"JSON\",\n\t\t\t[EntitySchemaPropertyType.Boolean]: \"TINYINT(1)\"\n\t\t};\n\n\t\tif (!entitySchema.properties) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"entitySchemaPropertiesUndefined\"\n\t\t\t);\n\t\t}\n\n\t\tconst primaryKeys: string[] = [];\n\n\t\tconst props: IEntitySchemaProperty<T>[] = [...entitySchema.properties];\n\n\t\tprops.unshift({\n\t\t\tproperty: MySqlEntityStorageConnector._PARTITION_KEY as keyof T,\n\t\t\ttype: EntitySchemaPropertyType.String,\n\t\t\tisPrimary: true\n\t\t});\n\n\t\tconst columnDefinitions = props\n\t\t\t.map(prop => {\n\t\t\t\tlet sqlType = sqlTypeMap[prop.type] || \"TEXT\";\n\t\t\t\tif (prop.format) {\n\t\t\t\t\tswitch (prop.type) {\n\t\t\t\t\t\tcase EntitySchemaPropertyType.String:\n\t\t\t\t\t\t\tsqlType = \"LONGTEXT\";\n\t\t\t\t\t\t\tswitch (prop.format) {\n\t\t\t\t\t\t\t\tcase \"uuid\":\n\t\t\t\t\t\t\t\t\tsqlType = \"CHAR(36)\";\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase \"date\":\n\t\t\t\t\t\t\t\tcase \"date-time\":\n\t\t\t\t\t\t\t\t\tsqlType = \"LONGTEXT\";\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase EntitySchemaPropertyType.Number:\n\t\t\t\t\t\t\tsqlType = \"FLOAT\";\n\t\t\t\t\t\t\tswitch (prop.format) {\n\t\t\t\t\t\t\t\tcase \"float\":\n\t\t\t\t\t\t\t\t\tsqlType = \"FLOAT\";\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase \"double\":\n\t\t\t\t\t\t\t\t\tsqlType = \"DOUBLE\";\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase EntitySchemaPropertyType.Integer:\n\t\t\t\t\t\t\tsqlType = \"INT\";\n\t\t\t\t\t\t\tswitch (prop.format) {\n\t\t\t\t\t\t\t\tcase \"int8\":\n\t\t\t\t\t\t\t\tcase \"uint8\":\n\t\t\t\t\t\t\t\t\tsqlType = \"TINYINT\";\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase \"int16\":\n\t\t\t\t\t\t\t\tcase \"uint16\":\n\t\t\t\t\t\t\t\t\tsqlType = \"SMALLINT\";\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase \"int32\":\n\t\t\t\t\t\t\t\tcase \"uint32\":\n\t\t\t\t\t\t\t\t\tsqlType = \"INT\";\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase \"int64\":\n\t\t\t\t\t\t\t\tcase \"uint64\":\n\t\t\t\t\t\t\t\t\tsqlType = \"BIGINT\";\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst columnName = String(prop.property);\n\t\t\t\tconst nullable = prop.optional ? \" NULL\" : \" NOT NULL\";\n\n\t\t\t\tif (prop.isPrimary) {\n\t\t\t\t\tif (sqlType === \"LONGTEXT\" || sqlType === \"TEXT\") {\n\t\t\t\t\t\tprimaryKeys.push(`\\`${columnName}\\`(255)`);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tprimaryKeys.push(`\\`${columnName}\\``);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn `\\`${columnName}\\` ${sqlType}${nullable}`;\n\t\t\t})\n\t\t\t.join(\", \");\n\n\t\tconst primaryKeyDefinition =\n\t\t\tprimaryKeys.length > 0 ? `, PRIMARY KEY (${primaryKeys.join(\", \")})` : \"\";\n\t\treturn columnDefinitions + primaryKeyDefinition;\n\t}\n}\n"]}
1
+ {"version":3,"file":"mysqlEntityStorageConnector.js","sourceRoot":"","sources":["../../src/mysqlEntityStorageConnector.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { ContextIdHelper, ContextIdStore, type IContextIds } from \"@twin.org/context\";\nimport {\n\tBaseError,\n\tCoerce,\n\tComponentFactory,\n\tGeneralError,\n\tGuards,\n\tHealthStatus,\n\ttype IHealth,\n\tIs,\n\ttype IValidationFailure,\n\tMutex,\n\tObjectHelper,\n\tSharedStore,\n\tValidation\n} from \"@twin.org/core\";\nimport {\n\tComparisonOperator,\n\ttype EntityCondition,\n\tEntitySchemaFactory,\n\tEntitySchemaHelper,\n\tEntitySchemaPropertyType,\n\ttype IComparator,\n\ttype IEntitySchema,\n\ttype IEntitySchemaProperty,\n\tLogicalOperator,\n\tSortDirection\n} from \"@twin.org/entity\";\nimport {\n\tEntityStorageHelper,\n\ttype IEntityStorageConnector,\n\ttype IEntityStorageMigrationConnector,\n\ttype IMigrationOptions\n} from \"@twin.org/entity-storage-models\";\nimport type { ILoggingComponent } from \"@twin.org/logging-models\";\nimport { nameof } from \"@twin.org/nameof\";\nimport { type Pool, type PoolOptions, createPool } from \"mysql2/promise\";\nimport type { IMySqlEntityStorageConnectorConfig } from \"./models/IMySqlEntityStorageConnectorConfig.js\";\nimport type { IMySqlEntityStorageConnectorConstructorOptions } from \"./models/IMySqlEntityStorageConnectorConstructorOptions.js\";\n\n/**\n * Class for performing entity storage operations using MySql.\n */\nexport class MySqlEntityStorageConnector<\n\tT = unknown\n> implements IEntityStorageMigrationConnector<T> {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<MySqlEntityStorageConnector>();\n\n\t/**\n\t * Limit the number of entities when finding.\n\t * @internal\n\t */\n\tprivate static readonly _DEFAULT_LIMIT: number = 40;\n\n\t/**\n\t * Partition id field name.\n\t * @internal\n\t */\n\tprivate static readonly _PARTITION_KEY: string = \"partitionId\";\n\n\t/**\n\t * Partition id field value.\n\t * @internal\n\t */\n\tprivate static readonly _PARTITION_KEY_VALUE: string = \"root\";\n\n\t/**\n\t * The name for the schema.\n\t * @internal\n\t */\n\tprivate readonly _entitySchemaName: string;\n\n\t/**\n\t * The schema for the entity.\n\t * @internal\n\t */\n\tprivate readonly _entitySchema: IEntitySchema<T>;\n\n\t/**\n\t * The keys to use from the context ids to create partitions.\n\t * @internal\n\t */\n\tprivate readonly _partitionContextIds?: string[];\n\n\t/**\n\t * The configuration for the connector.\n\t * @internal\n\t */\n\tprivate readonly _config: IMySqlEntityStorageConnectorConfig;\n\n\t/**\n\t * The connection pool for MySql.\n\t * @internal\n\t */\n\tprivate _pool?: Pool;\n\n\t/**\n\t * The primary key property.\n\t * @internal\n\t */\n\tprivate readonly _primaryKeyProperty: IEntitySchemaProperty<T>;\n\n\t/**\n\t * Milliseconds to wait for the directory lock before throwing.\n\t * @internal\n\t */\n\tprivate readonly _mutexTimeoutMs?: number;\n\n\t/**\n\t * Create a new instance of MySqlEntityStorageConnector.\n\t * @param options The options for the connector.\n\t */\n\tconstructor(options: IMySqlEntityStorageConnectorConstructorOptions) {\n\t\tGuards.object(MySqlEntityStorageConnector.CLASS_NAME, nameof(options), options);\n\t\tGuards.stringValue(\n\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.entitySchema),\n\t\t\toptions.entitySchema\n\t\t);\n\t\tGuards.object<IMySqlEntityStorageConnectorConfig>(\n\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config),\n\t\t\toptions.config\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.host),\n\t\t\toptions.config.host\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.user),\n\t\t\toptions.config.user\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.password),\n\t\t\toptions.config.password\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.database),\n\t\t\toptions.config.database\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.tableName),\n\t\t\toptions.config.tableName\n\t\t);\n\n\t\tthis._entitySchemaName = options.entitySchema;\n\t\tthis._entitySchema = EntitySchemaFactory.get(options.entitySchema);\n\t\tthis._partitionContextIds = options.partitionContextIds;\n\t\tthis._primaryKeyProperty = EntitySchemaHelper.getPrimaryKey(this._entitySchema);\n\n\t\tthis._config = options.config;\n\t\tthis._mutexTimeoutMs = Coerce.integer(options.config.mutexTimeoutMs);\n\t}\n\n\t/**\n\t * Returns the class name of the component.\n\t * @returns The class name of the component.\n\t */\n\tpublic className(): string {\n\t\treturn MySqlEntityStorageConnector.CLASS_NAME;\n\t}\n\n\t/**\n\t * Get the health of the component.\n\t * @returns The health of the component.\n\t */\n\tpublic async health(): Promise<IHealth[]> {\n\t\ttry {\n\t\t\tconst pool = await this.getPool();\n\t\t\tawait pool.query(\n\t\t\t\t`SELECT 1 FROM \\`${this._config.database}\\`.\\`${this._config.tableName}\\` LIMIT 0`\n\t\t\t);\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tsource: MySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\tstatus: HealthStatus.Ok,\n\t\t\t\t\tdescription: \"healthDescription\",\n\t\t\t\t\tdata: { database: this._config.database, tableName: this._config.tableName }\n\t\t\t\t}\n\t\t\t];\n\t\t} catch {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tsource: MySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\tstatus: HealthStatus.Error,\n\t\t\t\t\tdescription: \"healthDescription\",\n\t\t\t\t\tmessage: \"connectionFailed\",\n\t\t\t\t\tdata: { database: this._config.database, tableName: this._config.tableName }\n\t\t\t\t}\n\t\t\t];\n\t\t}\n\t}\n\n\t/**\n\t * Get the schema for the entities.\n\t * @returns The schema for the entities.\n\t */\n\tpublic getSchema(): IEntitySchema {\n\t\treturn this._entitySchema as IEntitySchema;\n\t}\n\n\t/**\n\t * Initialize the MySql environment.\n\t * @param nodeLoggingComponentType Optional type of the logging component.\n\t * @returns A promise that resolves to a boolean indicating success.\n\t */\n\tpublic async bootstrap(nodeLoggingComponentType?: string): Promise<boolean> {\n\t\tconst nodeLogging = ComponentFactory.getIfExists<ILoggingComponent>(nodeLoggingComponentType);\n\n\t\ttry {\n\t\t\tconst pool = await this.getPool();\n\n\t\t\tconst databaseExists = await this.databaseExists();\n\t\t\tif (!databaseExists) {\n\t\t\t\tawait nodeLogging?.log({\n\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\tsource: MySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\tmessage: \"databaseCreating\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tdatabaseName: this._config.database\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tawait pool.query(`CREATE DATABASE IF NOT EXISTS \\`${this._config.database}\\``);\n\n\t\t\t\tawait this.waitForDatabaseExists();\n\t\t\t} else {\n\t\t\t\tawait nodeLogging?.log({\n\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\tsource: MySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\tmessage: \"databaseExists\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tdatabaseName: this._config.database\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst tableExists = await this.tableExists();\n\t\t\tif (!tableExists) {\n\t\t\t\tawait nodeLogging?.log({\n\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\tsource: MySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\tmessage: \"tableCreating\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\ttableName: this._config.tableName\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tawait pool.query(\n\t\t\t\t\t`CREATE TABLE IF NOT EXISTS \\`${this._config.database}\\`.\\`${this._config.tableName}\\` (${this.mapMySqlProperties()})`\n\t\t\t\t);\n\n\t\t\t\tawait this.waitForTableExists();\n\t\t\t} else {\n\t\t\t\tawait nodeLogging?.log({\n\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\tsource: MySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\tmessage: \"tableExists\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\ttableName: this._config.tableName\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tawait nodeLogging?.log({\n\t\t\t\tlevel: \"error\",\n\t\t\t\tsource: MySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\tts: Date.now(),\n\t\t\t\tmessage: \"databaseCreateFailed\",\n\t\t\t\terror: BaseError.fromError(error),\n\t\t\t\tdata: {\n\t\t\t\t\tdatabaseName: this._config.database\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * The component needs to be stopped when the node is closed.\n\t * @param nodeLoggingComponentType The node logging component type.\n\t * @returns Nothing.\n\t */\n\tpublic async stop(nodeLoggingComponentType?: string): Promise<void> {\n\t\tif (this._pool) {\n\t\t\tconst poolConfig = this.createPoolConfig();\n\t\t\tconst poolId = `${poolConfig.host}|${poolConfig.port}|${poolConfig.user}`;\n\n\t\t\ttry {\n\t\t\t\tawait Mutex.lock(`mySqlPools:${poolId}`, {\n\t\t\t\t\tthrowOnTimeout: true,\n\t\t\t\t\ttimeoutMs: this._mutexTimeoutMs\n\t\t\t\t});\n\t\t\t\tconst sharedPools = SharedStore.get<{ [id: string]: { pool: Pool; useCounter: number } }>(\n\t\t\t\t\t\"mySqlPools\",\n\t\t\t\t\t() => ({})\n\t\t\t\t);\n\t\t\t\tif (sharedPools[poolId]) {\n\t\t\t\t\t// Decrease the use counter and close the pool if no longer used\n\t\t\t\t\tsharedPools[poolId].useCounter--;\n\t\t\t\t\tif (sharedPools[poolId].useCounter <= 0) {\n\t\t\t\t\t\tconst poolInstance = sharedPools[poolId].pool;\n\t\t\t\t\t\tawait poolInstance.end();\n\t\t\t\t\t\tdelete sharedPools[poolId];\n\t\t\t\t\t\tthis._pool = undefined;\n\t\t\t\t\t}\n\t\t\t\t\tSharedStore.set(\"mySqlPools\", sharedPools);\n\t\t\t\t} else {\n\t\t\t\t\t// Pool was already ended by another connector; clear our stale reference.\n\t\t\t\t\tthis._pool = undefined;\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tMutex.unlock(`mySqlPools:${poolId}`);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Get an entity from MySql.\n\t * @param id The id of the entity to get, or the index value if secondaryIndex is set.\n\t * @param secondaryIndex Get the item using a secondary index.\n\t * @param conditions The optional conditions to match for the entities.\n\t * @returns The object if it can be found or undefined.\n\t */\n\tpublic async get(\n\t\tid: string,\n\t\tsecondaryIndex?: keyof T,\n\t\tconditions?: { property: keyof T; value: unknown }[]\n\t): Promise<T | undefined> {\n\t\tGuards.stringValue(MySqlEntityStorageConnector.CLASS_NAME, nameof(id), id);\n\n\t\tEntityStorageHelper.validateConditions(this._entitySchema, conditions);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\ttry {\n\t\t\tconst pool = await this.getPool();\n\n\t\t\tconst whereClauses: string[] = [];\n\t\t\tconst values: unknown[] = [];\n\n\t\t\twhereClauses.push(`\\`${MySqlEntityStorageConnector._PARTITION_KEY}\\` = ?`);\n\t\t\tvalues.push(partitionKey ?? MySqlEntityStorageConnector._PARTITION_KEY_VALUE);\n\n\t\t\tif (secondaryIndex) {\n\t\t\t\twhereClauses.push(`\\`${String(secondaryIndex)}\\` = ?`);\n\t\t\t} else {\n\t\t\t\twhereClauses.push(`\\`${String(this._primaryKeyProperty.property)}\\` = ?`);\n\t\t\t}\n\t\t\tvalues.push(id);\n\n\t\t\tif (Is.arrayValue(conditions)) {\n\t\t\t\tfor (const condition of conditions) {\n\t\t\t\t\twhereClauses.push(`\\`${String(condition.property)}\\` = ?`);\n\t\t\t\t\tvalues.push(condition.value);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst query = `SELECT * FROM \\`${this._config.database}\\`.\\`${this._config.tableName}\\` WHERE ${whereClauses.join(\" AND \")} LIMIT 1`;\n\t\t\tconst [rows] = await pool.query(query, values);\n\n\t\t\tif (Is.array(rows) && rows.length === 1) {\n\t\t\t\tconst item = EntityStorageHelper.unPrepareEntity<T>(rows[0] as T, [\n\t\t\t\t\tMySqlEntityStorageConnector._PARTITION_KEY\n\t\t\t\t]);\n\t\t\t\treturn this.coerceEntityTypes(item) as T;\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"getFailed\",\n\t\t\t\t{\n\t\t\t\t\tid\n\t\t\t\t},\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Set an entity.\n\t * @param entity The entity to set.\n\t * @param conditions The optional conditions to match for the entities.\n\t * @returns The id of the entity.\n\t */\n\tpublic async set(entity: T, conditions?: { property: keyof T; value: unknown }[]): Promise<void> {\n\t\tGuards.object<T>(MySqlEntityStorageConnector.CLASS_NAME, nameof(entity), entity);\n\t\tEntityStorageHelper.validateConditions(this._entitySchema, conditions);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tconst prepared = EntityStorageHelper.prepareEntity(\n\t\t\tentity,\n\t\t\tthis._entitySchema,\n\t\t\t[\n\t\t\t\t{\n\t\t\t\t\tproperty: MySqlEntityStorageConnector._PARTITION_KEY,\n\t\t\t\t\tvalue: partitionKey ?? MySqlEntityStorageConnector._PARTITION_KEY_VALUE\n\t\t\t\t}\n\t\t\t],\n\t\t\t{ nullBehavior: \"nullify\" }\n\t\t);\n\n\t\tconst id = prepared[this._primaryKeyProperty.property] as unknown as string;\n\n\t\ttry {\n\t\t\tif (Is.arrayValue(conditions)) {\n\t\t\t\tconst itemData = await this.get(id);\n\t\t\t\tif (Is.notEmpty(itemData) && !this.verifyConditions(conditions, itemData as T)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst props = [...(this._entitySchema.properties ?? [])];\n\t\t\tprops.unshift({\n\t\t\t\tproperty: MySqlEntityStorageConnector._PARTITION_KEY as keyof T,\n\t\t\t\ttype: EntitySchemaPropertyType.String\n\t\t\t});\n\n\t\t\tconst keys: string[] = [];\n\t\t\tconst values = [];\n\n\t\t\tfor (const prop of props) {\n\t\t\t\tkeys.push(prop.property as string);\n\t\t\t\tconst val = prepared[prop.property];\n\t\t\t\tif (val === null || val === undefined) {\n\t\t\t\t\tvalues.push(null);\n\t\t\t\t} else if (\n\t\t\t\t\tprop.type === EntitySchemaPropertyType.Object ||\n\t\t\t\t\tprop.type === EntitySchemaPropertyType.Array\n\t\t\t\t) {\n\t\t\t\t\tvalues.push(JSON.stringify(val));\n\t\t\t\t} else {\n\t\t\t\t\tvalues.push(val);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet sql = `INSERT INTO \\`${this._config.database}\\`.\\`${this._config.tableName}\\``;\n\t\t\tsql += ` (${keys.map(key => `\\`${key}\\``).join(\", \")})`;\n\t\t\tsql += ` VALUES (${values.map(() => \"?\").join(\", \")})`;\n\t\t\tsql += ` ON DUPLICATE KEY UPDATE ${keys.map(key => `\\`${key}\\` = VALUES(\\`${key}\\`)`).join(\", \")};`;\n\n\t\t\tconst pool = await this.getPool();\n\t\t\tawait pool.query(sql, values);\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"setFailed\",\n\t\t\t\t{\n\t\t\t\t\tid\n\t\t\t\t},\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Set multiple entities in a batch.\n\t * @param entities The entities to set.\n\t * @returns Nothing.\n\t */\n\tpublic async setBatch(entities: T[]): Promise<void> {\n\t\tGuards.arrayValue(MySqlEntityStorageConnector.CLASS_NAME, nameof(entities), entities);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tconst preparedEntities = entities.map(entity =>\n\t\t\tEntityStorageHelper.prepareEntity(\n\t\t\t\tentity,\n\t\t\t\tthis._entitySchema,\n\t\t\t\t[\n\t\t\t\t\t{\n\t\t\t\t\t\tproperty: MySqlEntityStorageConnector._PARTITION_KEY,\n\t\t\t\t\t\tvalue: partitionKey ?? MySqlEntityStorageConnector._PARTITION_KEY_VALUE\n\t\t\t\t\t}\n\t\t\t\t],\n\t\t\t\t{ nullBehavior: \"nullify\" }\n\t\t\t)\n\t\t);\n\n\t\ttry {\n\t\t\tconst props = [...(this._entitySchema.properties ?? [])];\n\t\t\tprops.unshift({\n\t\t\t\tproperty: MySqlEntityStorageConnector._PARTITION_KEY as keyof T,\n\t\t\t\ttype: EntitySchemaPropertyType.String\n\t\t\t});\n\n\t\t\tconst keys = props.map(p => p.property as string);\n\t\t\tconst allValues: unknown[] = [];\n\n\t\t\tfor (const prepared of preparedEntities) {\n\t\t\t\tfor (const prop of props) {\n\t\t\t\t\tconst val = prepared[prop.property];\n\t\t\t\t\tif (\n\t\t\t\t\t\tprop.type === EntitySchemaPropertyType.Object ||\n\t\t\t\t\t\tprop.type === EntitySchemaPropertyType.Array\n\t\t\t\t\t) {\n\t\t\t\t\t\tallValues.push(Is.empty(val) ? null : JSON.stringify(val));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tallValues.push(Is.empty(val) ? null : val);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst rowPlaceholder = `(${keys.map(() => \"?\").join(\", \")})`;\n\t\t\tlet sql = `INSERT INTO \\`${this._config.database}\\`.\\`${this._config.tableName}\\``;\n\t\t\tsql += ` (${keys.map(key => `\\`${key}\\``).join(\", \")})`;\n\t\t\tsql += ` VALUES ${entities.map(() => rowPlaceholder).join(\", \")}`;\n\t\t\tsql += ` ON DUPLICATE KEY UPDATE ${keys.map(key => `\\`${key}\\` = VALUES(\\`${key}\\`)`).join(\", \")};`;\n\n\t\t\tconst pool = await this.getPool();\n\t\t\tawait pool.query(sql, allValues);\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"setBatchFailed\",\n\t\t\t\tundefined,\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Empty the entity storage.\n\t * @returns Nothing.\n\t */\n\tpublic async empty(): Promise<void> {\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\ttry {\n\t\t\tconst pool = await this.getPool();\n\t\t\tawait pool.query(\n\t\t\t\t`DELETE FROM \\`${this._config.database}\\`.\\`${this._config.tableName}\\` WHERE \\`${MySqlEntityStorageConnector._PARTITION_KEY}\\` = ?`,\n\t\t\t\t[partitionKey ?? MySqlEntityStorageConnector._PARTITION_KEY_VALUE]\n\t\t\t);\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(MySqlEntityStorageConnector.CLASS_NAME, \"emptyFailed\", undefined, err);\n\t\t}\n\t}\n\n\t/**\n\t * Remove the entity.\n\t * @param id The id of the entity to remove.\n\t * @param conditions The optional conditions to match for the entities.\n\t * @returns Nothing.\n\t */\n\tpublic async remove(\n\t\tid: string,\n\t\tconditions?: { property: keyof T; value: unknown }[]\n\t): Promise<void> {\n\t\tGuards.stringValue(MySqlEntityStorageConnector.CLASS_NAME, nameof(id), id);\n\n\t\tEntityStorageHelper.validateConditions(this._entitySchema, conditions);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\ttry {\n\t\t\tconst pool = await this.getPool();\n\n\t\t\tconst itemData = await this.get(id, undefined, conditions);\n\t\t\tif (Is.notEmpty(itemData)) {\n\t\t\t\tconst values: unknown[] = [];\n\t\t\t\tconst whereClauses: string[] = [];\n\n\t\t\t\twhereClauses.push(`\\`${this._primaryKeyProperty.property as string}\\` = ?`);\n\t\t\t\tvalues.push(id);\n\n\t\t\t\twhereClauses.push(`\\`${MySqlEntityStorageConnector._PARTITION_KEY}\\` = ?`);\n\t\t\t\tvalues.push(partitionKey ?? MySqlEntityStorageConnector._PARTITION_KEY_VALUE);\n\n\t\t\t\tif (Is.arrayValue(conditions)) {\n\t\t\t\t\twhereClauses.push(\n\t\t\t\t\t\t...conditions.map(condition => {\n\t\t\t\t\t\t\tvalues.push(condition.value);\n\t\t\t\t\t\t\treturn `\\`${String(condition.property)}\\` = ?`;\n\t\t\t\t\t\t})\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tconst query = `DELETE FROM \\`${this._config.database}\\`.\\`${this._config.tableName}\\` WHERE ${whereClauses.join(\" AND \")}`;\n\t\t\t\tawait pool.query(query, values);\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"removeFailed\",\n\t\t\t\t{\n\t\t\t\t\tid\n\t\t\t\t},\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Teardown the entity storage by dropping the table.\n\t * @param nodeLoggingComponentType The node logging component type.\n\t * @returns True if the teardown process was successful.\n\t */\n\tpublic async teardown(nodeLoggingComponentType?: string): Promise<boolean> {\n\t\tconst nodeLogging = ComponentFactory.getIfExists<ILoggingComponent>(nodeLoggingComponentType);\n\n\t\tawait nodeLogging?.log({\n\t\t\tlevel: \"info\",\n\t\t\tsource: MySqlEntityStorageConnector.CLASS_NAME,\n\t\t\tts: Date.now(),\n\t\t\tmessage: \"tableDropping\",\n\t\t\tdata: { tableName: this._config.tableName }\n\t\t});\n\n\t\ttry {\n\t\t\tif (await this.tableExists()) {\n\t\t\t\tconst pool = await this.getPool();\n\t\t\t\tawait pool.query(`DROP TABLE \\`${this._config.database}\\`.\\`${this._config.tableName}\\`;`);\n\t\t\t\tawait this.waitForTableNotExists();\n\t\t\t}\n\n\t\t\tawait nodeLogging?.log({\n\t\t\t\tlevel: \"info\",\n\t\t\t\tsource: MySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\tts: Date.now(),\n\t\t\t\tmessage: \"tableDropped\",\n\t\t\t\tdata: { tableName: this._config.tableName }\n\t\t\t});\n\n\t\t\treturn true;\n\t\t} catch (err) {\n\t\t\tawait nodeLogging?.log({\n\t\t\t\tlevel: \"error\",\n\t\t\t\tsource: MySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\tts: Date.now(),\n\t\t\t\tmessage: \"teardownFailed\",\n\t\t\t\terror: BaseError.fromError(err)\n\t\t\t});\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Remove multiple entities by their primary key IDs.\n\t * @param ids The ids of the entities to remove.\n\t * @returns Nothing.\n\t */\n\tpublic async removeBatch(ids: string[]): Promise<void> {\n\t\tGuards.arrayValue(MySqlEntityStorageConnector.CLASS_NAME, nameof(ids), ids);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\ttry {\n\t\t\tconst pool = await this.getPool();\n\t\t\tconst sql = `DELETE FROM \\`${this._config.database}\\`.\\`${this._config.tableName}\\` WHERE \\`${MySqlEntityStorageConnector._PARTITION_KEY}\\` = ? AND \\`${String(this._primaryKeyProperty.property)}\\` IN (?)`;\n\t\t\tawait pool.query(sql, [\n\t\t\t\tpartitionKey ?? MySqlEntityStorageConnector._PARTITION_KEY_VALUE,\n\t\t\t\tids\n\t\t\t]);\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"removeBatchFailed\",\n\t\t\t\tundefined,\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Find all the entities which match the conditions.\n\t * @param conditions The conditions to match for the entities.\n\t * @param sortProperties The optional sort order.\n\t * @param properties The optional properties to return, defaults to all.\n\t * @param cursor The cursor to request the next chunk of entities.\n\t * @param limit The suggested number of entities to return in each chunk, in some scenarios can return a different amount.\n\t * @returns All the entities for the storage matching the conditions,\n\t * and a cursor which can be used to request more entities.\n\t */\n\tpublic async query(\n\t\tconditions?: EntityCondition<T>,\n\t\tsortProperties?: { property: keyof T; sortDirection: SortDirection }[],\n\t\tproperties?: (keyof T)[],\n\t\tcursor?: string,\n\t\tlimit?: number\n\t): Promise<{ entities: Partial<T>[]; cursor?: string }> {\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tEntityStorageHelper.validateSortProperties(this._entitySchema, sortProperties);\n\t\tEntityStorageHelper.validateProperties(this._entitySchema, properties);\n\t\tEntityStorageHelper.validateConditionProperties(this._entitySchema, conditions);\n\n\t\tif (!Is.empty(limit)) {\n\t\t\tconst validationFailures: IValidationFailure[] = [];\n\t\t\tValidation.integer(nameof(limit), limit, validationFailures, undefined, { minValue: 1 });\n\t\t\tValidation.asValidationError(\n\t\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"query\",\n\t\t\t\tvalidationFailures\n\t\t\t);\n\t\t}\n\n\t\tlet sql = \"\";\n\t\ttry {\n\t\t\tconst returnSize = limit ?? MySqlEntityStorageConnector._DEFAULT_LIMIT;\n\n\t\t\tlet orderByClause: string = \"\";\n\t\t\tif (Is.array(sortProperties)) {\n\t\t\t\tconst orderClauses: string[] = [];\n\t\t\t\tfor (const sortProperty of sortProperties) {\n\t\t\t\t\tconst direction = sortProperty.sortDirection === SortDirection.Ascending ? \"ASC\" : \"DESC\";\n\t\t\t\t\torderClauses.push(`\\`${String(sortProperty.property)}\\` ${direction}`);\n\t\t\t\t}\n\t\t\t\torderByClause = `ORDER BY ${orderClauses.join(\", \")}`;\n\t\t\t}\n\n\t\t\tconst { whereClauses, values } = this.buildWhereClause(conditions, partitionKey);\n\n\t\t\tconst startIndex = Coerce.number(cursor) ?? 0;\n\n\t\t\tsql = `SELECT ${properties ? properties.map(p => `\\`${String(p)}\\``).join(\", \") : \"*\"} FROM \\`${this._config.database}\\`.\\`${this._config.tableName}\\``;\n\t\t\tif (whereClauses.length > 0) {\n\t\t\t\tsql += ` WHERE ${whereClauses.join(\" AND \")}`;\n\t\t\t}\n\t\t\tsql += ` ${orderByClause} LIMIT ${returnSize + 1} OFFSET ${startIndex}`;\n\n\t\t\tconst pool = await this.getPool();\n\t\t\tconst [rows] = (await pool.query(sql, values)) ?? [];\n\n\t\t\tconst hasMore = Is.array(rows) && rows.length > returnSize;\n\t\t\tconst resultRows = hasMore ? (rows as unknown[]).slice(0, returnSize) : rows;\n\t\t\tconst entities = resultRows as Partial<T>[];\n\t\t\tfor (let i = 0; i < entities.length; i++) {\n\t\t\t\tentities[i] = EntityStorageHelper.unPrepareEntity(entities[i], [\n\t\t\t\t\tMySqlEntityStorageConnector._PARTITION_KEY\n\t\t\t\t]);\n\t\t\t\tentities[i] = this.coerceEntityTypes(entities[i]);\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tentities,\n\t\t\t\tcursor: hasMore ? Coerce.string(startIndex + returnSize) : undefined\n\t\t\t};\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(MySqlEntityStorageConnector.CLASS_NAME, \"queryFailed\", { sql }, err);\n\t\t}\n\t}\n\n\t/**\n\t * Count all the entities which match the conditions.\n\t * @param conditions The optional conditions to match for the entities.\n\t * @returns The total count of entities in the storage.\n\t */\n\tpublic async count(conditions?: EntityCondition<T>): Promise<number> {\n\t\tEntityStorageHelper.validateConditionProperties(this._entitySchema, conditions);\n\n\t\tlet sql: string | undefined;\n\t\ttry {\n\t\t\tconst pool = await this.getPool();\n\n\t\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\t\tconst partitionKey = ContextIdHelper.combinedContextKey(\n\t\t\t\tcontextIds,\n\t\t\t\tthis._partitionContextIds\n\t\t\t);\n\n\t\t\tconst { whereClauses, values } = this.buildWhereClause(conditions, partitionKey);\n\n\t\t\tsql = `SELECT COUNT(*) AS count FROM \\`${this._config.database}\\`.\\`${this._config.tableName}\\``;\n\t\t\tif (whereClauses.length > 0) {\n\t\t\t\tsql += ` WHERE ${whereClauses.join(\" AND \")}`;\n\t\t\t}\n\n\t\t\tconst [rows] = await pool.query(sql, values);\n\t\t\treturn Number((rows as { count: number }[])[0].count);\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(MySqlEntityStorageConnector.CLASS_NAME, \"countFailed\", { sql }, err);\n\t\t}\n\t}\n\n\t/**\n\t * Get all unique partition context ids present in the table.\n\t * @returns An array of context id objects, one per unique partition.\n\t */\n\tpublic async getPartitionContextIds(): Promise<IContextIds[]> {\n\t\tif (!Is.arrayValue(this._partitionContextIds)) {\n\t\t\treturn [];\n\t\t}\n\n\t\ttry {\n\t\t\tconst pool = await this.getPool();\n\t\t\tconst [rows] = await pool.query(\n\t\t\t\t`SELECT DISTINCT \\`${MySqlEntityStorageConnector._PARTITION_KEY}\\` FROM \\`${this._config.database}\\`.\\`${this._config.tableName}\\``\n\t\t\t);\n\t\t\treturn (rows as { [key: string]: string }[])\n\t\t\t\t.map(row => row[MySqlEntityStorageConnector._PARTITION_KEY])\n\t\t\t\t.filter((id): id is string => Is.stringValue(id))\n\t\t\t\t.map(id => ContextIdHelper.shortSplit(this._partitionContextIds ?? [], id));\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"getPartitionContextIdsFailed\",\n\t\t\t\tundefined,\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Create the target connector for performing the migration using a temporary table.\n\t * @param newEntitySchema The name of the new entity schema to create the connector for.\n\t * @returns Connector for performing the migration.\n\t */\n\tpublic async createTargetConnector<U>(\n\t\tnewEntitySchema: string\n\t): Promise<IEntityStorageConnector<U>> {\n\t\tconst migrationTableName = `${this._config.tableName}Migration${Date.now()}`;\n\t\treturn new MySqlEntityStorageConnector<U>({\n\t\t\tentitySchema: newEntitySchema,\n\t\t\tconfig: {\n\t\t\t\t...this._config,\n\t\t\t\ttableName: migrationTableName\n\t\t\t},\n\t\t\tpartitionContextIds: this._partitionContextIds\n\t\t});\n\t}\n\n\t/**\n\t * Finalize the migration by dropping the source table and renaming the migration table to the original name.\n\t * @param targetConnector The connector holding the migrated data in a temporary table.\n\t * @param options The options to control how the migration is finalized.\n\t * @param loggingComponentType The logging component type to use during finalization.\n\t * @returns The final connector using the original table name with the new schema.\n\t */\n\tpublic async finalizeMigration<U>(\n\t\ttargetConnector: MySqlEntityStorageConnector<U>,\n\t\toptions?: IMigrationOptions,\n\t\tloggingComponentType?: string\n\t): Promise<MySqlEntityStorageConnector<U>> {\n\t\t// Teardown the existing table with the original name to free up the name for the new table\n\t\tawait this.teardown(loggingComponentType);\n\n\t\t// RENAME TABLE is an atomic metadata-only operation in MySQL — no data copying needed.\n\t\tconst pool = await this.getPool();\n\t\tawait pool.query(\n\t\t\t`RENAME TABLE \\`${targetConnector._config.database}\\`.\\`${targetConnector._config.tableName}\\` TO \\`${this._config.database}\\`.\\`${this._config.tableName}\\``\n\t\t);\n\n\t\tconst finalConnector = new MySqlEntityStorageConnector<U>({\n\t\t\tentitySchema: targetConnector._entitySchemaName,\n\t\t\tconfig: this._config,\n\t\t\tpartitionContextIds: this._partitionContextIds\n\t\t});\n\n\t\tif (await finalConnector.bootstrap(loggingComponentType)) {\n\t\t\tawait targetConnector.stop();\n\t\t\treturn finalConnector;\n\t\t}\n\n\t\tthrow new GeneralError(\n\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\"finalizeMigrationFailedBootstrap\",\n\t\t\tundefined\n\t\t);\n\t}\n\n\t/**\n\t * Cleanup a failed or aborted migration by dropping the temporary migration table.\n\t * @param targetConnector The target connector to cleanup.\n\t * @param options The options to control how the migration is cleaned up.\n\t * @param loggingComponentType The optional component type to use for logging.\n\t * @returns A promise that resolves when the cleanup is complete.\n\t */\n\tpublic async cleanupMigration<U>(\n\t\ttargetConnector: IEntityStorageConnector<U> | undefined,\n\t\toptions?: IMigrationOptions,\n\t\tloggingComponentType?: string\n\t): Promise<void> {\n\t\t// If something failed the only thing to cleanup is the migration table\n\t\tawait targetConnector?.teardown?.(loggingComponentType);\n\t}\n\n\t/**\n\t * Check if the database exists.\n\t * @returns True if the database exists, false otherwise.\n\t */\n\tpublic async databaseExists(): Promise<boolean> {\n\t\ttry {\n\t\t\tconst pool = await this.getPool();\n\t\t\tconst [rows] = await pool.query(\"SHOW DATABASES LIKE ?;\", [this._config.database]);\n\t\t\treturn Is.arrayValue(rows);\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Coerce MySQL raw row values back to proper TypeScript types based on the entity schema.\n\t * MySQL returns TINYINT(1) as 0/1 rather than false/true; this method converts those.\n\t * @param entity The raw entity row from MySQL.\n\t * @returns The entity with schema-correct types.\n\t * @internal\n\t */\n\tprivate coerceEntityTypes(entity: Partial<T>): Partial<T> {\n\t\tfor (const prop of this._entitySchema.properties ?? []) {\n\t\t\tconst value = entity[prop.property];\n\t\t\tif (prop.type === EntitySchemaPropertyType.Boolean && !Is.empty(value)) {\n\t\t\t\tObjectHelper.propertySet(entity, prop.property as string, Boolean(value));\n\t\t\t}\n\t\t}\n\t\treturn entity;\n\t}\n\n\t/**\n\t * Wait for a database to exist.\n\t * @returns Nothing.\n\t * @internal\n\t */\n\tprivate async waitForDatabaseExists(): Promise<void> {\n\t\tfor (let attempt = 0; attempt < 20; attempt++) {\n\t\t\tconst databaseExists = await this.databaseExists();\n\t\t\tif (databaseExists) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tawait new Promise(resolve => setTimeout(resolve, 250));\n\t\t}\n\t}\n\n\t/**\n\t * Check if the table exists.\n\t * @returns True if the table exists, false otherwise.\n\t * @internal\n\t */\n\tprivate async tableExists(): Promise<boolean> {\n\t\ttry {\n\t\t\tconst pool = await this.getPool();\n\t\t\tconst [rows] = await pool.query(\"SHOW TABLES FROM ?? LIKE ?\", [\n\t\t\t\tthis._config.database,\n\t\t\t\tthis._config.tableName\n\t\t\t]);\n\t\t\treturn Is.arrayValue(rows);\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Wait for a table to exist.\n\t * @returns Nothing.\n\t * @internal\n\t */\n\tprivate async waitForTableExists(): Promise<void> {\n\t\tfor (let attempt = 0; attempt < 20; attempt++) {\n\t\t\tconst tableExists = await this.tableExists();\n\t\t\tif (tableExists) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tawait new Promise(resolve => setTimeout(resolve, 250));\n\t\t}\n\t}\n\n\t/**\n\t * Wait for a table to not exist.\n\t * @returns Nothing.\n\t * @internal\n\t */\n\tprivate async waitForTableNotExists(): Promise<void> {\n\t\tfor (let attempt = 0; attempt < 20; attempt++) {\n\t\t\tconst tableExists = await this.tableExists();\n\t\t\tif (!tableExists) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tawait new Promise(resolve => setTimeout(resolve, 250));\n\t\t}\n\t}\n\n\t/**\n\t * Get or create the connection pool.\n\t * @returns The MySql connection pool.\n\t * @internal\n\t */\n\tprivate async getPool(): Promise<Pool> {\n\t\tif (!this._pool) {\n\t\t\tconst poolConfig = this.createPoolConfig();\n\t\t\tconst poolId = `${poolConfig.host}|${poolConfig.port}|${poolConfig.user}`;\n\n\t\t\ttry {\n\t\t\t\tawait Mutex.lock(`mySqlPools:${poolId}`, {\n\t\t\t\t\tthrowOnTimeout: true,\n\t\t\t\t\ttimeoutMs: this._mutexTimeoutMs\n\t\t\t\t});\n\n\t\t\t\tconst sharedPools = SharedStore.get<{ [id: string]: { pool: Pool; useCounter: number } }>(\n\t\t\t\t\t\"mySqlPools\",\n\t\t\t\t\t() => ({})\n\t\t\t\t);\n\n\t\t\t\t// If there is no pool for the id, create it\n\t\t\t\tif (!sharedPools[poolId]) {\n\t\t\t\t\tsharedPools[poolId] = {\n\t\t\t\t\t\tpool: createPool(poolConfig),\n\t\t\t\t\t\tuseCounter: 0\n\t\t\t\t\t};\n\t\t\t\t\tSharedStore.set(\"mySqlPools\", sharedPools);\n\t\t\t\t}\n\t\t\t\t// Increase the use counter and return the pool\n\t\t\t\tsharedPools[poolId].useCounter++;\n\t\t\t\tthis._pool = sharedPools[poolId].pool;\n\t\t\t} finally {\n\t\t\t\tMutex.unlock(`mySqlPools:${poolId}`);\n\t\t\t}\n\t\t}\n\t\treturn this._pool;\n\t}\n\n\t/**\n\t * Create the connection pool configuration.\n\t * @returns The MySql pool configuration.\n\t * @internal\n\t */\n\tprivate createPoolConfig(): PoolOptions {\n\t\tconst poolConfig = this._config.pool ?? {};\n\n\t\treturn {\n\t\t\thost: this._config.host,\n\t\t\tport: this._config.port ?? 3306,\n\t\t\tuser: this._config.user,\n\t\t\tpassword: this._config.password,\n\n\t\t\tconnectionLimit: poolConfig.connectionLimit ?? 10,\n\t\t\tmaxIdle: poolConfig.maxIdle ?? 10,\n\t\t\tidleTimeout: poolConfig.idleTimeout ?? 60000,\n\t\t\tenableKeepAlive: poolConfig.enableKeepAlive ?? true,\n\t\t\tkeepAliveInitialDelay: 0,\n\t\t\twaitForConnections: poolConfig.waitForConnections ?? true,\n\t\t\tqueueLimit: poolConfig.queueLimit ?? 0\n\t\t};\n\t}\n\n\t/**\n\t * Build where clause arrays for a query, combining partition key and optional conditions.\n\t * @param conditions The optional entity conditions to include.\n\t * @param partitionKey The partition key value.\n\t * @returns The where clauses and bound values.\n\t * @internal\n\t */\n\tprivate buildWhereClause(\n\t\tconditions: EntityCondition<T> | undefined,\n\t\tpartitionKey: string | undefined\n\t): { whereClauses: string[]; values: unknown[] } {\n\t\tconst whereClauses: string[] = [];\n\t\tconst values: unknown[] = [];\n\n\t\tconst finalConditions: EntityCondition<T> = {\n\t\t\tconditions: [],\n\t\t\tlogicalOperator: LogicalOperator.And\n\t\t};\n\n\t\tfinalConditions.conditions.push({\n\t\t\tproperty: MySqlEntityStorageConnector._PARTITION_KEY,\n\t\t\tcomparison: ComparisonOperator.Equals,\n\t\t\tvalue: partitionKey ?? MySqlEntityStorageConnector._PARTITION_KEY_VALUE\n\t\t});\n\n\t\tif (!Is.empty(conditions)) {\n\t\t\tfinalConditions.conditions.push(conditions);\n\t\t}\n\n\t\tthis.buildQueryParameters(\"\", finalConditions, whereClauses, values);\n\n\t\treturn { whereClauses, values };\n\t}\n\n\t/**\n\t * Create an SQL condition clause.\n\t * @param objectPath The path for the nested object.\n\t * @param condition The conditions to create the query from.\n\t * @param whereClauses The where clauses to use in the query.\n\t * @param values The values to use in the query.\n\t * @internal\n\t */\n\tprivate buildQueryParameters(\n\t\tobjectPath: string,\n\t\tcondition: EntityCondition<T> | undefined,\n\t\twhereClauses: string[],\n\t\tvalues: unknown[]\n\t): void {\n\t\tif (Is.undefined(condition)) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (\"conditions\" in condition) {\n\t\t\tif (condition.conditions.length === 0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst joinConditions: string[] = condition.conditions.map(c => {\n\t\t\t\tconst subWhereClauses: string[] = [];\n\t\t\t\tconst subValues: unknown[] = [];\n\t\t\t\tthis.buildQueryParameters(objectPath, c, subWhereClauses, subValues);\n\t\t\t\tvalues.push(...subValues);\n\t\t\t\treturn subWhereClauses.join(\" AND \");\n\t\t\t});\n\n\t\t\tconst logicalOperator = this.mapConditionalOperator(condition.logicalOperator);\n\t\t\tconst queryClause = joinConditions.filter(j => j.length > 0).join(` ${logicalOperator} `);\n\n\t\t\tif (queryClause.length > 0) {\n\t\t\t\twhereClauses.push(`(${queryClause})`);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tconst schemaProp = this._entitySchema.properties?.find(p => p.property === condition.property);\n\t\tconst comparison = this.mapComparisonOperator(objectPath, condition, schemaProp?.type, values);\n\t\twhereClauses.push(comparison);\n\t}\n\n\t/**\n\t * Map the framework comparison operators to those in MySQL.\n\t * @param objectPath The prefix to use for the condition.\n\t * @param comparator The operator to map.\n\t * @param type The type of the property.\n\t * @param values The values to use in the query.\n\t * @returns The comparison expression.\n\t * @throws GeneralError if the comparison operator is not supported.\n\t * @internal\n\t */\n\tprivate mapComparisonOperator(\n\t\tobjectPath: string,\n\t\tcomparator: IComparator,\n\t\ttype: EntitySchemaPropertyType | undefined,\n\t\tvalues: unknown[]\n\t): string {\n\t\tlet prop = objectPath;\n\t\tif (prop.length > 0) {\n\t\t\tprop += \".\";\n\t\t}\n\n\t\tprop += comparator.property;\n\n\t\tif (comparator.comparison === ComparisonOperator.In) {\n\t\t\tconst inValues = Is.array(comparator.value) ? comparator.value : [comparator.value];\n\t\t\tif (inValues.length === 0) {\n\t\t\t\t// MySQL rejects `IN ()` as a syntax error — short-circuit to a condition\n\t\t\t\t// that is always false so the query returns zero rows cleanly (#141).\n\t\t\t\treturn \"1 = 0\";\n\t\t\t}\n\t\t\tvalues.push(...inValues.map(val => this.propertyToDbValue(val, type)));\n\t\t\tconst placeholders = inValues.map(() => \"?\").join(\", \");\n\t\t\treturn `\\`${prop}\\` IN (${placeholders})`;\n\t\t}\n\n\t\t// null/undefined must use IS NULL / IS NOT NULL — never a parameterised placeholder.\n\t\t// Passing undefined through propertyToDbValue() coerces it to NaN for number fields\n\t\t// (Number(undefined) === NaN), and null coerces to 0 (Number(null) === 0), both of\n\t\t// which produce semantically wrong or invalid SQL.\n\t\tif (comparator.value === null || comparator.value === undefined) {\n\t\t\tif (\n\t\t\t\tcomparator.comparison === ComparisonOperator.Equals ||\n\t\t\t\tcomparator.comparison === ComparisonOperator.NotEquals\n\t\t\t) {\n\t\t\t\tconst nullCheck =\n\t\t\t\t\tcomparator.comparison === ComparisonOperator.Equals ? \"IS NULL\" : \"IS NOT NULL\";\n\n\t\t\t\tif (comparator.property.split(\".\").length > 1) {\n\t\t\t\t\tconst rootProp = comparator.property.split(\".\")[0];\n\t\t\t\t\tconst nestedPath = comparator.property.split(\".\").slice(1).join(\".\");\n\t\t\t\t\tconst rootSchema = this._entitySchema.properties?.find(p => p.property === rootProp);\n\t\t\t\t\tconst isArray = rootSchema?.type === EntitySchemaPropertyType.Array;\n\t\t\t\t\tconst jsonPath = isArray ? `$[*].${nestedPath}` : `$.${nestedPath}`;\n\t\t\t\t\tconst jsonExpr = `JSON_UNQUOTE(JSON_EXTRACT(\\`${rootProp}\\`, '${jsonPath}'))`;\n\t\t\t\t\treturn `${jsonExpr} ${nullCheck}`;\n\t\t\t\t}\n\t\t\t\treturn `\\`${prop}\\` ${nullCheck}`;\n\t\t\t}\n\t\t}\n\n\t\tconst dbValue = this.propertyToDbValue(comparator.value, type);\n\t\tvalues.push(dbValue);\n\n\t\tif (comparator.property.split(\".\").length > 1) {\n\t\t\tconst rootProp = comparator.property.split(\".\")[0];\n\t\t\tconst nestedPath = comparator.property.split(\".\").slice(1).join(\".\");\n\t\t\tconst rootSchema = this._entitySchema.properties?.find(p => p.property === rootProp);\n\t\t\tconst isArray = rootSchema?.type === EntitySchemaPropertyType.Array;\n\t\t\tconst jsonPath = isArray ? `$[*].${nestedPath}` : `$.${nestedPath}`;\n\t\t\tconst jsonExpr = `JSON_UNQUOTE(JSON_EXTRACT(\\`${rootProp}\\`, '${jsonPath}'))`;\n\n\t\t\tswitch (comparator.comparison) {\n\t\t\t\tcase ComparisonOperator.Includes: {\n\t\t\t\t\tvalues.pop();\n\t\t\t\t\tvalues.push(`%${String(comparator.value).toLowerCase()}%`);\n\t\t\t\t\treturn `LOWER(${jsonExpr}) LIKE ?`;\n\t\t\t\t}\n\t\t\t\tcase ComparisonOperator.NotEquals:\n\t\t\t\t\treturn `${jsonExpr} <> ?`;\n\t\t\t\tcase ComparisonOperator.GreaterThan:\n\t\t\t\t\treturn `${jsonExpr} > ?`;\n\t\t\t\tcase ComparisonOperator.LessThan:\n\t\t\t\t\treturn `${jsonExpr} < ?`;\n\t\t\t\tcase ComparisonOperator.GreaterThanOrEqual:\n\t\t\t\t\treturn `${jsonExpr} >= ?`;\n\t\t\t\tcase ComparisonOperator.LessThanOrEqual:\n\t\t\t\t\treturn `${jsonExpr} <= ?`;\n\t\t\t\tdefault:\n\t\t\t\t\treturn `${jsonExpr} = ?`;\n\t\t\t}\n\t\t}\n\n\t\tswitch (comparator.comparison) {\n\t\t\tcase ComparisonOperator.Equals:\n\t\t\t\tif (Is.object(comparator.value) || Is.array(comparator.value)) {\n\t\t\t\t\treturn `JSON_CONTAINS(\\`${prop}\\`, ?)`;\n\t\t\t\t}\n\t\t\t\treturn `\\`${prop}\\` = ?`;\n\t\t\tcase ComparisonOperator.NotEquals:\n\t\t\t\tif (Is.object(comparator.value) || Is.array(comparator.value)) {\n\t\t\t\t\treturn `NOT JSON_CONTAINS(\\`${prop}\\`, ?)`;\n\t\t\t\t}\n\t\t\t\treturn `\\`${prop}\\` <> ?`;\n\t\t\tcase ComparisonOperator.GreaterThan:\n\t\t\t\treturn `\\`${prop}\\` > ?`;\n\t\t\tcase ComparisonOperator.LessThan:\n\t\t\t\treturn `\\`${prop}\\` < ?`;\n\t\t\tcase ComparisonOperator.GreaterThanOrEqual:\n\t\t\t\treturn `\\`${prop}\\` >= ?`;\n\t\t\tcase ComparisonOperator.LessThanOrEqual:\n\t\t\t\treturn `\\`${prop}\\` <= ?`;\n\t\t\tcase ComparisonOperator.Includes: {\n\t\t\t\tif (type === EntitySchemaPropertyType.String) {\n\t\t\t\t\tvalues.pop();\n\t\t\t\t\tvalues.push(`%${String(comparator.value).toLowerCase()}%`);\n\t\t\t\t\treturn `LOWER(\\`${prop}\\`) LIKE ?`;\n\t\t\t\t}\n\t\t\t\tvalues.pop();\n\t\t\t\tvalues.push(JSON.stringify(comparator.value));\n\t\t\t\treturn `JSON_CONTAINS(\\`${prop}\\`, ?)`;\n\t\t\t}\n\t\t\tcase ComparisonOperator.NotIncludes: {\n\t\t\t\tif (type === EntitySchemaPropertyType.String) {\n\t\t\t\t\tvalues.pop();\n\t\t\t\t\tvalues.push(`%${String(comparator.value).toLowerCase()}%`);\n\t\t\t\t\treturn `LOWER(\\`${prop}\\`) NOT LIKE ?`;\n\t\t\t\t}\n\t\t\t\tvalues.pop();\n\t\t\t\tvalues.push(JSON.stringify(comparator.value));\n\t\t\t\treturn `NOT JSON_CONTAINS(\\`${prop}\\`, ?)`;\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\tthrow new GeneralError(MySqlEntityStorageConnector.CLASS_NAME, \"comparisonNotSupported\", {\n\t\t\t\t\tcomparison: comparator.comparison\n\t\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Format a value to insert into DB.\n\t * @param value The value to format.\n\t * @param type The type for the property.\n\t * @returns The value after conversion.\n\t * @internal\n\t */\n\tprivate propertyToDbValue(value: unknown, type?: EntitySchemaPropertyType): unknown {\n\t\tif (Is.object(value)) {\n\t\t\treturn JSON.stringify(value);\n\t\t}\n\n\t\tif (type === \"string\") {\n\t\t\treturn String(value);\n\t\t} else if (type === \"number\") {\n\t\t\treturn Number(value);\n\t\t} else if (type === \"boolean\") {\n\t\t\treturn value ? 1 : 0;\n\t\t}\n\n\t\treturn value;\n\t}\n\n\t/**\n\t * Map the framework conditional operators to those in MySQL.\n\t * @param operator The operator to map.\n\t * @returns The conditional operator.\n\t * @throws GeneralError if the conditional operator is not supported.\n\t * @internal\n\t */\n\tprivate mapConditionalOperator(operator?: LogicalOperator): string {\n\t\tif ((operator ?? LogicalOperator.And) === LogicalOperator.And) {\n\t\t\treturn \"AND\";\n\t\t} else if (operator === LogicalOperator.Or) {\n\t\t\treturn \"OR\";\n\t\t}\n\n\t\tthrow new GeneralError(MySqlEntityStorageConnector.CLASS_NAME, \"conditionalNotSupported\", {\n\t\t\toperator\n\t\t});\n\t}\n\n\t/**\n\t * Verify the conditions for the entity.\n\t * @param conditions The conditions to verify.\n\t * @param obj The object to verify the conditions against.\n\t * @returns True if all conditions are met, false otherwise.\n\t * @internal\n\t */\n\tprivate verifyConditions(\n\t\tconditions: { property: keyof T; value: unknown }[],\n\t\tobj: { [key in keyof T]: unknown }\n\t): boolean {\n\t\treturn conditions.every(\n\t\t\tcondition => ObjectHelper.propertyGet(obj, condition.property as string) === condition.value\n\t\t);\n\t}\n\n\t/**\n\t * Map entity schema properties to SQL properties.\n\t * @param schema The schema to use, defaults to the connector's own schema.\n\t * @returns The SQL properties as a string.\n\t * @throws GeneralError if the entity properties do not exist.\n\t * @internal\n\t */\n\tprivate mapMySqlProperties(schema?: IEntitySchema<T>): string {\n\t\tconst entitySchema = schema ?? this._entitySchema;\n\n\t\tconst sqlTypeMap: { [key in EntitySchemaPropertyType]: string } = {\n\t\t\t[EntitySchemaPropertyType.String]: \"LONGTEXT\",\n\t\t\t[EntitySchemaPropertyType.Number]: \"FLOAT\",\n\t\t\t[EntitySchemaPropertyType.Integer]: \"INT\",\n\t\t\t[EntitySchemaPropertyType.Object]: \"JSON\",\n\t\t\t[EntitySchemaPropertyType.Array]: \"JSON\",\n\t\t\t[EntitySchemaPropertyType.Boolean]: \"TINYINT(1)\"\n\t\t};\n\n\t\tif (!entitySchema.properties) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"entitySchemaPropertiesUndefined\"\n\t\t\t);\n\t\t}\n\n\t\tconst primaryKeys: string[] = [];\n\n\t\tconst props: IEntitySchemaProperty<T>[] = [...entitySchema.properties];\n\n\t\tprops.unshift({\n\t\t\tproperty: MySqlEntityStorageConnector._PARTITION_KEY as keyof T,\n\t\t\ttype: EntitySchemaPropertyType.String,\n\t\t\tisPrimary: true\n\t\t});\n\n\t\tconst columnDefinitions = props\n\t\t\t.map(prop => {\n\t\t\t\tlet sqlType = sqlTypeMap[prop.type] || \"TEXT\";\n\t\t\t\tif (prop.format) {\n\t\t\t\t\tswitch (prop.type) {\n\t\t\t\t\t\tcase EntitySchemaPropertyType.String:\n\t\t\t\t\t\t\tsqlType = \"LONGTEXT\";\n\t\t\t\t\t\t\tswitch (prop.format) {\n\t\t\t\t\t\t\t\tcase \"uuid\":\n\t\t\t\t\t\t\t\t\tsqlType = \"CHAR(36)\";\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase \"date\":\n\t\t\t\t\t\t\t\tcase \"date-time\":\n\t\t\t\t\t\t\t\t\tsqlType = \"LONGTEXT\";\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase EntitySchemaPropertyType.Number:\n\t\t\t\t\t\t\tsqlType = \"FLOAT\";\n\t\t\t\t\t\t\tswitch (prop.format) {\n\t\t\t\t\t\t\t\tcase \"float\":\n\t\t\t\t\t\t\t\t\tsqlType = \"FLOAT\";\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase \"double\":\n\t\t\t\t\t\t\t\t\tsqlType = \"DOUBLE\";\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase EntitySchemaPropertyType.Integer:\n\t\t\t\t\t\t\tsqlType = \"INT\";\n\t\t\t\t\t\t\tswitch (prop.format) {\n\t\t\t\t\t\t\t\tcase \"int8\":\n\t\t\t\t\t\t\t\tcase \"uint8\":\n\t\t\t\t\t\t\t\t\tsqlType = \"TINYINT\";\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase \"int16\":\n\t\t\t\t\t\t\t\tcase \"uint16\":\n\t\t\t\t\t\t\t\t\tsqlType = \"SMALLINT\";\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase \"int32\":\n\t\t\t\t\t\t\t\tcase \"uint32\":\n\t\t\t\t\t\t\t\t\tsqlType = \"INT\";\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase \"int64\":\n\t\t\t\t\t\t\t\tcase \"uint64\":\n\t\t\t\t\t\t\t\t\tsqlType = \"BIGINT\";\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst columnName = String(prop.property);\n\t\t\t\tconst nullable = prop.optional ? \" NULL\" : \" NOT NULL\";\n\n\t\t\t\tif (prop.isPrimary) {\n\t\t\t\t\tif (sqlType === \"LONGTEXT\" || sqlType === \"TEXT\") {\n\t\t\t\t\t\tprimaryKeys.push(`\\`${columnName}\\`(255)`);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tprimaryKeys.push(`\\`${columnName}\\``);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn `\\`${columnName}\\` ${sqlType}${nullable}`;\n\t\t\t})\n\t\t\t.join(\", \");\n\n\t\tconst primaryKeyDefinition =\n\t\t\tprimaryKeys.length > 0 ? `, PRIMARY KEY (${primaryKeys.join(\", \")})` : \"\";\n\t\treturn columnDefinitions + primaryKeyDefinition;\n\t}\n}\n"]}
@@ -61,4 +61,8 @@ export interface IMySqlEntityStorageConnectorConfig {
61
61
  */
62
62
  queueLimit?: number;
63
63
  };
64
+ /**
65
+ * Maximum milliseconds to wait for the per-directory write lock before throwing.
66
+ */
67
+ mutexTimeoutMs?: number;
64
68
  }
package/docs/changelog.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.9.1-next.8](https://github.com/iotaledger/twin-entity-storage/compare/entity-storage-connector-mysql-v0.9.1-next.7...entity-storage-connector-mysql-v0.9.1-next.8) (2026-07-03)
4
+
5
+
6
+ ### Features
7
+
8
+ * add mutex lock to mysql pool ([44762c6](https://github.com/iotaledger/twin-entity-storage/commit/44762c6bc517bb3baf6b5261a9f9fd93992fc238))
9
+
10
+
11
+ ### Dependencies
12
+
13
+ * The following workspace dependencies were updated
14
+ * dependencies
15
+ * @twin.org/entity-storage-models bumped from 0.9.1-next.7 to 0.9.1-next.8
16
+ * devDependencies
17
+ * @twin.org/entity-storage-connector-memory bumped from 0.9.1-next.7 to 0.9.1-next.8
18
+
3
19
  ## [0.9.1-next.7](https://github.com/iotaledger/twin-entity-storage/compare/entity-storage-connector-mysql-v0.9.1-next.6...entity-storage-connector-mysql-v0.9.1-next.7) (2026-07-02)
4
20
 
5
21
 
@@ -129,3 +129,11 @@ Maximum queued requests (0 = unlimited).
129
129
  ```ts
130
130
  0
131
131
  ```
132
+
133
+ ***
134
+
135
+ ### mutexTimeoutMs? {#mutextimeoutms}
136
+
137
+ > `optional` **mutexTimeoutMs?**: `number`
138
+
139
+ Maximum milliseconds to wait for the per-directory write lock before throwing.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@twin.org/entity-storage-connector-mysql",
3
- "version": "0.9.1-next.7",
3
+ "version": "0.9.1-next.8",
4
4
  "description": "MySQL connector for relational persistence with SQL querying.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -18,7 +18,7 @@
18
18
  "@twin.org/core": "next",
19
19
  "@twin.org/data-json-ld": "next",
20
20
  "@twin.org/entity": "next",
21
- "@twin.org/entity-storage-models": "0.9.1-next.7",
21
+ "@twin.org/entity-storage-models": "0.9.1-next.8",
22
22
  "@twin.org/logging-models": "next",
23
23
  "@twin.org/nameof": "next",
24
24
  "mysql2": "3.22.5"