presidium 0.15.27 → 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/DynamoStream.js +3 -2
- package/KinesisStream.js +57 -17
- package/KinesisStream.test.js +87 -2
- package/TranscribeStream.js +4 -0
- package/TranscribeStream.test.js +1 -1
- package/package.json +1 -1
package/DynamoStream.js
CHANGED
|
@@ -144,20 +144,20 @@ DynamoStream.prototype.getRecords = async function* getRecords(
|
|
|
144
144
|
*/
|
|
145
145
|
|
|
146
146
|
}).promise().then(get('ShardIterator'))
|
|
147
|
+
|
|
147
148
|
let records = await this.client.getRecords({
|
|
148
149
|
ShardIterator: startingShardIterator,
|
|
149
150
|
Limit: this.getRecordsLimit
|
|
150
151
|
}).promise()
|
|
151
|
-
|
|
152
152
|
if (records.Records.length > 0) {
|
|
153
153
|
yield* records.Records.map(assign({
|
|
154
154
|
table: always(this.table),
|
|
155
155
|
shardId: always(Shard.ShardId),
|
|
156
156
|
}))
|
|
157
157
|
}
|
|
158
|
+
await new Promise(resolve => setTimeout(resolve, this.getRecordsInterval))
|
|
158
159
|
|
|
159
160
|
while (!this.closed && records.NextShardIterator != null) {
|
|
160
|
-
await new Promise(resolve => setTimeout(resolve, this.getRecordsInterval))
|
|
161
161
|
records = await this.client.getRecords({
|
|
162
162
|
ShardIterator: records.NextShardIterator,
|
|
163
163
|
Limit: this.getRecordsLimit
|
|
@@ -168,6 +168,7 @@ DynamoStream.prototype.getRecords = async function* getRecords(
|
|
|
168
168
|
shardId: always(Shard.ShardId),
|
|
169
169
|
}))
|
|
170
170
|
}
|
|
171
|
+
await new Promise(resolve => setTimeout(resolve, this.getRecordsInterval))
|
|
171
172
|
}
|
|
172
173
|
}
|
|
173
174
|
|
package/KinesisStream.js
CHANGED
|
@@ -29,11 +29,6 @@ const {
|
|
|
29
29
|
* endpoint: string,
|
|
30
30
|
* shardIteratorType: 'AT_SEQUENCE_NUMBER'|'AFTER_SEQUENCE_NUMBER'|'TRIM_HORIZON'|'LATEST'|'AT_TIMESTAMP',
|
|
31
31
|
* timestamp: Date|string|number, // find events at date (requires shardIteratorType 'AT_TIMESTAMP')
|
|
32
|
-
* startingSequenceNumber: string, // find events at data record (requires shardIteratorType 'AT_SEQUENCE_NUMBER' or 'AFTER_SEQUENCE_NUMBER')
|
|
33
|
-
* shardFilterType: 'AFTER_SHARD_ID'|'AT_TRIM_HORIZON'|'FROM_TRIM_HORIZON'|'AT_LATEST'|'AT_TIMESTAMP'|'FROM_TIMESTAMP',
|
|
34
|
-
* shardFilterShardId: string,
|
|
35
|
-
* shardFilterTimestamp: Date|string|number,
|
|
36
|
-
* streamCreationTimestamp: Date|string|number, // distinguishes streams of same name e.g. after deleting
|
|
37
32
|
* }) -> KinesisStream
|
|
38
33
|
* ```
|
|
39
34
|
*
|
|
@@ -53,13 +48,8 @@ const KinesisStream = function (options) {
|
|
|
53
48
|
this.shardUpdatePeriod = options.shardUpdatePeriod ?? 15000
|
|
54
49
|
this.getRecordsInterval = options.getRecordsInterval ?? 1000
|
|
55
50
|
this.shardIteratorType = options.shardIteratorType ?? 'LATEST'
|
|
56
|
-
this.
|
|
57
|
-
this.shardFilterType = options.shardFilterType
|
|
58
|
-
this.shardFilterShardId = options.shardFilterShardId
|
|
59
|
-
this.shardFilterTimestamp = options.shardFilterTimestamp
|
|
60
|
-
this.streamCreationTimestamp = options.streamCreationTimestamp
|
|
51
|
+
this.shardCount = options.shardCount ?? 1
|
|
61
52
|
this.timestamp = options.timestamp
|
|
62
|
-
this.startingSequenceNumber = options.startingSequenceNumber
|
|
63
53
|
this.kinesis = new Kinesis(omit(['name'])(options))
|
|
64
54
|
this.cancelToken = new Promise((_, reject) => (this.canceller = reject))
|
|
65
55
|
|
|
@@ -76,7 +66,7 @@ const KinesisStream = function (options) {
|
|
|
76
66
|
}).catch(async () => {
|
|
77
67
|
await this.kinesis.client.createStream({
|
|
78
68
|
StreamName: this.name,
|
|
79
|
-
ShardCount:
|
|
69
|
+
ShardCount: this.shardCount,
|
|
80
70
|
}).promise()
|
|
81
71
|
await this.kinesis.client.waitFor('streamExists', {
|
|
82
72
|
StreamName: this.name
|
|
@@ -103,7 +93,7 @@ KinesisStream.prototype.delete = function deleteStream() {
|
|
|
103
93
|
* @synopsis
|
|
104
94
|
* ```coffeescript [specscript]
|
|
105
95
|
* KinesisStream(options).putRecord(
|
|
106
|
-
* data string|
|
|
96
|
+
* data string|Buffer,
|
|
107
97
|
* options {
|
|
108
98
|
* partitionKey: string, // input to aws hash function to determine which shard
|
|
109
99
|
* explicitHashKey: string, // skips aws hash function to determine which shard
|
|
@@ -129,6 +119,57 @@ KinesisStream.prototype.putRecord = async function putRecord(data, options = {})
|
|
|
129
119
|
}).promise()
|
|
130
120
|
}
|
|
131
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
|
+
|
|
132
173
|
// () => ()
|
|
133
174
|
KinesisStream.prototype.close = function close() {
|
|
134
175
|
this.closed = true
|
|
@@ -163,9 +204,7 @@ KinesisStream.prototype.getRecords = async function* getRecords(Shard) {
|
|
|
163
204
|
ShardId: Shard.ShardId,
|
|
164
205
|
StreamName: this.name,
|
|
165
206
|
ShardIteratorType: this.shardIteratorType,
|
|
166
|
-
...this.
|
|
167
|
-
Timestamp: this.shardIteratorTimestamp,
|
|
168
|
-
},
|
|
207
|
+
...this.timestamp == null ? {} : { Timestamp: this.timestamp },
|
|
169
208
|
}).promise().then(get('ShardIterator'))
|
|
170
209
|
|
|
171
210
|
let records = await this.kinesis.client.getRecords({
|
|
@@ -175,9 +214,9 @@ KinesisStream.prototype.getRecords = async function* getRecords(Shard) {
|
|
|
175
214
|
if (records.Records.length > 0) {
|
|
176
215
|
yield* records.Records
|
|
177
216
|
}
|
|
217
|
+
await new Promise(resolve => setTimeout(resolve, this.getRecordsInterval))
|
|
178
218
|
|
|
179
219
|
while (!this.closed && records.NextShardIterator != null) {
|
|
180
|
-
await new Promise(resolve => setTimeout(resolve, this.getRecordsInterval))
|
|
181
220
|
records = await this.kinesis.client.getRecords({
|
|
182
221
|
ShardIterator: records.NextShardIterator,
|
|
183
222
|
Limit: this.getRecordsLimit,
|
|
@@ -185,6 +224,7 @@ KinesisStream.prototype.getRecords = async function* getRecords(Shard) {
|
|
|
185
224
|
if (records.Records.length > 0) {
|
|
186
225
|
yield* records.Records
|
|
187
226
|
}
|
|
227
|
+
await new Promise(resolve => setTimeout(resolve, this.getRecordsInterval))
|
|
188
228
|
}
|
|
189
229
|
}
|
|
190
230
|
|
package/KinesisStream.test.js
CHANGED
|
@@ -7,9 +7,11 @@ const map = require('rubico/map')
|
|
|
7
7
|
const thunkify = require('rubico/thunkify')
|
|
8
8
|
|
|
9
9
|
const test = new Test('KinesisStream', KinesisStream)
|
|
10
|
+
|
|
10
11
|
.before(function () {
|
|
11
12
|
this.streams = []
|
|
12
13
|
})
|
|
14
|
+
|
|
13
15
|
.case({
|
|
14
16
|
name: 'my-stream',
|
|
15
17
|
endpoint: 'http://localhost:4567',
|
|
@@ -21,7 +23,87 @@ const test = new Test('KinesisStream', KinesisStream)
|
|
|
21
23
|
await myStream.putRecord('hey')
|
|
22
24
|
await myStream.putRecord('ho', { partitionKey: 'ho' })
|
|
23
25
|
await myStream.putRecord('hi', { explicitHashKey: '127' })
|
|
26
|
+
const first3 = await asyncIterableTake(3)(myStream)
|
|
27
|
+
const first3Again = await asyncIterableTake(3)(myStream)
|
|
28
|
+
assert.deepEqual(first3, first3Again)
|
|
29
|
+
this.streams.push(myStream)
|
|
30
|
+
})
|
|
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
|
+
})
|
|
24
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
|
+
|
|
97
|
+
.case({
|
|
98
|
+
name: 'my-stream',
|
|
99
|
+
endpoint: 'http://localhost:4567',
|
|
100
|
+
shardIteratorType: 'AT_TIMESTAMP',
|
|
101
|
+
timestamp: new Date(Date.now() - 5000),
|
|
102
|
+
}, async function (myStream) {
|
|
103
|
+
await myStream.ready
|
|
104
|
+
await myStream.putRecord('hey')
|
|
105
|
+
await myStream.putRecord('ho', { partitionKey: 'ho' })
|
|
106
|
+
await myStream.putRecord('hi', { explicitHashKey: '127' })
|
|
25
107
|
const first3 = await asyncIterableTake(3)(myStream)
|
|
26
108
|
const first3Again = await asyncIterableTake(3)(myStream)
|
|
27
109
|
assert.deepEqual(first3, first3Again)
|
|
@@ -69,8 +151,11 @@ const test = new Test('KinesisStream', KinesisStream)
|
|
|
69
151
|
await new Promise(resolve => setTimeout(resolve, 1000))
|
|
70
152
|
})
|
|
71
153
|
|
|
72
|
-
.after(async function() {
|
|
73
|
-
await map(
|
|
154
|
+
.after(async function () {
|
|
155
|
+
await map(async function cleanup(stream) {
|
|
156
|
+
stream.close()
|
|
157
|
+
await stream.delete()
|
|
158
|
+
})(this.streams)
|
|
74
159
|
})
|
|
75
160
|
|
|
76
161
|
if (process.argv[1] == __filename) {
|
package/TranscribeStream.js
CHANGED
package/TranscribeStream.test.js
CHANGED
|
@@ -53,7 +53,7 @@ const test = new Test('TranscribeStream', async function () {
|
|
|
53
53
|
wav.fromMuLaw()
|
|
54
54
|
testTranscribeStream.sendAudioChunk(Buffer.from(wav.data.samples))
|
|
55
55
|
} else if (event.event == 'stop') {
|
|
56
|
-
testTranscribeStream.
|
|
56
|
+
testTranscribeStream.close()
|
|
57
57
|
}
|
|
58
58
|
})
|
|
59
59
|
|