@soulcraft/brainy 0.54.0 → 0.54.2
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/dist/storage/adapters/s3CompatibleStorage.d.ts +43 -0
- package/dist/storage/adapters/s3CompatibleStorage.js +263 -0
- package/dist/storage/adapters/s3CompatibleStorage.js.map +1 -1
- package/dist/utils/requestCoalescer.d.ts +91 -0
- package/dist/utils/requestCoalescer.js +324 -0
- package/dist/utils/requestCoalescer.js.map +1 -0
- package/dist/utils/writeBuffer.d.ts +93 -0
- package/dist/utils/writeBuffer.js +328 -0
- package/dist/utils/writeBuffer.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Request Coalescer
|
|
3
|
+
* Batches and deduplicates operations to reduce S3 API calls
|
|
4
|
+
* Automatically flushes based on size, time, or pressure
|
|
5
|
+
*/
|
|
6
|
+
import { createModuleLogger } from './logger.js';
|
|
7
|
+
/**
|
|
8
|
+
* Coalesces multiple operations into efficient batches
|
|
9
|
+
*/
|
|
10
|
+
export class RequestCoalescer {
|
|
11
|
+
constructor(processor, options) {
|
|
12
|
+
this.logger = createModuleLogger('RequestCoalescer');
|
|
13
|
+
// Operation queues by type
|
|
14
|
+
this.writeQueue = new Map();
|
|
15
|
+
this.readQueue = new Map();
|
|
16
|
+
this.deleteQueue = new Map();
|
|
17
|
+
// Batch configuration
|
|
18
|
+
this.maxBatchSize = 100;
|
|
19
|
+
this.maxBatchAge = 100; // ms - flush quickly under load
|
|
20
|
+
this.minBatchSize = 10; // Don't flush until we have enough
|
|
21
|
+
// Flush timers
|
|
22
|
+
this.flushTimer = null;
|
|
23
|
+
this.lastFlush = Date.now();
|
|
24
|
+
// Statistics
|
|
25
|
+
this.stats = {
|
|
26
|
+
totalOperations: 0,
|
|
27
|
+
coalescedOperations: 0,
|
|
28
|
+
deduplicated: 0,
|
|
29
|
+
batchesProcessed: 0,
|
|
30
|
+
averageBatchSize: 0
|
|
31
|
+
};
|
|
32
|
+
this.processor = processor;
|
|
33
|
+
if (options) {
|
|
34
|
+
this.maxBatchSize = options.maxBatchSize || this.maxBatchSize;
|
|
35
|
+
this.maxBatchAge = options.maxBatchAge || this.maxBatchAge;
|
|
36
|
+
this.minBatchSize = options.minBatchSize || this.minBatchSize;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Add a write operation to be coalesced
|
|
41
|
+
*/
|
|
42
|
+
async write(key, data) {
|
|
43
|
+
return new Promise((resolve, reject) => {
|
|
44
|
+
// Check if we already have a pending write for this key
|
|
45
|
+
const existing = this.writeQueue.get(key);
|
|
46
|
+
if (existing && existing.length > 0) {
|
|
47
|
+
// Replace the data but resolve all promises
|
|
48
|
+
const last = existing[existing.length - 1];
|
|
49
|
+
last.data = data; // Use latest data
|
|
50
|
+
// Add this promise to be resolved
|
|
51
|
+
existing.push({
|
|
52
|
+
type: 'write',
|
|
53
|
+
key,
|
|
54
|
+
data,
|
|
55
|
+
resolve,
|
|
56
|
+
reject,
|
|
57
|
+
timestamp: Date.now()
|
|
58
|
+
});
|
|
59
|
+
this.stats.deduplicated++;
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
// New write operation
|
|
63
|
+
this.writeQueue.set(key, [{
|
|
64
|
+
type: 'write',
|
|
65
|
+
key,
|
|
66
|
+
data,
|
|
67
|
+
resolve,
|
|
68
|
+
reject,
|
|
69
|
+
timestamp: Date.now()
|
|
70
|
+
}]);
|
|
71
|
+
}
|
|
72
|
+
this.stats.totalOperations++;
|
|
73
|
+
this.checkFlush();
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Add a read operation to be coalesced
|
|
78
|
+
*/
|
|
79
|
+
async read(key) {
|
|
80
|
+
return new Promise((resolve, reject) => {
|
|
81
|
+
// Check if we already have a pending read for this key
|
|
82
|
+
const existing = this.readQueue.get(key);
|
|
83
|
+
if (existing && existing.length > 0) {
|
|
84
|
+
// Coalesce with existing read
|
|
85
|
+
existing.push({
|
|
86
|
+
type: 'read',
|
|
87
|
+
key,
|
|
88
|
+
resolve,
|
|
89
|
+
reject,
|
|
90
|
+
timestamp: Date.now()
|
|
91
|
+
});
|
|
92
|
+
this.stats.deduplicated++;
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
// New read operation
|
|
96
|
+
this.readQueue.set(key, [{
|
|
97
|
+
type: 'read',
|
|
98
|
+
key,
|
|
99
|
+
resolve,
|
|
100
|
+
reject,
|
|
101
|
+
timestamp: Date.now()
|
|
102
|
+
}]);
|
|
103
|
+
}
|
|
104
|
+
this.stats.totalOperations++;
|
|
105
|
+
this.checkFlush();
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Add a delete operation to be coalesced
|
|
110
|
+
*/
|
|
111
|
+
async delete(key) {
|
|
112
|
+
return new Promise((resolve, reject) => {
|
|
113
|
+
// Cancel any pending writes for this key
|
|
114
|
+
if (this.writeQueue.has(key)) {
|
|
115
|
+
const writes = this.writeQueue.get(key);
|
|
116
|
+
writes.forEach(op => op.reject(new Error('Cancelled by delete')));
|
|
117
|
+
this.writeQueue.delete(key);
|
|
118
|
+
this.stats.deduplicated += writes.length;
|
|
119
|
+
}
|
|
120
|
+
// Cancel any pending reads for this key
|
|
121
|
+
if (this.readQueue.has(key)) {
|
|
122
|
+
const reads = this.readQueue.get(key);
|
|
123
|
+
reads.forEach(op => op.resolve(null)); // Return null for deleted items
|
|
124
|
+
this.readQueue.delete(key);
|
|
125
|
+
this.stats.deduplicated += reads.length;
|
|
126
|
+
}
|
|
127
|
+
// Check if we already have a pending delete
|
|
128
|
+
const existing = this.deleteQueue.get(key);
|
|
129
|
+
if (existing && existing.length > 0) {
|
|
130
|
+
// Coalesce with existing delete
|
|
131
|
+
existing.push({
|
|
132
|
+
type: 'delete',
|
|
133
|
+
key,
|
|
134
|
+
resolve,
|
|
135
|
+
reject,
|
|
136
|
+
timestamp: Date.now()
|
|
137
|
+
});
|
|
138
|
+
this.stats.deduplicated++;
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
// New delete operation
|
|
142
|
+
this.deleteQueue.set(key, [{
|
|
143
|
+
type: 'delete',
|
|
144
|
+
key,
|
|
145
|
+
resolve,
|
|
146
|
+
reject,
|
|
147
|
+
timestamp: Date.now()
|
|
148
|
+
}]);
|
|
149
|
+
}
|
|
150
|
+
this.stats.totalOperations++;
|
|
151
|
+
this.checkFlush();
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Check if we should flush the queues
|
|
156
|
+
*/
|
|
157
|
+
checkFlush() {
|
|
158
|
+
const totalSize = this.writeQueue.size + this.readQueue.size + this.deleteQueue.size;
|
|
159
|
+
const now = Date.now();
|
|
160
|
+
const age = now - this.lastFlush;
|
|
161
|
+
// Immediate flush conditions
|
|
162
|
+
if (totalSize >= this.maxBatchSize) {
|
|
163
|
+
this.flush('size_limit');
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
// Age-based flush
|
|
167
|
+
if (age >= this.maxBatchAge && totalSize >= this.minBatchSize) {
|
|
168
|
+
this.flush('age_limit');
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
// Schedule a flush if not already scheduled
|
|
172
|
+
if (!this.flushTimer && totalSize > 0) {
|
|
173
|
+
const delay = Math.max(10, this.maxBatchAge - age);
|
|
174
|
+
this.flushTimer = setTimeout(() => {
|
|
175
|
+
this.flush('timer');
|
|
176
|
+
}, delay);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Flush all queued operations
|
|
181
|
+
*/
|
|
182
|
+
async flush(reason = 'manual') {
|
|
183
|
+
// Clear timer
|
|
184
|
+
if (this.flushTimer) {
|
|
185
|
+
clearTimeout(this.flushTimer);
|
|
186
|
+
this.flushTimer = null;
|
|
187
|
+
}
|
|
188
|
+
// Collect all operations into a single batch
|
|
189
|
+
const batch = [];
|
|
190
|
+
// Process deletes first (highest priority)
|
|
191
|
+
this.deleteQueue.forEach((ops) => {
|
|
192
|
+
// Only take the first operation per key (others are duplicates)
|
|
193
|
+
if (ops.length > 0) {
|
|
194
|
+
batch.push(ops[0]);
|
|
195
|
+
this.stats.coalescedOperations += ops.length;
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
// Then writes
|
|
199
|
+
this.writeQueue.forEach((ops) => {
|
|
200
|
+
if (ops.length > 0) {
|
|
201
|
+
// Use the last write (most recent data)
|
|
202
|
+
const lastWrite = ops[ops.length - 1];
|
|
203
|
+
batch.push(lastWrite);
|
|
204
|
+
this.stats.coalescedOperations += ops.length;
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
// Then reads
|
|
208
|
+
this.readQueue.forEach((ops) => {
|
|
209
|
+
if (ops.length > 0) {
|
|
210
|
+
batch.push(ops[0]);
|
|
211
|
+
this.stats.coalescedOperations += ops.length;
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
// Clear queues
|
|
215
|
+
const allOps = [
|
|
216
|
+
...Array.from(this.deleteQueue.values()).flat(),
|
|
217
|
+
...Array.from(this.writeQueue.values()).flat(),
|
|
218
|
+
...Array.from(this.readQueue.values()).flat()
|
|
219
|
+
];
|
|
220
|
+
this.deleteQueue.clear();
|
|
221
|
+
this.writeQueue.clear();
|
|
222
|
+
this.readQueue.clear();
|
|
223
|
+
if (batch.length === 0) {
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
// Update stats
|
|
227
|
+
this.stats.batchesProcessed++;
|
|
228
|
+
this.stats.averageBatchSize =
|
|
229
|
+
(this.stats.averageBatchSize * (this.stats.batchesProcessed - 1) + batch.length) /
|
|
230
|
+
this.stats.batchesProcessed;
|
|
231
|
+
this.logger.debug(`Flushing batch of ${batch.length} operations (${allOps.length} total) - reason: ${reason}`);
|
|
232
|
+
// Process the batch
|
|
233
|
+
try {
|
|
234
|
+
await this.processor(batch);
|
|
235
|
+
// Resolve all promises
|
|
236
|
+
allOps.forEach(op => {
|
|
237
|
+
if (op.type === 'read') {
|
|
238
|
+
// Find the result for this read
|
|
239
|
+
const result = batch.find(b => b.key === op.key && b.type === 'read');
|
|
240
|
+
op.resolve(result?.data || null);
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
op.resolve(undefined);
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
catch (error) {
|
|
248
|
+
// Reject all promises
|
|
249
|
+
allOps.forEach(op => op.reject(error));
|
|
250
|
+
this.logger.error('Batch processing failed:', error);
|
|
251
|
+
}
|
|
252
|
+
this.lastFlush = Date.now();
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Get current statistics
|
|
256
|
+
*/
|
|
257
|
+
getStats() {
|
|
258
|
+
return { ...this.stats };
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Get current queue sizes
|
|
262
|
+
*/
|
|
263
|
+
getQueueSizes() {
|
|
264
|
+
return {
|
|
265
|
+
writes: this.writeQueue.size,
|
|
266
|
+
reads: this.readQueue.size,
|
|
267
|
+
deletes: this.deleteQueue.size,
|
|
268
|
+
total: this.writeQueue.size + this.readQueue.size + this.deleteQueue.size
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Adjust batch parameters based on load
|
|
273
|
+
*/
|
|
274
|
+
adjustParameters(pending) {
|
|
275
|
+
if (pending > 10000) {
|
|
276
|
+
// Extreme load - batch aggressively
|
|
277
|
+
this.maxBatchSize = 500;
|
|
278
|
+
this.maxBatchAge = 50;
|
|
279
|
+
this.minBatchSize = 50;
|
|
280
|
+
}
|
|
281
|
+
else if (pending > 1000) {
|
|
282
|
+
// High load - larger batches
|
|
283
|
+
this.maxBatchSize = 200;
|
|
284
|
+
this.maxBatchAge = 100;
|
|
285
|
+
this.minBatchSize = 20;
|
|
286
|
+
}
|
|
287
|
+
else if (pending > 100) {
|
|
288
|
+
// Moderate load
|
|
289
|
+
this.maxBatchSize = 100;
|
|
290
|
+
this.maxBatchAge = 200;
|
|
291
|
+
this.minBatchSize = 10;
|
|
292
|
+
}
|
|
293
|
+
else {
|
|
294
|
+
// Low load - optimize for latency
|
|
295
|
+
this.maxBatchSize = 50;
|
|
296
|
+
this.maxBatchAge = 500;
|
|
297
|
+
this.minBatchSize = 5;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Force immediate flush of all operations
|
|
302
|
+
*/
|
|
303
|
+
async forceFlush() {
|
|
304
|
+
await this.flush('force');
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
// Global coalescer instances by storage type
|
|
308
|
+
const coalescers = new Map();
|
|
309
|
+
/**
|
|
310
|
+
* Get or create a coalescer for a storage instance
|
|
311
|
+
*/
|
|
312
|
+
export function getCoalescer(storageId, processor) {
|
|
313
|
+
if (!coalescers.has(storageId)) {
|
|
314
|
+
coalescers.set(storageId, new RequestCoalescer(processor));
|
|
315
|
+
}
|
|
316
|
+
return coalescers.get(storageId);
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Clear all coalescers
|
|
320
|
+
*/
|
|
321
|
+
export function clearCoalescers() {
|
|
322
|
+
coalescers.clear();
|
|
323
|
+
}
|
|
324
|
+
//# sourceMappingURL=requestCoalescer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"requestCoalescer.js","sourceRoot":"","sources":["../../src/utils/requestCoalescer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Write Buffer
|
|
3
|
+
* Accumulates writes and flushes them in bulk to reduce S3 operations
|
|
4
|
+
* Implements intelligent deduplication and compression
|
|
5
|
+
*/
|
|
6
|
+
interface FlushResult {
|
|
7
|
+
successful: number;
|
|
8
|
+
failed: number;
|
|
9
|
+
duration: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* High-performance write buffer for bulk operations
|
|
13
|
+
*/
|
|
14
|
+
export declare class WriteBuffer<T> {
|
|
15
|
+
private logger;
|
|
16
|
+
private buffer;
|
|
17
|
+
private maxBufferSize;
|
|
18
|
+
private flushInterval;
|
|
19
|
+
private minFlushSize;
|
|
20
|
+
private maxRetries;
|
|
21
|
+
private flushTimer;
|
|
22
|
+
private isFlushing;
|
|
23
|
+
private lastFlush;
|
|
24
|
+
private pendingFlush;
|
|
25
|
+
private totalWrites;
|
|
26
|
+
private totalFlushes;
|
|
27
|
+
private failedWrites;
|
|
28
|
+
private duplicatesRemoved;
|
|
29
|
+
private writeFunction;
|
|
30
|
+
private type;
|
|
31
|
+
private backpressure;
|
|
32
|
+
constructor(type: 'noun' | 'verb' | 'metadata', writeFunction: (items: Map<string, T>) => Promise<void>, options?: {
|
|
33
|
+
maxBufferSize?: number;
|
|
34
|
+
flushInterval?: number;
|
|
35
|
+
minFlushSize?: number;
|
|
36
|
+
});
|
|
37
|
+
/**
|
|
38
|
+
* Add item to buffer
|
|
39
|
+
*/
|
|
40
|
+
add(id: string, data: T): Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* Check if we should flush
|
|
43
|
+
*/
|
|
44
|
+
private checkFlush;
|
|
45
|
+
/**
|
|
46
|
+
* Flush buffer to storage
|
|
47
|
+
*/
|
|
48
|
+
flush(reason?: string): Promise<FlushResult>;
|
|
49
|
+
/**
|
|
50
|
+
* Perform the actual flush
|
|
51
|
+
*/
|
|
52
|
+
private doFlush;
|
|
53
|
+
/**
|
|
54
|
+
* Start periodic flush timer
|
|
55
|
+
*/
|
|
56
|
+
private startPeriodicFlush;
|
|
57
|
+
/**
|
|
58
|
+
* Stop periodic flush timer
|
|
59
|
+
*/
|
|
60
|
+
stop(): void;
|
|
61
|
+
/**
|
|
62
|
+
* Force flush all pending writes
|
|
63
|
+
*/
|
|
64
|
+
forceFlush(): Promise<FlushResult>;
|
|
65
|
+
/**
|
|
66
|
+
* Get buffer statistics
|
|
67
|
+
*/
|
|
68
|
+
getStats(): {
|
|
69
|
+
bufferSize: number;
|
|
70
|
+
totalWrites: number;
|
|
71
|
+
totalFlushes: number;
|
|
72
|
+
failedWrites: number;
|
|
73
|
+
duplicatesRemoved: number;
|
|
74
|
+
avgFlushSize: number;
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* Adjust parameters based on load
|
|
78
|
+
*/
|
|
79
|
+
adjustForLoad(pendingRequests: number): void;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Get or create a write buffer
|
|
83
|
+
*/
|
|
84
|
+
export declare function getWriteBuffer<T>(id: string, type: 'noun' | 'verb' | 'metadata', writeFunction: (items: Map<string, T>) => Promise<void>): WriteBuffer<T>;
|
|
85
|
+
/**
|
|
86
|
+
* Flush all write buffers
|
|
87
|
+
*/
|
|
88
|
+
export declare function flushAllBuffers(): Promise<void>;
|
|
89
|
+
/**
|
|
90
|
+
* Clear all write buffers
|
|
91
|
+
*/
|
|
92
|
+
export declare function clearWriteBuffers(): void;
|
|
93
|
+
export {};
|