presidium 0.15.30 → 0.15.31

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/KinesisStream.js CHANGED
@@ -48,6 +48,7 @@ const KinesisStream = function (options) {
48
48
  this.shardUpdatePeriod = options.shardUpdatePeriod ?? 15000
49
49
  this.getRecordsInterval = options.getRecordsInterval ?? 1000
50
50
  this.shardIteratorType = options.shardIteratorType ?? 'LATEST'
51
+ this.shardCount = options.shardCount ?? 1
51
52
  this.timestamp = options.timestamp
52
53
  this.kinesis = new Kinesis(omit(['name'])(options))
53
54
  this.cancelToken = new Promise((_, reject) => (this.canceller = reject))
@@ -65,7 +66,7 @@ const KinesisStream = function (options) {
65
66
  }).catch(async () => {
66
67
  await this.kinesis.client.createStream({
67
68
  StreamName: this.name,
68
- ShardCount: 1,
69
+ ShardCount: this.shardCount,
69
70
  }).promise()
70
71
  await this.kinesis.client.waitFor('streamExists', {
71
72
  StreamName: this.name
@@ -92,7 +93,7 @@ KinesisStream.prototype.delete = function deleteStream() {
92
93
  * @synopsis
93
94
  * ```coffeescript [specscript]
94
95
  * KinesisStream(options).putRecord(
95
- * data string|binary,
96
+ * data string|Buffer,
96
97
  * options {
97
98
  * partitionKey: string, // input to aws hash function to determine which shard
98
99
  * explicitHashKey: string, // skips aws hash function to determine which shard
@@ -118,6 +119,57 @@ KinesisStream.prototype.putRecord = async function putRecord(data, options = {})
118
119
  }).promise()
119
120
  }
120
121
 
122
+ /**
123
+ * @name KinesisStream.prototype.putRecords
124
+ *
125
+ * @synopsis
126
+ * ```coffeescript [specscript]
127
+ * KinesisStream(options).putRecords(records Array<{
128
+ * data: string|Buffer,
129
+ * partitionKey: string, // input to aws hash function to determine which shard
130
+ * explicitHashKey: string, // skips aws hash function to determine which shard
131
+ * }>) -> Promise<{
132
+ * FailedRecordCount: number, // number of unsuccessfully processed records
133
+ * Records: Array<{
134
+ * SequenceNumber: string,
135
+ * ShardId: string,
136
+ * ErrorCode?: 'ProvisionedThroughputExceededException'|'InternalFailure',
137
+ * ErrorMessage?: string,
138
+ * }>,
139
+ * EncryptionType: 'NONE'|'KMS',
140
+ * }>
141
+ * ```
142
+ *
143
+ * @description
144
+ * Limits/Quotas:
145
+ * * 500 records max per request
146
+ * * 1 MB per record max
147
+ * * 5 MB per request max
148
+ * * 1000 records per second per shard
149
+ * * 1 MB per second per shard
150
+ *
151
+ * https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Kinesis.html#putRecords-property
152
+ */
153
+ KinesisStream.prototype.putRecords = async function putRecords(records) {
154
+ return this.kinesis.client.putRecords({
155
+ StreamName: this.name,
156
+ Records: records.map(({ data, partitionKey, explicitHashKey }) => ({
157
+ Data: data,
158
+ PartitionKey: partitionKey ?? data.slice(0, 255),
159
+ ...explicitHashKey && { ExplicitHashKey: explicitHashKey },
160
+ }))
161
+ }).promise().then(tap(response => {
162
+ if (response.Records.some(has('ErrorCode'))) {
163
+ const errors = response.Records.filter(has('ErrorCode')).map(Record => {
164
+ const error = new Error(Record.ErrorMessage)
165
+ error.code = Record.ErrorCode
166
+ return error
167
+ })
168
+ throw new AggregateError(errors, 'Some records failed to process')
169
+ }
170
+ }))
171
+ }
172
+
121
173
  // () => ()
122
174
  KinesisStream.prototype.close = function close() {
123
175
  this.closed = true
@@ -29,6 +29,71 @@ const test = new Test('KinesisStream', KinesisStream)
29
29
  this.streams.push(myStream)
30
30
  })
31
31
 
32
+ .case({
33
+ name: 'my-stream',
34
+ endpoint: 'http://localhost:4567',
35
+ shardIteratorType: 'TRIM_HORIZON',
36
+ getRecordsLimit: 1,
37
+ listShardsLimit: 1,
38
+ shardCount: 2,
39
+ }, async function (myStream) {
40
+ await myStream.ready
41
+ await myStream.putRecord('hey', { partitionKey: 'a' })
42
+ await myStream.putRecord('ho', { partitionKey: 'a' })
43
+ await myStream.putRecord('hi', { partitionKey: 'a' })
44
+ const first3 = await asyncIterableTake(3)(myStream)
45
+ const first3Again = await asyncIterableTake(3)(myStream)
46
+ assert.deepEqual(first3, first3Again)
47
+ this.streams.push(myStream)
48
+ })
49
+
50
+ .case({
51
+ name: 'my-stream',
52
+ endpoint: 'http://localhost:4567',
53
+ shardIteratorType: 'TRIM_HORIZON',
54
+ }, async function (myStream) {
55
+ await myStream.ready
56
+ await myStream.putRecords([
57
+ { data: 'hey' },
58
+ { data: 'ho', partitionKey: 'ho' },
59
+ { data: 'hi', explicitHashKey: '127' },
60
+ ])
61
+ const first3 = await asyncIterableTake(3)(myStream)
62
+ const first3Again = await asyncIterableTake(3)(myStream)
63
+ assert.deepEqual(first3, first3Again)
64
+ this.streams.push(myStream)
65
+ })
66
+
67
+ .case({
68
+ name: 'my-stream',
69
+ endpoint: 'http://localhost:4567',
70
+ shardIteratorType: 'TRIM_HORIZON',
71
+ }, async function (myStream) {
72
+ myStream.kinesis.client.putRecords = () => ({
73
+ promise: async () => ({
74
+ Records: [
75
+ {
76
+ ErrorCode: 'ProvisionedThroughputExceededException',
77
+ ErrorMessage: 'Some message with accountId, stream name, and shard ID',
78
+ },
79
+ {
80
+ ErrorCode: 'ProvisionedThroughputExceededException',
81
+ ErrorMessage: 'Some message with accountId, stream name, and shard ID',
82
+ },
83
+ ],
84
+ }),
85
+ })
86
+ await myStream.ready
87
+ await assert.rejects(
88
+ () => myStream.putRecords([{ data: 'hey' }]),
89
+ new AggregateError([
90
+ new Error('Some message with accountId, stream name, and shard ID'),
91
+ new Error('Some message with accountId, stream name, and shard ID'),
92
+ ], 'Some records failed to process')
93
+ )
94
+ this.streams.push(myStream)
95
+ })
96
+
32
97
  .case({
33
98
  name: 'my-stream',
34
99
  endpoint: 'http://localhost:4567',
@@ -86,8 +151,11 @@ const test = new Test('KinesisStream', KinesisStream)
86
151
  await new Promise(resolve => setTimeout(resolve, 1000))
87
152
  })
88
153
 
89
- .after(async function() {
90
- await map(stream => stream.delete())(this.streams)
154
+ .after(async function () {
155
+ await map(async function cleanup(stream) {
156
+ stream.close()
157
+ await stream.delete()
158
+ })(this.streams)
91
159
  })
92
160
 
93
161
  if (process.argv[1] == __filename) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "presidium",
3
- "version": "0.15.30",
3
+ "version": "0.15.31",
4
4
  "description": "A library for creating web services",
5
5
  "author": "Richard Tong",
6
6
  "license": "MIT",