@streamr/node 100.0.0-rc.0

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.
Files changed (238) hide show
  1. package/LICENSE +78 -0
  2. package/README.md +54 -0
  3. package/bin/broker.ts +36 -0
  4. package/bin/config-wizard.js +4 -0
  5. package/bin/config-wizard.ts +17 -0
  6. package/bin/delete-expired-data.ts +41 -0
  7. package/bin/entry-point.ts +27 -0
  8. package/configs/development-1.env.json +68 -0
  9. package/configs/development-2.env.json +53 -0
  10. package/configs/development-3.env.json +53 -0
  11. package/configs/development-prod-resend.env.json +21 -0
  12. package/configs/docker-1.env.json +72 -0
  13. package/configs/docker-2.env.json +58 -0
  14. package/configs/docker-3.env.json +58 -0
  15. package/configuration.md +38 -0
  16. package/dist/bin/broker.d.ts +2 -0
  17. package/dist/bin/broker.js +42 -0
  18. package/dist/bin/broker.js.map +1 -0
  19. package/dist/bin/config-wizard.d.ts +2 -0
  20. package/dist/bin/config-wizard.js +22 -0
  21. package/dist/bin/config-wizard.js.map +1 -0
  22. package/dist/bin/delete-expired-data.d.ts +2 -0
  23. package/dist/bin/delete-expired-data.js +44 -0
  24. package/dist/bin/delete-expired-data.js.map +1 -0
  25. package/dist/bin/entry-point.d.ts +2 -0
  26. package/dist/bin/entry-point.js +28 -0
  27. package/dist/bin/entry-point.js.map +1 -0
  28. package/dist/package.json +78 -0
  29. package/dist/src/Plugin.d.ts +33 -0
  30. package/dist/src/Plugin.js +43 -0
  31. package/dist/src/Plugin.js.map +1 -0
  32. package/dist/src/apiAuthentication.d.ts +4 -0
  33. package/dist/src/apiAuthentication.js +16 -0
  34. package/dist/src/apiAuthentication.js.map +1 -0
  35. package/dist/src/broker.d.ts +8 -0
  36. package/dist/src/broker.js +69 -0
  37. package/dist/src/broker.js.map +1 -0
  38. package/dist/src/config/ConfigWizard.d.ts +5 -0
  39. package/dist/src/config/ConfigWizard.js +466 -0
  40. package/dist/src/config/ConfigWizard.js.map +1 -0
  41. package/dist/src/config/config.d.ts +26 -0
  42. package/dist/src/config/config.js +92 -0
  43. package/dist/src/config/config.js.map +1 -0
  44. package/dist/src/config/config.schema.json +86 -0
  45. package/dist/src/config/definitions.schema.json +35 -0
  46. package/dist/src/config/migration.d.ts +6 -0
  47. package/dist/src/config/migration.js +210 -0
  48. package/dist/src/config/migration.js.map +1 -0
  49. package/dist/src/config/validateConfig.d.ts +4 -0
  50. package/dist/src/config/validateConfig.js +40 -0
  51. package/dist/src/config/validateConfig.js.map +1 -0
  52. package/dist/src/exports.d.ts +3 -0
  53. package/dist/src/exports.js +6 -0
  54. package/dist/src/exports.js.map +1 -0
  55. package/dist/src/helpers/PayloadFormat.d.ts +19 -0
  56. package/dist/src/helpers/PayloadFormat.js +85 -0
  57. package/dist/src/helpers/PayloadFormat.js.map +1 -0
  58. package/dist/src/helpers/applyPluginClientConfigs.d.ts +3 -0
  59. package/dist/src/helpers/applyPluginClientConfigs.js +29 -0
  60. package/dist/src/helpers/applyPluginClientConfigs.js.map +1 -0
  61. package/dist/src/helpers/fetchOrThrow.d.ts +2 -0
  62. package/dist/src/helpers/fetchOrThrow.js +20 -0
  63. package/dist/src/helpers/fetchOrThrow.js.map +1 -0
  64. package/dist/src/helpers/generateMnemonicFromAddress.d.ts +5 -0
  65. package/dist/src/helpers/generateMnemonicFromAddress.js +16 -0
  66. package/dist/src/helpers/generateMnemonicFromAddress.js.map +1 -0
  67. package/dist/src/helpers/multiply.d.ts +1 -0
  68. package/dist/src/helpers/multiply.js +10 -0
  69. package/dist/src/helpers/multiply.js.map +1 -0
  70. package/dist/src/helpers/parser.d.ts +9 -0
  71. package/dist/src/helpers/parser.js +62 -0
  72. package/dist/src/helpers/parser.js.map +1 -0
  73. package/dist/src/helpers/partitions.d.ts +8 -0
  74. package/dist/src/helpers/partitions.js +32 -0
  75. package/dist/src/helpers/partitions.js.map +1 -0
  76. package/dist/src/helpers/weightedSample.d.ts +16 -0
  77. package/dist/src/helpers/weightedSample.js +35 -0
  78. package/dist/src/helpers/weightedSample.js.map +1 -0
  79. package/dist/src/httpServer.d.ts +16 -0
  80. package/dist/src/httpServer.js +71 -0
  81. package/dist/src/httpServer.js.map +1 -0
  82. package/dist/src/pluginRegistry.d.ts +3 -0
  83. package/dist/src/pluginRegistry.js +35 -0
  84. package/dist/src/pluginRegistry.js.map +1 -0
  85. package/dist/src/plugins/consoleMetrics/ConsoleMetricsPlugin.d.ts +12 -0
  86. package/dist/src/plugins/consoleMetrics/ConsoleMetricsPlugin.js +36 -0
  87. package/dist/src/plugins/consoleMetrics/ConsoleMetricsPlugin.js.map +1 -0
  88. package/dist/src/plugins/consoleMetrics/config.schema.json +18 -0
  89. package/dist/src/plugins/http/HttpPlugin.d.ts +8 -0
  90. package/dist/src/plugins/http/HttpPlugin.js +23 -0
  91. package/dist/src/plugins/http/HttpPlugin.js.map +1 -0
  92. package/dist/src/plugins/http/config.schema.json +12 -0
  93. package/dist/src/plugins/http/publishEndpoint.d.ts +3 -0
  94. package/dist/src/plugins/http/publishEndpoint.js +72 -0
  95. package/dist/src/plugins/http/publishEndpoint.js.map +1 -0
  96. package/dist/src/plugins/info/InfoPlugin.d.ts +9 -0
  97. package/dist/src/plugins/info/InfoPlugin.js +31 -0
  98. package/dist/src/plugins/info/InfoPlugin.js.map +1 -0
  99. package/dist/src/plugins/info/config.schema.json +12 -0
  100. package/dist/src/plugins/mqtt/Bridge.d.ts +40 -0
  101. package/dist/src/plugins/mqtt/Bridge.js +136 -0
  102. package/dist/src/plugins/mqtt/Bridge.js.map +1 -0
  103. package/dist/src/plugins/mqtt/MqttPlugin.d.ts +14 -0
  104. package/dist/src/plugins/mqtt/MqttPlugin.js +30 -0
  105. package/dist/src/plugins/mqtt/MqttPlugin.js.map +1 -0
  106. package/dist/src/plugins/mqtt/MqttServer.d.ts +22 -0
  107. package/dist/src/plugins/mqtt/MqttServer.js +109 -0
  108. package/dist/src/plugins/mqtt/MqttServer.js.map +1 -0
  109. package/dist/src/plugins/mqtt/config.schema.json +26 -0
  110. package/dist/src/plugins/operator/ConsistentHashRing.d.ts +20 -0
  111. package/dist/src/plugins/operator/ConsistentHashRing.js +64 -0
  112. package/dist/src/plugins/operator/ConsistentHashRing.js.map +1 -0
  113. package/dist/src/plugins/operator/ContractFacade.d.ts +80 -0
  114. package/dist/src/plugins/operator/ContractFacade.js +364 -0
  115. package/dist/src/plugins/operator/ContractFacade.js.map +1 -0
  116. package/dist/src/plugins/operator/MaintainTopologyHelper.d.ts +23 -0
  117. package/dist/src/plugins/operator/MaintainTopologyHelper.js +75 -0
  118. package/dist/src/plugins/operator/MaintainTopologyHelper.js.map +1 -0
  119. package/dist/src/plugins/operator/MaintainTopologyService.d.ts +11 -0
  120. package/dist/src/plugins/operator/MaintainTopologyService.js +57 -0
  121. package/dist/src/plugins/operator/MaintainTopologyService.js.map +1 -0
  122. package/dist/src/plugins/operator/OperatorFleetState.d.ts +33 -0
  123. package/dist/src/plugins/operator/OperatorFleetState.js +112 -0
  124. package/dist/src/plugins/operator/OperatorFleetState.js.map +1 -0
  125. package/dist/src/plugins/operator/OperatorPlugin.d.ts +50 -0
  126. package/dist/src/plugins/operator/OperatorPlugin.js +159 -0
  127. package/dist/src/plugins/operator/OperatorPlugin.js.map +1 -0
  128. package/dist/src/plugins/operator/StreamPartAssignments.d.ts +28 -0
  129. package/dist/src/plugins/operator/StreamPartAssignments.js +104 -0
  130. package/dist/src/plugins/operator/StreamPartAssignments.js.map +1 -0
  131. package/dist/src/plugins/operator/announceNodeToContract.d.ts +3 -0
  132. package/dist/src/plugins/operator/announceNodeToContract.js +39 -0
  133. package/dist/src/plugins/operator/announceNodeToContract.js.map +1 -0
  134. package/dist/src/plugins/operator/announceNodeToStream.d.ts +3 -0
  135. package/dist/src/plugins/operator/announceNodeToStream.js +25 -0
  136. package/dist/src/plugins/operator/announceNodeToStream.js.map +1 -0
  137. package/dist/src/plugins/operator/checkOperatorValueBreach.d.ts +2 -0
  138. package/dist/src/plugins/operator/checkOperatorValueBreach.js +21 -0
  139. package/dist/src/plugins/operator/checkOperatorValueBreach.js.map +1 -0
  140. package/dist/src/plugins/operator/closeExpiredFlags.d.ts +3 -0
  141. package/dist/src/plugins/operator/closeExpiredFlags.js +24 -0
  142. package/dist/src/plugins/operator/closeExpiredFlags.js.map +1 -0
  143. package/dist/src/plugins/operator/config.schema.json +152 -0
  144. package/dist/src/plugins/operator/createIsLeaderFn.d.ts +4 -0
  145. package/dist/src/plugins/operator/createIsLeaderFn.js +14 -0
  146. package/dist/src/plugins/operator/createIsLeaderFn.js.map +1 -0
  147. package/dist/src/plugins/operator/fetchRedundancyFactor.d.ts +2 -0
  148. package/dist/src/plugins/operator/fetchRedundancyFactor.js +43 -0
  149. package/dist/src/plugins/operator/fetchRedundancyFactor.js.map +1 -0
  150. package/dist/src/plugins/operator/formCoordinationStreamId.d.ts +3 -0
  151. package/dist/src/plugins/operator/formCoordinationStreamId.js +9 -0
  152. package/dist/src/plugins/operator/formCoordinationStreamId.js.map +1 -0
  153. package/dist/src/plugins/operator/heartbeatUtils.d.ts +67 -0
  154. package/dist/src/plugins/operator/heartbeatUtils.js +26 -0
  155. package/dist/src/plugins/operator/heartbeatUtils.js.map +1 -0
  156. package/dist/src/plugins/operator/inspectOverTime.d.ts +22 -0
  157. package/dist/src/plugins/operator/inspectOverTime.js +146 -0
  158. package/dist/src/plugins/operator/inspectOverTime.js.map +1 -0
  159. package/dist/src/plugins/operator/inspectRandomNode.d.ts +8 -0
  160. package/dist/src/plugins/operator/inspectRandomNode.js +44 -0
  161. package/dist/src/plugins/operator/inspectRandomNode.js.map +1 -0
  162. package/dist/src/plugins/operator/inspectionUtils.d.ts +23 -0
  163. package/dist/src/plugins/operator/inspectionUtils.js +120 -0
  164. package/dist/src/plugins/operator/inspectionUtils.js.map +1 -0
  165. package/dist/src/plugins/operator/maintainOperatorValue.d.ts +2 -0
  166. package/dist/src/plugins/operator/maintainOperatorValue.js +21 -0
  167. package/dist/src/plugins/operator/maintainOperatorValue.js.map +1 -0
  168. package/dist/src/plugins/operator/reviewSuspectNode.d.ts +24 -0
  169. package/dist/src/plugins/operator/reviewSuspectNode.js +56 -0
  170. package/dist/src/plugins/operator/reviewSuspectNode.js.map +1 -0
  171. package/dist/src/plugins/storage/Batch.d.ts +51 -0
  172. package/dist/src/plugins/storage/Batch.js +121 -0
  173. package/dist/src/plugins/storage/Batch.js.map +1 -0
  174. package/dist/src/plugins/storage/BatchManager.d.ts +27 -0
  175. package/dist/src/plugins/storage/BatchManager.js +117 -0
  176. package/dist/src/plugins/storage/BatchManager.js.map +1 -0
  177. package/dist/src/plugins/storage/Bucket.d.ts +23 -0
  178. package/dist/src/plugins/storage/Bucket.js +90 -0
  179. package/dist/src/plugins/storage/Bucket.js.map +1 -0
  180. package/dist/src/plugins/storage/BucketManager.d.ts +56 -0
  181. package/dist/src/plugins/storage/BucketManager.js +306 -0
  182. package/dist/src/plugins/storage/BucketManager.js.map +1 -0
  183. package/dist/src/plugins/storage/DataQueryFormat.d.ts +10 -0
  184. package/dist/src/plugins/storage/DataQueryFormat.js +51 -0
  185. package/dist/src/plugins/storage/DataQueryFormat.js.map +1 -0
  186. package/dist/src/plugins/storage/DeleteExpiredCmd.d.ts +28 -0
  187. package/dist/src/plugins/storage/DeleteExpiredCmd.js +155 -0
  188. package/dist/src/plugins/storage/DeleteExpiredCmd.js.map +1 -0
  189. package/dist/src/plugins/storage/SetMembershipSynchronizer.d.ts +33 -0
  190. package/dist/src/plugins/storage/SetMembershipSynchronizer.js +102 -0
  191. package/dist/src/plugins/storage/SetMembershipSynchronizer.js.map +1 -0
  192. package/dist/src/plugins/storage/Storage.d.ts +47 -0
  193. package/dist/src/plugins/storage/Storage.js +459 -0
  194. package/dist/src/plugins/storage/Storage.js.map +1 -0
  195. package/dist/src/plugins/storage/StorageConfig.d.ts +43 -0
  196. package/dist/src/plugins/storage/StorageConfig.js +83 -0
  197. package/dist/src/plugins/storage/StorageConfig.js.map +1 -0
  198. package/dist/src/plugins/storage/StorageEventListener.d.ts +17 -0
  199. package/dist/src/plugins/storage/StorageEventListener.js +46 -0
  200. package/dist/src/plugins/storage/StorageEventListener.js.map +1 -0
  201. package/dist/src/plugins/storage/StoragePlugin.d.ts +32 -0
  202. package/dist/src/plugins/storage/StoragePlugin.js +103 -0
  203. package/dist/src/plugins/storage/StoragePlugin.js.map +1 -0
  204. package/dist/src/plugins/storage/StoragePoller.d.ts +15 -0
  205. package/dist/src/plugins/storage/StoragePoller.js +47 -0
  206. package/dist/src/plugins/storage/StoragePoller.js.map +1 -0
  207. package/dist/src/plugins/storage/config.schema.json +88 -0
  208. package/dist/src/plugins/storage/dataMetadataEndpoint.d.ts +3 -0
  209. package/dist/src/plugins/storage/dataMetadataEndpoint.js +35 -0
  210. package/dist/src/plugins/storage/dataMetadataEndpoint.js.map +1 -0
  211. package/dist/src/plugins/storage/dataQueryEndpoint.d.ts +6 -0
  212. package/dist/src/plugins/storage/dataQueryEndpoint.js +181 -0
  213. package/dist/src/plugins/storage/dataQueryEndpoint.js.map +1 -0
  214. package/dist/src/plugins/storage/storageConfigEndpoint.d.ts +3 -0
  215. package/dist/src/plugins/storage/storageConfigEndpoint.js +31 -0
  216. package/dist/src/plugins/storage/storageConfigEndpoint.js.map +1 -0
  217. package/dist/src/plugins/subscriber/SubscriberPlugin.d.ts +16 -0
  218. package/dist/src/plugins/subscriber/SubscriberPlugin.js +22 -0
  219. package/dist/src/plugins/subscriber/SubscriberPlugin.js.map +1 -0
  220. package/dist/src/plugins/subscriber/config.schema.json +31 -0
  221. package/dist/src/plugins/websocket/Connection.d.ts +9 -0
  222. package/dist/src/plugins/websocket/Connection.js +45 -0
  223. package/dist/src/plugins/websocket/Connection.js.map +1 -0
  224. package/dist/src/plugins/websocket/PublishConnection.d.ts +12 -0
  225. package/dist/src/plugins/websocket/PublishConnection.js +46 -0
  226. package/dist/src/plugins/websocket/PublishConnection.js.map +1 -0
  227. package/dist/src/plugins/websocket/SubscribeConnection.d.ts +13 -0
  228. package/dist/src/plugins/websocket/SubscribeConnection.js +50 -0
  229. package/dist/src/plugins/websocket/SubscribeConnection.js.map +1 -0
  230. package/dist/src/plugins/websocket/WebsocketPlugin.d.ts +19 -0
  231. package/dist/src/plugins/websocket/WebsocketPlugin.js +26 -0
  232. package/dist/src/plugins/websocket/WebsocketPlugin.js.map +1 -0
  233. package/dist/src/plugins/websocket/WebsocketServer.d.ts +16 -0
  234. package/dist/src/plugins/websocket/WebsocketServer.js +132 -0
  235. package/dist/src/plugins/websocket/WebsocketServer.js.map +1 -0
  236. package/dist/src/plugins/websocket/config.schema.json +51 -0
  237. package/package.json +78 -0
  238. package/plugins.md +318 -0
