@twin.org/entity-storage-connector-scylladb 0.0.2-next.1 → 0.0.2-next.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -13,7 +13,7 @@ npm install @twin.org/entity-storage-connector-scylladb
13
13
  The tests developed are functional tests and need an instance of ScyllaDB up and running. To run ScyllaDB locally:
14
14
 
15
15
  ```shell
16
- docker run -p 9500:9042 --name twin-entity-storage-scylla --hostname scylla -d scylladb/scylla:5.4.9 --smp 1
16
+ docker run -p 9500:9042 --name twin-entity-storage-scylladb --hostname scylla -d scylladb/scylla:5.4.9 --smp 1
17
17
  ```
18
18
 
19
19
  Afterwards you can run the tests as follows:
@@ -2,7 +2,6 @@
2
2
 
3
3
  var core = require('@twin.org/core');
4
4
  var entity = require('@twin.org/entity');
5
- var loggingModels = require('@twin.org/logging-models');
6
5
  var cassandraDriver = require('cassandra-driver');
7
6
 
8
7
  // Copyright 2024 IOTA Stiftung.
@@ -12,15 +11,14 @@ var cassandraDriver = require('cassandra-driver');
12
11
  */
13
12
  class AbstractScyllaDBConnector {
14
13
  /**
15
- * Limit the number of entities when finding.
16
- * @internal
14
+ * Runtime name for the class.
17
15
  */
18
- static PAGE_SIZE = 40;
16
+ static CLASS_NAME = "AbstractScyllaDBConnector";
19
17
  /**
20
- * Runtime name for the class.
18
+ * Limit the number of entities when finding.
21
19
  * @internal
22
20
  */
23
- CLASS_NAME;
21
+ static _DEFAULT_LIMIT = 40;
24
22
  /**
25
23
  * The name of the database table.
26
24
  * @internal
@@ -32,7 +30,7 @@ class AbstractScyllaDBConnector {
32
30
  */
33
31
  _config;
34
32
  /**
35
- * The logging connector.
33
+ * The logging component.
36
34
  * @internal
37
35
  */
38
36
  _logging;
@@ -49,22 +47,18 @@ class AbstractScyllaDBConnector {
49
47
  /**
50
48
  * Create a new instance of AbstractScyllaDBConnector.
51
49
  * @param options The options for the connector.
52
- * @param options.loggingConnectorType The type of logging connector to use, defaults to no logging.
50
+ * @param options.loggingComponentType The type of logging component to use, defaults to no logging.
53
51
  * @param options.entitySchema The name of the entity schema.
54
52
  * @param options.config The configuration for the connector.
55
- * @param className The name of the derived class.
56
- */
57
- constructor(options, className) {
58
- this.CLASS_NAME = className;
59
- core.Guards.object(this.CLASS_NAME, "options", options);
60
- core.Guards.stringValue(this.CLASS_NAME, "options.entitySchema", options.entitySchema);
61
- core.Guards.object(this.CLASS_NAME, "options.config", options.config);
62
- core.Guards.arrayValue(this.CLASS_NAME, "options.config.hosts", options.config.hosts);
63
- core.Guards.stringValue(this.CLASS_NAME, "options.config.localDataCenter", options.config.localDataCenter);
64
- core.Guards.stringValue(this.CLASS_NAME, "options.config.keyspace", options.config.keyspace);
65
- if (core.Is.stringValue(options.loggingConnectorType)) {
66
- this._logging = loggingModels.LoggingConnectorFactory.get(options.loggingConnectorType);
67
- }
53
+ */
54
+ constructor(options) {
55
+ core.Guards.object(AbstractScyllaDBConnector.CLASS_NAME, "options", options);
56
+ core.Guards.stringValue(AbstractScyllaDBConnector.CLASS_NAME, "options.entitySchema", options.entitySchema);
57
+ core.Guards.object(AbstractScyllaDBConnector.CLASS_NAME, "options.config", options.config);
58
+ core.Guards.arrayValue(AbstractScyllaDBConnector.CLASS_NAME, "options.config.hosts", options.config.hosts);
59
+ core.Guards.stringValue(AbstractScyllaDBConnector.CLASS_NAME, "options.config.localDataCenter", options.config.localDataCenter);
60
+ core.Guards.stringValue(AbstractScyllaDBConnector.CLASS_NAME, "options.config.keyspace", options.config.keyspace);
61
+ this._logging = core.ComponentFactory.getIfExists(options.loggingComponentType ?? "logging");
68
62
  this._entitySchema = entity.EntitySchemaFactory.get(options.entitySchema);
69
63
  this._primaryKey = entity.EntitySchemaHelper.getPrimaryKey(this._entitySchema);
70
64
  this._config = options.config;
@@ -85,7 +79,7 @@ class AbstractScyllaDBConnector {
85
79
  * @returns The object if it can be found or undefined.
86
80
  */
87
81
  async get(id, secondaryIndex, conditions) {
88
- core.Guards.stringValue(this.CLASS_NAME, "id", id);
82
+ core.Guards.stringValue(AbstractScyllaDBConnector.CLASS_NAME, "id", id);
89
83
  let connection;
90
84
  try {
91
85
  const indexField = secondaryIndex ?? this._primaryKey?.property;
@@ -95,7 +89,7 @@ class AbstractScyllaDBConnector {
95
89
  }
96
90
  await this._logging?.log({
97
91
  level: "info",
98
- source: this.CLASS_NAME,
92
+ source: AbstractScyllaDBConnector.CLASS_NAME,
99
93
  ts: Date.now(),
100
94
  message: "sql",
101
95
  data: { sql }
@@ -107,7 +101,7 @@ class AbstractScyllaDBConnector {
107
101
  }
108
102
  }
109
103
  catch (error) {
110
- throw new core.GeneralError(this.CLASS_NAME, "getFailed", {
104
+ throw new core.GeneralError(AbstractScyllaDBConnector.CLASS_NAME, "getFailed", {
111
105
  id
112
106
  }, error);
113
107
  }
@@ -120,15 +114,15 @@ class AbstractScyllaDBConnector {
120
114
  * @param conditions The conditions to match for the entities.
121
115
  * @param sortProperties The optional sort order.
122
116
  * @param properties The optional properties to return, defaults to all.
123
- * @param cursor The cursor to request the next page of entities.
124
- * @param pageSize The suggested number of entities to return in each chunk, in some scenarios can return a different amount.
117
+ * @param cursor The cursor to request the next chunk of entities.
118
+ * @param limit The suggested number of entities to return in each chunk, in some scenarios can return a different amount.
125
119
  * @returns All the entities for the storage matching the conditions,
126
120
  * and a cursor which can be used to request more entities.
127
121
  */
128
- async query(conditions, sortProperties, properties, cursor, pageSize) {
122
+ async query(conditions, sortProperties, properties, cursor, limit) {
129
123
  let connection;
130
124
  try {
131
- let returnSize = pageSize ?? AbstractScyllaDBConnector.PAGE_SIZE;
125
+ let returnSize = limit ?? AbstractScyllaDBConnector._DEFAULT_LIMIT;
132
126
  let sql = `SELECT * FROM "${this._fullTableName}"`;
133
127
  if (core.Is.array(properties)) {
134
128
  const fields = [];
@@ -220,7 +214,7 @@ class AbstractScyllaDBConnector {
220
214
  }
221
215
  await this._logging?.log({
222
216
  level: "info",
223
- source: this.CLASS_NAME,
217
+ source: AbstractScyllaDBConnector.CLASS_NAME,
224
218
  ts: Date.now(),
225
219
  message: "sql",
226
220
  data: { sql }
@@ -236,7 +230,7 @@ class AbstractScyllaDBConnector {
236
230
  };
237
231
  }
238
232
  catch (error) {
239
- throw new core.GeneralError(this.CLASS_NAME, "findFailed", { table: this._fullTableName }, error);
233
+ throw new core.GeneralError(AbstractScyllaDBConnector.CLASS_NAME, "findFailed", { table: this._fullTableName }, error);
240
234
  }
241
235
  finally {
242
236
  await this.closeConnection(connection);
@@ -281,13 +275,13 @@ class AbstractScyllaDBConnector {
281
275
  * @returns The rows.
282
276
  * @internal
283
277
  */
284
- async queryDB(connection, sql, params, pageState, pageSize) {
278
+ async queryDB(connection, sql, params, pageState, limit) {
285
279
  return new Promise((resolve, reject) => {
286
280
  const rows = [];
287
281
  connection.eachRow(sql, params, {
288
282
  prepare: true,
289
283
  autoPage: false,
290
- fetchSize: pageSize ?? AbstractScyllaDBConnector.PAGE_SIZE,
284
+ fetchSize: limit ?? AbstractScyllaDBConnector._DEFAULT_LIMIT,
291
285
  pageState
292
286
  }, (n, row) => {
293
287
  rows.push(row);
@@ -342,7 +336,7 @@ class AbstractScyllaDBConnector {
342
336
  return JSON.parse(value);
343
337
  }
344
338
  catch {
345
- throw new core.GeneralError(this.CLASS_NAME, "parseJSONFailed", {
339
+ throw new core.GeneralError(AbstractScyllaDBConnector.CLASS_NAME, "parseJSONFailed", {
346
340
  name: fieldDescriptor.property,
347
341
  value
348
342
  });
@@ -362,7 +356,6 @@ class AbstractScyllaDBConnector {
362
356
  */
363
357
  propertyToDbValue(value, fieldDescriptor) {
364
358
  if (fieldDescriptor) {
365
- // eslint-disable-next-line no-constant-condition
366
359
  if (fieldDescriptor.type === "string" && fieldDescriptor.format === "json") {
367
360
  return core.Is.empty(value) ? "null" : this.jsonWrap(value);
368
361
  }
@@ -411,7 +404,6 @@ class AbstractScyllaDBConnector {
411
404
  */
412
405
  jsonWrap(value) {
413
406
  let json = JSON.stringify(value);
414
- // eslint-disable-next-line no-control-regex
415
407
  json = json.replace(/[\b\0\t\n\r\u001A\\]/g, s => {
416
408
  switch (s) {
417
409
  case "\0":
@@ -443,24 +435,25 @@ class ScyllaDBTableConnector extends AbstractScyllaDBConnector {
443
435
  /**
444
436
  * Runtime name for the class.
445
437
  */
446
- CLASS_NAME = "ScyllaDBTableConnector";
438
+ static CLASS_NAME = "ScyllaDBTableConnector";
447
439
  /**
448
440
  * Create a new instance of ScyllaDBTableConnector.
449
441
  * @param options The options for the connector.
450
442
  */
443
+ // eslint-disable-next-line @typescript-eslint/no-useless-constructor
451
444
  constructor(options) {
452
- super(options, "ScyllaDBTableConnector");
445
+ super(options);
453
446
  }
454
447
  /**
455
448
  * Bootstrap the component by creating and initializing any resources it needs.
456
- * @param nodeLoggingConnectorType The node logging connector type, defaults to "node-logging".
449
+ * @param nodeLoggingComponentType The node logging component type.
457
450
  * @returns True if the bootstrapping process was successful.
458
451
  */
459
- async bootstrap(nodeLoggingConnectorType) {
460
- const nodeLogging = loggingModels.LoggingConnectorFactory.getIfExists(nodeLoggingConnectorType ?? "node-logging");
452
+ async bootstrap(nodeLoggingComponentType) {
453
+ const nodeLogging = core.ComponentFactory.getIfExists(nodeLoggingComponentType);
461
454
  nodeLogging?.log({
462
455
  level: "info",
463
- source: this.CLASS_NAME,
456
+ source: ScyllaDBTableConnector.CLASS_NAME,
464
457
  ts: Date.now(),
465
458
  message: "tableCreating",
466
459
  data: { table: this._fullTableName }
@@ -488,7 +481,7 @@ class ScyllaDBTableConnector extends AbstractScyllaDBConnector {
488
481
  "${subTypeSchemaRef}" (${typeFields.join(",")})`;
489
482
  await nodeLogging?.log({
490
483
  level: "info",
491
- source: this.CLASS_NAME,
484
+ source: ScyllaDBTableConnector.CLASS_NAME,
492
485
  ts: Date.now(),
493
486
  message: "sql",
494
487
  data: { sql }
@@ -496,7 +489,7 @@ class ScyllaDBTableConnector extends AbstractScyllaDBConnector {
496
489
  await this.execute(dbConnection, sql);
497
490
  await nodeLogging?.log({
498
491
  level: "info",
499
- source: this.CLASS_NAME,
492
+ source: ScyllaDBTableConnector.CLASS_NAME,
500
493
  ts: Date.now(),
501
494
  message: "typeCreated",
502
495
  data: { typeName: subTypeSchemaRef }
@@ -526,7 +519,7 @@ class ScyllaDBTableConnector extends AbstractScyllaDBConnector {
526
519
  const sql = `CREATE TABLE IF NOT EXISTS "${this._fullTableName}" (${fields.join(", ")})`;
527
520
  await nodeLogging?.log({
528
521
  level: "info",
529
- source: this.CLASS_NAME,
522
+ source: ScyllaDBTableConnector.CLASS_NAME,
530
523
  ts: Date.now(),
531
524
  message: "sql",
532
525
  data: { sql }
@@ -534,7 +527,7 @@ class ScyllaDBTableConnector extends AbstractScyllaDBConnector {
534
527
  await this.execute(dbConnection, sql);
535
528
  await nodeLogging?.log({
536
529
  level: "info",
537
- source: this.CLASS_NAME,
530
+ source: ScyllaDBTableConnector.CLASS_NAME,
538
531
  ts: Date.now(),
539
532
  message: "tableCreated",
540
533
  data: { table: this._fullTableName }
@@ -544,7 +537,7 @@ class ScyllaDBTableConnector extends AbstractScyllaDBConnector {
544
537
  if (core.BaseError.isErrorCode(err, "ResourceInUseException")) {
545
538
  await nodeLogging?.log({
546
539
  level: "info",
547
- source: this.CLASS_NAME,
540
+ source: ScyllaDBTableConnector.CLASS_NAME,
548
541
  ts: Date.now(),
549
542
  message: "tableExists",
550
543
  data: { table: this._fullTableName }
@@ -553,7 +546,7 @@ class ScyllaDBTableConnector extends AbstractScyllaDBConnector {
553
546
  else {
554
547
  await nodeLogging?.log({
555
548
  level: "error",
556
- source: this.CLASS_NAME,
549
+ source: ScyllaDBTableConnector.CLASS_NAME,
557
550
  ts: Date.now(),
558
551
  message: "tableCreateFailed",
559
552
  error: err,
@@ -570,7 +563,7 @@ class ScyllaDBTableConnector extends AbstractScyllaDBConnector {
570
563
  * @param conditions The optional conditions to match for the entities.
571
564
  */
572
565
  async set(entity$1, conditions) {
573
- core.Guards.object(this.CLASS_NAME, "entity", entity$1);
566
+ core.Guards.object(ScyllaDBTableConnector.CLASS_NAME, "entity", entity$1);
574
567
  entity.EntitySchemaHelper.validateEntity(entity$1, this.getSchema());
575
568
  let connection;
576
569
  const id = entity$1[this._primaryKey?.property];
@@ -599,7 +592,7 @@ class ScyllaDBTableConnector extends AbstractScyllaDBConnector {
599
592
  const sql = `UPDATE "${this._fullTableName}" SET ${updateValues.join(",")}${conditionString}`;
600
593
  await this._logging?.log({
601
594
  level: "info",
602
- source: this.CLASS_NAME,
595
+ source: ScyllaDBTableConnector.CLASS_NAME,
603
596
  ts: Date.now(),
604
597
  message: "sql",
605
598
  data: { sql }
@@ -608,7 +601,7 @@ class ScyllaDBTableConnector extends AbstractScyllaDBConnector {
608
601
  await this.execute(connection, sql, propValues);
609
602
  }
610
603
  catch (error) {
611
- throw new core.GeneralError(this.CLASS_NAME, "entityStorage.setFailed", {
604
+ throw new core.GeneralError(ScyllaDBTableConnector.CLASS_NAME, "setFailed", {
612
605
  id
613
606
  }, error);
614
607
  }
@@ -622,7 +615,7 @@ class ScyllaDBTableConnector extends AbstractScyllaDBConnector {
622
615
  * @param conditions The optional conditions to match for the entities.
623
616
  */
624
617
  async remove(id, conditions) {
625
- core.Guards.stringValue(this.CLASS_NAME, "id", id);
618
+ core.Guards.stringValue(ScyllaDBTableConnector.CLASS_NAME, "id", id);
626
619
  let connection;
627
620
  try {
628
621
  conditions ??= [];
@@ -631,16 +624,16 @@ class ScyllaDBTableConnector extends AbstractScyllaDBConnector {
631
624
  const sql = `DELETE FROM "${this._fullTableName}" WHERE ${sqlCondition}`;
632
625
  await this._logging?.log({
633
626
  level: "info",
634
- source: this.CLASS_NAME,
627
+ source: ScyllaDBTableConnector.CLASS_NAME,
635
628
  ts: Date.now(),
636
- message: "entityStorage.sqlRemove",
629
+ message: "sql",
637
630
  data: { sql }
638
631
  });
639
632
  connection = await this.openConnection();
640
633
  await this.execute(connection, sql, conditionValues);
641
634
  }
642
635
  catch (error) {
643
- throw new core.GeneralError(this.CLASS_NAME, "removeFailed", {
636
+ throw new core.GeneralError(ScyllaDBTableConnector.CLASS_NAME, "removeFailed", {
644
637
  id
645
638
  }, error);
646
639
  }
@@ -658,7 +651,7 @@ class ScyllaDBTableConnector extends AbstractScyllaDBConnector {
658
651
  await connection.execute(`DROP TABLE IF EXISTS "${this._fullTableName}"`);
659
652
  }
660
653
  catch (error) {
661
- throw new core.GeneralError(this.CLASS_NAME, "dropTableFailed", { table: this._fullTableName }, error);
654
+ throw new core.GeneralError(ScyllaDBTableConnector.CLASS_NAME, "dropTableFailed", { table: this._fullTableName }, error);
662
655
  }
663
656
  finally {
664
657
  await this.closeConnection(connection);
@@ -674,7 +667,7 @@ class ScyllaDBTableConnector extends AbstractScyllaDBConnector {
674
667
  await connection.execute(`TRUNCATE TABLE "${this._fullTableName}"`);
675
668
  }
676
669
  catch (error) {
677
- throw new core.GeneralError(this.CLASS_NAME, "truncateTableFailed", { table: this._fullTableName }, error);
670
+ throw new core.GeneralError(ScyllaDBTableConnector.CLASS_NAME, "truncateTableFailed", { table: this._fullTableName }, error);
678
671
  }
679
672
  finally {
680
673
  await this.closeConnection(connection);
@@ -739,7 +732,7 @@ class ScyllaDBTableConnector extends AbstractScyllaDBConnector {
739
732
  break;
740
733
  case "object":
741
734
  if (!logicalField.itemTypeRef) {
742
- throw new core.GeneralError(this.CLASS_NAME, "itemTypeNotDefined", {
735
+ throw new core.GeneralError(ScyllaDBTableConnector.CLASS_NAME, "itemTypeNotDefined", {
743
736
  type: logicalField.type,
744
737
  table: this._fullTableName
745
738
  });
@@ -748,7 +741,7 @@ class ScyllaDBTableConnector extends AbstractScyllaDBConnector {
748
741
  break;
749
742
  case "array":
750
743
  if (!logicalField.itemType && !logicalField.itemTypeRef) {
751
- throw new core.GeneralError(this.CLASS_NAME, "itemTypeNotDefined", {
744
+ throw new core.GeneralError(ScyllaDBTableConnector.CLASS_NAME, "itemTypeNotDefined", {
752
745
  type: logicalField.type,
753
746
  table: this._fullTableName
754
747
  });
@@ -794,7 +787,7 @@ class ScyllaDBViewConnector extends AbstractScyllaDBConnector {
794
787
  /**
795
788
  * Runtime name for the class.
796
789
  */
797
- CLASS_NAME = "ScyllaDBViewConnector";
790
+ static CLASS_NAME = "ScyllaDBViewConnector";
798
791
  /**
799
792
  * The view descriptor.
800
793
  * @internal
@@ -812,10 +805,10 @@ class ScyllaDBViewConnector extends AbstractScyllaDBConnector {
812
805
  constructor(options) {
813
806
  // We need this conversion so that types can match in the superclass and reuse the get method
814
807
  super({
815
- loggingConnectorType: options.loggingConnectorType,
808
+ loggingComponentType: options.loggingComponentType,
816
809
  entitySchema: options.viewSchema,
817
810
  config: options.config
818
- }, "ScyllaDBViewConnector");
811
+ });
819
812
  this._viewSchema = entity.EntitySchemaHelper.getSchema(options.viewSchema);
820
813
  // We need the underlying class to use the view name for lookups
821
814
  // so substitute the view name for the entity name
@@ -825,14 +818,14 @@ class ScyllaDBViewConnector extends AbstractScyllaDBConnector {
825
818
  }
826
819
  /**
827
820
  * Bootstrap the component by creating and initializing any resources it needs.
828
- * @param nodeLoggingConnectorType The node logging connector type, defaults to "node-logging".
821
+ * @param nodeLoggingComponentType The node logging component type.
829
822
  * @returns True if the bootstrapping process was successful.
830
823
  */
831
- async bootstrap(nodeLoggingConnectorType) {
832
- const nodeLogging = loggingModels.LoggingConnectorFactory.getIfExists(nodeLoggingConnectorType ?? "node-logging");
824
+ async bootstrap(nodeLoggingComponentType) {
825
+ const nodeLogging = core.ComponentFactory.getIfExists(nodeLoggingComponentType);
833
826
  nodeLogging?.log({
834
827
  level: "info",
835
- source: this.CLASS_NAME,
828
+ source: ScyllaDBViewConnector.CLASS_NAME,
836
829
  ts: Date.now(),
837
830
  message: "viewCreating",
838
831
  data: { view: this._fullTableName }
@@ -855,7 +848,7 @@ class ScyllaDBViewConnector extends AbstractScyllaDBConnector {
855
848
  await this.execute(dbConnection, sql);
856
849
  nodeLogging?.log({
857
850
  level: "info",
858
- source: this.CLASS_NAME,
851
+ source: ScyllaDBViewConnector.CLASS_NAME,
859
852
  ts: Date.now(),
860
853
  message: "viewCreated",
861
854
  data: { view: this._fullTableName }
@@ -865,7 +858,7 @@ class ScyllaDBViewConnector extends AbstractScyllaDBConnector {
865
858
  if (core.BaseError.isErrorCode(err, "ResourceInUseException")) {
866
859
  nodeLogging?.log({
867
860
  level: "info",
868
- source: this.CLASS_NAME,
861
+ source: ScyllaDBViewConnector.CLASS_NAME,
869
862
  ts: Date.now(),
870
863
  message: "viewExists",
871
864
  data: { view: this._fullTableName }
@@ -874,7 +867,7 @@ class ScyllaDBViewConnector extends AbstractScyllaDBConnector {
874
867
  else {
875
868
  nodeLogging?.log({
876
869
  level: "error",
877
- source: this.CLASS_NAME,
870
+ source: ScyllaDBViewConnector.CLASS_NAME,
878
871
  ts: Date.now(),
879
872
  message: "viewCreateFailed",
880
873
  error: err,
@@ -890,14 +883,18 @@ class ScyllaDBViewConnector extends AbstractScyllaDBConnector {
890
883
  * @param entity The entity to set.
891
884
  */
892
885
  async set(entity) {
893
- throw new core.NotSupportedError(this.CLASS_NAME, "set", {});
886
+ throw new core.NotSupportedError(ScyllaDBViewConnector.CLASS_NAME, "notSupported", {
887
+ methodName: "set"
888
+ });
894
889
  }
895
890
  /**
896
891
  * Delete the entity.
897
892
  * @param id The id of the entity to remove.
898
893
  */
899
894
  async remove(id) {
900
- throw new core.NotSupportedError(this.CLASS_NAME, "remove", {});
895
+ throw new core.NotSupportedError(ScyllaDBViewConnector.CLASS_NAME, "notSupported", {
896
+ methodName: "remove"
897
+ });
901
898
  }
902
899
  }
903
900