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 +54 -2
- package/KinesisStream.test.js +70 -2
- package/package.json +1 -1
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:
|
|
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|
|
|
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
|
package/KinesisStream.test.js
CHANGED
|
@@ -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(
|
|
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) {
|