@@ -0,0 +1,459 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.startCassandraStorage = exports.Storage = void 0;
7
+ const cassandra_driver_1 = require("cassandra-driver");
8
+ const utils_1 = require("@streamr/utils");
9
+ const BatchManager_1 = require("./BatchManager");
10
+ const stream_1 = require("stream");
11
+ const events_1 = require("events");
12
+ const stream_2 = require("stream");
13
+ const uuid_1 = require("uuid");
14
+ const merge2_1 = __importDefault(require("merge2"));
15
+ const BucketManager_1 = require("./BucketManager");
16
+ const utils_2 = require("@streamr/utils");
17
+ const dataQueryEndpoint_1 = require("./dataQueryEndpoint");
18
+ const trackerless_network_1 = require("@streamr/trackerless-network");
19
+ const logger = new utils_2.Logger(module);
20
+ const MAX_TIMESTAMP_VALUE = 8640000000000000; // https://262.ecma-international.org/5.1/#sec-15.9.1.1
21
+ const MAX_RESEND_LAST = 10000;
22
+ const bucketsToIds = (buckets) => buckets.map((bucket) => bucket.getId());
23
+ class Storage extends events_1.EventEmitter {
24
+ opts;
25
+ cassandraClient;
26
+ bucketManager;
27
+ batchManager;
28
+ pendingStores;
29
+ constructor(cassandraClient, opts) {
30
+ super();
31
+ const defaultOptions = {
32
+ useTtl: false,
33
+ retriesIntervalMilliseconds: 500
34
+ };
35
+ this.opts = {
36
+ ...defaultOptions,
37
+ ...opts
38
+ };
39
+ this.cassandraClient = cassandraClient;
40
+ this.bucketManager = new BucketManager_1.BucketManager(cassandraClient, opts);
41
+ this.batchManager = new BatchManager_1.BatchManager(cassandraClient, {
42
+ useTtl: this.opts.useTtl
43
+ });
44
+ this.pendingStores = new Map();
45
+ }
46
+ async store(streamMessage) {
47
+ logger.debug('Store message', { msgId: streamMessage.messageId });
48
+ const bucketId = this.bucketManager.getBucketId(streamMessage.getStreamId(), streamMessage.getStreamPartition(), streamMessage.getTimestamp());
49
+ return new Promise((resolve, reject) => {
50
+ if (bucketId) {
51
+ logger.trace('Found bucket', { bucketId });
52
+ const record = {
53
+ streamId: streamMessage.getStreamId(),
54
+ partition: streamMessage.getStreamPartition(),
55
+ timestamp: streamMessage.getTimestamp(),
56
+ sequenceNo: streamMessage.getSequenceNumber(),
57
+ publisherId: streamMessage.getPublisherId(),
58
+ msgChainId: streamMessage.getMsgChainId(),
59
+ payload: Buffer.from((0, trackerless_network_1.convertStreamMessageToBytes)(streamMessage))
60
+ };
61
+ this.bucketManager.incrementBucket(bucketId, record.payload.length);
62
+ setImmediate(() => this.batchManager.store(bucketId, record, (err) => {
63
+ if (err) {
64
+ reject(err);
65
+ }
66
+ else {
67
+ this.emit('write', record.payload);
68
+ resolve(true);
69
+ }
70
+ }));
71
+ }
72
+ else {
73
+ logger.trace('Move message to pending messages (bucket not found)', {
74
+ messageId: JSON.stringify(streamMessage.messageId)
75
+ });
76
+ const uuid = (0, uuid_1.v1)();
77
+ const timeout = setTimeout(() => {
78
+ this.pendingStores.delete(uuid);
79
+ this.store(streamMessage).then(resolve, reject);
80
+ }, this.opts.retriesIntervalMilliseconds);
81
+ this.pendingStores.set(uuid, timeout);
82
+ }
83
+ });
84
+ }
85
+ requestLast(streamId, partition, limit) {
86
+ if (limit > MAX_RESEND_LAST) {
87
+ // eslint-disable-next-line no-param-reassign
88
+ limit = MAX_RESEND_LAST;
89
+ }
90
+ const GET_LAST_N_MESSAGES = 'SELECT payload FROM stream_data WHERE '
91
+ + 'stream_id = ? AND partition = ? AND bucket_id IN ? '
92
+ + 'ORDER BY ts DESC, sequence_no DESC '
93
+ + 'LIMIT ?';
94
+ const COUNT_MESSAGES = 'SELECT COUNT(*) AS total FROM stream_data WHERE stream_id = ? AND partition = ? AND bucket_id = ?';
95
+ const GET_BUCKETS = 'SELECT id FROM bucket WHERE stream_id = ? AND partition = ?';
96
+ let total = 0;
97
+ const options = {
98
+ prepare: true, fetchSize: 1
99
+ };
100
+ const resultStream = this.createResultStream({ streamId, partition, limit });
101
+ const makeLastQuery = async (bucketIds) => {
102
+ try {
103
+ const params = [streamId, partition, bucketIds, limit];
104
+ const resultSet = await this.cassandraClient.execute(GET_LAST_N_MESSAGES, params, {
105
+ prepare: true,
106
+ fetchSize: 0 // disable paging
107
+ });
108
+ resultSet.rows.reverse().forEach((r) => {
109
+ resultStream.write(r);
110
+ });
111
+ resultStream.end();
112
+ }
113
+ catch (err) {
114
+ resultStream.destroy(err);
115
+ }
116
+ };
117
+ let bucketId;
118
+ const bucketIds = [];
119
+ /**
120
+ * Process:
121
+ * - get latest bucketId => count number of messages in this bucket
122
+ * - if enough => get all messages and return
123
+ * - if not => move to the next bucket and repeat cycle
124
+ */
125
+ this.cassandraClient.eachRow(GET_BUCKETS, [streamId, partition], options, (_n, row) => {
126
+ bucketId = row.id;
127
+ bucketIds.push(bucketId);
128
+ }, async (err, result) => {
129
+ // do nothing if resultStream ended
130
+ if (resultStream.writableEnded || resultStream.readableEnded) {
131
+ return;
132
+ }
133
+ if (err) {
134
+ resultStream.destroy(err);
135
+ }
136
+ else {
137
+ // no buckets found at all
138
+ if (!bucketId) {
139
+ resultStream.end();
140
+ return;
141
+ }
142
+ try {
143
+ // get total stored message in bucket
144
+ const resultSet = await this.cassandraClient.execute(COUNT_MESSAGES, [streamId, partition, bucketId], {
145
+ prepare: true,
146
+ fetchSize: 0 // disable paging
147
+ });
148
+ const row = resultSet.first();
149
+ total += row.total.low;
150
+ // if not enough messages and we next page exists, repeat eachRow
151
+ if (result.nextPage && total < limit && total < MAX_RESEND_LAST) {
152
+ result.nextPage();
153
+ }
154
+ else {
155
+ makeLastQuery(bucketIds);
156
+ }
157
+ }
158
+ catch (err) {
159
+ resultStream.destroy(err);
160
+ }
161
+ }
162
+ });
163
+ return resultStream;
164
+ }
165
+ requestFrom(streamId, partition, fromTimestamp, fromSequenceNo, publisherId) {
166
+ return this.fetchRange(streamId, partition, fromTimestamp, fromSequenceNo, MAX_TIMESTAMP_VALUE, dataQueryEndpoint_1.MAX_SEQUENCE_NUMBER_VALUE, publisherId);
167
+ }
168
+ requestRange(streamId, partition, fromTimestamp, fromSequenceNo, toTimestamp, toSequenceNo, publisherId, msgChainId) {
169
+ // TODO is there any reason why we shouldn't allow range queries which contain publisherId, but not msgChainId?
170
+ // (or maybe even queries with msgChain but without publisherId)
171
+ const isValidRequest = (publisherId !== undefined && msgChainId !== undefined) || (publisherId === undefined && msgChainId === undefined);
172
+ if (!isValidRequest) {
173
+ throw new Error('Invalid combination of requestFrom arguments');
174
+ }
175
+ return this.fetchRange(streamId, partition, fromTimestamp, fromSequenceNo, toTimestamp, toSequenceNo, publisherId, msgChainId);
176
+ }
177
+ enableMetrics(metricsContext) {
178
+ const metrics = {
179
+ readMessagesPerSecond: new utils_1.RateMetric(),
180
+ readBytesPerSecond: new utils_1.RateMetric(),
181
+ writeMessagesPerSecond: new utils_1.RateMetric(),
182
+ writeBytesPerSecond: new utils_1.RateMetric()
183
+ };
184
+ metricsContext.addMetrics('broker.plugin.storage', metrics);
185
+ this.on('read', (streamMessage) => {
186
+ metrics.readMessagesPerSecond.record(1);
187
+ metrics.readBytesPerSecond.record(streamMessage.length);
188
+ });
189
+ this.on('write', (streamMessage) => {
190
+ metrics.writeMessagesPerSecond.record(1);
191
+ metrics.writeBytesPerSecond.record(streamMessage.length);
192
+ });
193
+ }
194
+ close() {
195
+ const keys = [...this.pendingStores.keys()];
196
+ keys.forEach((key) => {
197
+ const timeout = this.pendingStores.get(key);
198
+ clearTimeout(timeout);
199
+ this.pendingStores.delete(key);
200
+ });
201
+ this.bucketManager.stop();
202
+ this.batchManager.stop();
203
+ return this.cassandraClient.shutdown();
204
+ }
205
+ fetchRange(streamId, partition, fromTimestamp, fromSequenceNo, toTimestamp, toSequenceNo, publisherId, msgChainId) {
206
+ const resultStream = this.createResultStream({
207
+ streamId,
208
+ partition,
209
+ fromTimestamp,
210
+ fromSequenceNo,
211
+ toTimestamp,
212
+ toSequenceNo,
213
+ publisherId,
214
+ msgChainId,
215
+ });
216
+ this.bucketManager.getBucketsByTimestamp(streamId, partition, fromTimestamp, toTimestamp).then((buckets) => {
217
+ if (buckets.length === 0) {
218
+ resultStream.end();
219
+ return;
220
+ }
221
+ const bucketIds = bucketsToIds(buckets);
222
+ let queries;
223
+ // optimize the typical case where the sequenceNumber doesn't filter out anything
224
+ if ((fromSequenceNo === dataQueryEndpoint_1.MIN_SEQUENCE_NUMBER_VALUE) && (toSequenceNo === dataQueryEndpoint_1.MAX_SEQUENCE_NUMBER_VALUE)) {
225
+ queries = [
226
+ {
227
+ where: 'WHERE stream_id = ? AND partition = ? AND bucket_id IN ? AND ts >= ? AND ts <= ?',
228
+ params: [streamId, partition, bucketIds, fromTimestamp, toTimestamp]
229
+ }
230
+ ];
231
+ }
232
+ else {
233
+ queries = [
234
+ {
235
+ where: 'WHERE stream_id = ? AND partition = ? AND bucket_id IN ? AND ts = ? AND sequence_no >= ?',
236
+ params: [streamId, partition, bucketIds, fromTimestamp, fromSequenceNo]
237
+ },
238
+ {
239
+ where: 'WHERE stream_id = ? AND partition = ? AND bucket_id IN ? AND ts > ? AND ts < ?',
240
+ params: [streamId, partition, bucketIds, fromTimestamp, toTimestamp]
241
+ },
242
+ {
243
+ where: 'WHERE stream_id = ? AND partition = ? AND bucket_id IN ? AND ts = ? AND sequence_no <= ?',
244
+ params: [streamId, partition, bucketIds, toTimestamp, toSequenceNo]
245
+ }
246
+ ];
247
+ }
248
+ queries.forEach((q) => {
249
+ if (publisherId !== undefined) {
250
+ q.where += ' AND publisher_id = ?';
251
+ q.params.push(publisherId);
252
+ }
253
+ if (msgChainId !== undefined) {
254
+ q.where += ' AND msg_chain_id = ?';
255
+ q.params.push(msgChainId);
256
+ }
257
+ });
258
+ const streams = queries.map((q) => {
259
+ const select = `SELECT payload FROM stream_data ${q.where} ALLOW FILTERING`;
260
+ return this.queryWithStreamingResults(select, q.params);
261
+ });
262
+ return (0, stream_2.pipeline)(
263
+ // @ts-expect-error options not in type
264
+ (0, merge2_1.default)(...streams, {
265
+ pipeError: true,
266
+ }), resultStream, (err) => {
267
+ if (err) {
268
+ resultStream.destroy(err);
269
+ streams.forEach((s) => s.destroy(undefined));
270
+ }
271
+ });
272
+ })
273
+ .catch((e) => {
274
+ resultStream.destroy(e);
275
+ });
276
+ return resultStream;
277
+ }
278
+ queryWithStreamingResults(query, queryParams) {
279
+ return this.cassandraClient.stream(query, queryParams, {
280
+ prepare: true,
281
+ // force small page sizes, otherwise gives RangeError [ERR_OUT_OF_RANGE]: The value of "offset" is out of range.
282
+ fetchSize: 128,
283
+ readTimeout: 0,
284
+ });
285
+ }
286
+ parseRow(row, debugInfo) {
287
+ if (row.payload === null) {
288
+ logger.error('Found unexpected message with NULL payload in Cassandra', { debugInfo });
289
+ return null;
290
+ }
291
+ this.emit('read', row.payload);
292
+ return row.payload;
293
+ }
294
+ createResultStream(debugInfo) {
295
+ const self = this; // eslint-disable-line @typescript-eslint/no-this-alias
296
+ let last = Date.now();
297
+ return new stream_1.Transform({
298
+ highWaterMark: 1024, // buffer up to 1024 messages
299
+ objectMode: true,
300
+ transform(row, _, done) {
301
+ const now = Date.now();
302
+ const message = self.parseRow(row, debugInfo);
303
+ if (message !== null) {
304
+ this.push(message);
305
+ }
306
+ // To avoid blocking main thread for too long, after every 100ms
307
+ // pause & resume the cassandraStream to give other events in the event
308
+ // queue a chance to be handled.
309
+ if ((now - last) > 100) {
310
+ setImmediate(() => {
311
+ last = Date.now();
312
+ done();
313
+ });
314
+ }
315
+ else {
316
+ done();
317
+ }
318
+ }
319
+ });
320
+ }
321
+ async getFirstMessageTimestampInStream(streamId, partition) {
322
+ const bucketQuery = 'SELECT id FROM bucket WHERE stream_id=? AND partition =? ORDER BY date_create ASC LIMIT 1';
323
+ const queryParams = [streamId, partition];
324
+ const buckets = await this.cassandraClient.execute(bucketQuery, queryParams, {
325
+ prepare: true,
326
+ });
327
+ if (buckets.rows.length !== 1) {
328
+ return 0;
329
+ }
330
+ const bucketId = buckets.rows[0].id;
331
+ const query = 'SELECT ts FROM stream_data WHERE stream_id=? AND partition=? AND bucket_id=? ORDER BY ts ASC LIMIT 1';
332
+ const streams = await this.cassandraClient.execute(query, [
333
+ streamId,
334
+ partition,
335
+ bucketId
336
+ ], {
337
+ prepare: true
338
+ });
339
+ if (streams.rows.length !== 1) {
340
+ return 0;
341
+ }
342
+ const { ts } = streams.rows[0];
343
+ return new Date(ts).getTime();
344
+ }
345
+ async getLastMessageTimestampInStream(streamId, partition) {
346
+ const bucketQuery = 'SELECT id FROM bucket WHERE stream_id=? AND partition =? ORDER BY date_create DESC LIMIT 1';
347
+ const queryParams = [streamId, partition];
348
+ const buckets = await this.cassandraClient.execute(bucketQuery, queryParams, {
349
+ prepare: true,
350
+ });
351
+ if (buckets.rows.length !== 1) {
352
+ return 0;
353
+ }
354
+ const bucketId = buckets.rows[0].id;
355
+ const query = 'SELECT ts FROM stream_data WHERE stream_id=? AND partition=? AND bucket_id=? ORDER BY ts DESC LIMIT 1';
356
+ const streams = await this.cassandraClient.execute(query, [
357
+ streamId,
358
+ partition,
359
+ bucketId
360
+ ], {
361
+ prepare: true
362
+ });
363
+ if (streams.rows.length !== 1) {
364
+ return 0;
365
+ }
366
+ const { ts } = streams.rows[0];
367
+ return new Date(ts).getTime();
368
+ }
369
+ async getNumberOfMessagesInStream(streamId, partition) {
370
+ const query = 'SELECT SUM(records) as count FROM bucket WHERE stream_id=? AND partition=?';
371
+ const queryParams = [
372
+ streamId,
373
+ partition
374
+ ];
375
+ const res = await this.cassandraClient.execute(query, queryParams, {
376
+ prepare: true
377
+ });
378
+ if (res.rows.length !== 1) {
379
+ return 0;
380
+ }
381
+ const { count } = res.rows[0];
382
+ return count;
383
+ }
384
+ async getTotalBytesInStream(streamId, partition) {
385
+ const query = 'SELECT SUM(size) as count FROM bucket WHERE stream_id=? AND partition=?';
386
+ const queryParams = [
387
+ streamId,
388
+ partition
389
+ ];
390
+ const res = await this.cassandraClient.execute(query, queryParams, {
391
+ prepare: true
392
+ });
393
+ if (res.rows.length !== 1) {
394
+ return 0;
395
+ }
396
+ let { count } = res.rows[0];
397
+ // Cassandra's integer has overflown, calculate fetching row by row
398
+ if (count < 0) {
399
+ count = 0;
400
+ const query = 'SELECT size FROM bucket WHERE stream_id=? AND partition=?';
401
+ const queryParams = [
402
+ streamId,
403
+ partition
404
+ ];
405
+ const res = await this.cassandraClient.execute(query, queryParams, {
406
+ prepare: true
407
+ });
408
+ for (const row of res.rows) {
409
+ count += row.size;
410
+ }
411
+ }
412
+ return count;
413
+ }
414
+ }
415
+ exports.Storage = Storage;
416
+ function sleep(ms) {
417
+ return new Promise((resolve) => setTimeout(() => resolve(undefined), ms));
418
+ }
419
+ const startCassandraStorage = async ({ contactPoints, localDataCenter, keyspace, username, password, opts }) => {
420
+ const authProvider = new cassandra_driver_1.auth.PlainTextAuthProvider(username || '', password || '');
421
+ const requestLogger = new cassandra_driver_1.tracker.RequestLogger({
422
+ slowThreshold: 10 * 1000, // 10 secs
423
+ });
424
+ // @ts-expect-error 'emitter' field is missing in type definition file
425
+ requestLogger.emitter.on('slow', (message) => {
426
+ logger.warn('Encountered "slow" event from cassandraClient', { message });
427
+ });
428
+ const cassandraClient = new cassandra_driver_1.Client({
429
+ contactPoints,
430
+ localDataCenter,
431
+ keyspace,
432
+ authProvider,
433
+ requestTracker: requestLogger,
434
+ pooling: {
435
+ maxRequestsPerConnection: 32768
436
+ }
437
+ });
438
+ const nbTrials = 20;
439
+ let retryCount = nbTrials;
440
+ let lastError = '';
441
+ while (retryCount > 0) {
442
+ /* eslint-disable no-await-in-loop */
443
+ try {
444
+ await cassandraClient.connect().catch((err) => { throw err; });
445
+ return new Storage(cassandraClient, opts || {});
446
+ }
447
+ catch (err) {
448
+ // eslint-disable-next-line no-console
449
+ console.log('Cassandra not responding yet...');
450
+ retryCount -= 1;
451
+ await sleep(5000);
452
+ lastError = err;
453
+ }
454
+ /* eslint-enable no-await-in-loop */
455
+ }
456
+ throw new Error(`Failed to connect to Cassandra after ${nbTrials} trials: ${lastError.toString()}`);
457
+ };
458
+ exports.startCassandraStorage = startCassandraStorage;
459
+ //# sourceMappingURL=Storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Storage.js","sourceRoot":"","sources":["../../../../src/plugins/storage/Storage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ import { EthereumAddress } from '@streamr/utils';
2
+ import { StreamPartID } from '@streamr/protocol';
3
+ import { StreamrClient } from '@streamr/sdk';
4
+ export interface StorageConfigListener {
5
+ onStreamPartAdded: (streamPart: StreamPartID) => void;
6
+ onStreamPartRemoved: (streamPart: StreamPartID) => void;
7
+ }
8
+ /**
9
+ * Manages the two data sources for storage node assignments (poll-based and
10
+ * event-based), feeding the received full state and partial state updates to
11
+ * `StorageAssignmentSynchronizer`. The state diffs produced by the
12
+ * synchronizer are then further delivered to the user of this class via
13
+ * listeners.
14
+ *
15
+ * The two data sources, heterogeneous in nature, are:
16
+ *
17
+ * (1) Poll-based storage node assignments occurring on a scheduled interval
18
+ * (reliable, large payload, infrequent, may be stale)
19
+ *
20
+ * (2) Event-based storage node assignments picked up in real-time
21
+ * (intermittent, small payload, frequent, up-to-date)
22
+ *
23
+ * Event-based assignments are great for picking up on changes quickly.
24
+ * However, there is a risk of not receiving updates due to, e.g. connectivity
25
+ * issues. Therefore, if the real-time system fails, polling acts as a sort-of
26
+ * backup system.
27
+ */
28
+ export declare class StorageConfig {
29
+ private readonly listener;
30
+ private readonly synchronizer;
31
+ private readonly clusterSize;
32
+ private readonly myIndexInCluster;
33
+ private readonly storagePoller;
34
+ private readonly storageEventListener;
35
+ private readonly abortController;
36
+ constructor(clusterId: EthereumAddress, clusterSize: number, myIndexInCluster: number, pollInterval: number, streamrClient: StreamrClient, listener: StorageConfigListener);
37
+ start(): Promise<void>;
38
+ destroy(): void;
39
+ hasStreamPart(streamPart: StreamPartID): boolean;
40
+ getStreamParts(): ReadonlySet<StreamPartID>;
41
+ private createMyStreamParts;
42
+ private handleDiff;
43
+ }
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.StorageConfig = void 0;
4
+ const utils_1 = require("@streamr/utils");
5
+ const SetMembershipSynchronizer_1 = require("./SetMembershipSynchronizer");
6
+ const StoragePoller_1 = require("./StoragePoller");
7
+ const StorageEventListener_1 = require("./StorageEventListener");
8
+ const logger = new utils_1.Logger(module);
9
+ /**
10
+ * Manages the two data sources for storage node assignments (poll-based and
11
+ * event-based), feeding the received full state and partial state updates to
12
+ * `StorageAssignmentSynchronizer`. The state diffs produced by the
13
+ * synchronizer are then further delivered to the user of this class via
14
+ * listeners.
15
+ *
16
+ * The two data sources, heterogeneous in nature, are:
17
+ *
18
+ * (1) Poll-based storage node assignments occurring on a scheduled interval
19
+ * (reliable, large payload, infrequent, may be stale)
20
+ *
21
+ * (2) Event-based storage node assignments picked up in real-time
22
+ * (intermittent, small payload, frequent, up-to-date)
23
+ *
24
+ * Event-based assignments are great for picking up on changes quickly.
25
+ * However, there is a risk of not receiving updates due to, e.g. connectivity
26
+ * issues. Therefore, if the real-time system fails, polling acts as a sort-of
27
+ * backup system.
28
+ */
29
+ class StorageConfig {
30
+ listener;
31
+ synchronizer = new SetMembershipSynchronizer_1.SetMembershipSynchronizer();
32
+ clusterSize;
33
+ myIndexInCluster;
34
+ storagePoller;
35
+ storageEventListener;
36
+ abortController;
37
+ constructor(clusterId, clusterSize, myIndexInCluster, pollInterval, streamrClient, listener) {
38
+ this.clusterSize = clusterSize;
39
+ this.myIndexInCluster = myIndexInCluster;
40
+ this.listener = listener;
41
+ this.storagePoller = new StoragePoller_1.StoragePoller(clusterId, pollInterval, streamrClient, (streams, block) => {
42
+ const streamParts = streams.flatMap((stream) => ([
43
+ ...this.createMyStreamParts(stream)
44
+ ]));
45
+ this.handleDiff(this.synchronizer.ingestSnapshot(new Set(streamParts), block));
46
+ });
47
+ this.storageEventListener = new StorageEventListener_1.StorageEventListener(clusterId, streamrClient, (stream, type, block) => {
48
+ const streamParts = this.createMyStreamParts(stream);
49
+ this.handleDiff(this.synchronizer.ingestPatch(streamParts, type, block));
50
+ });
51
+ this.abortController = new AbortController();
52
+ }
53
+ async start() {
54
+ this.storageEventListener.start();
55
+ await this.storagePoller.start(this.abortController.signal);
56
+ }
57
+ destroy() {
58
+ this.abortController.abort();
59
+ this.storageEventListener.destroy();
60
+ }
61
+ hasStreamPart(streamPart) {
62
+ return this.getStreamParts().has(streamPart);
63
+ }
64
+ getStreamParts() {
65
+ return this.synchronizer.getState();
66
+ }
67
+ createMyStreamParts(stream) {
68
+ return new Set(stream.getStreamParts().filter((streamPart) => {
69
+ const hashedIndex = (0, utils_1.keyToArrayIndex)(this.clusterSize, streamPart);
70
+ return hashedIndex === this.myIndexInCluster;
71
+ }));
72
+ }
73
+ handleDiff({ added, removed }) {
74
+ added.forEach((streamPart) => this.listener.onStreamPartAdded(streamPart));
75
+ removed.forEach((streamPart) => this.listener.onStreamPartRemoved(streamPart));
76
+ logger.info('Updated state', {
77
+ added,
78
+ removed
79
+ });
80
+ }
81
+ }
82
+ exports.StorageConfig = StorageConfig;
83
+ //# sourceMappingURL=StorageConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StorageConfig.js","sourceRoot":"","sources":["../../../../src/plugins/storage/StorageConfig.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { Stream, StreamrClient } from '@streamr/sdk';
2
+ import { EthereumAddress } from '@streamr/utils';
3
+ /**
4
+ * Hooks up to StreamrClient event listener to learn about
5
+ * stream assignment and removal events in real-time.
6
+ */
7
+ export declare class StorageEventListener {
8
+ private readonly clusterId;
9
+ private readonly streamrClient;
10
+ private readonly onEvent;
11
+ private readonly onAddToStorageNode;
12
+ private readonly onRemoveFromStorageNode;
13
+ constructor(clusterId: EthereumAddress, streamrClient: StreamrClient, onEvent: (stream: Stream, type: 'added' | 'removed', block: number) => void);
14
+ private handleEvent;
15
+ start(): void;
16
+ destroy(): void;
17
+ }