@far-world-labs/verblets 0.1.7 → 0.3.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/README.md +86 -213
- package/dist/index.browser.js +74 -0
- package/dist/index.js +548 -0
- package/dist/shared-C6kPWghF.js +7806 -0
- package/package.json +32 -8
- package/.cursor/launch.json +0 -30
- package/.cursor/settings.json +0 -20
- package/.github/workflows/branch-protection.yml +0 -22
- package/.github/workflows/ci.yml +0 -165
- package/.husky/pre-commit +0 -4
- package/.prettierrc +0 -6
- package/.release-it.json +0 -12
- package/.vitest.config.examples.js +0 -8
- package/.vitest.config.js +0 -8
- package/.vscode/launch.json +0 -31
- package/AGENTS.md +0 -220
- package/DEVELOPING.md +0 -105
- package/docker-compose.yml +0 -7
- package/eslint.config.js +0 -80
- package/scripts/generate-chain/index.js +0 -111
- package/scripts/generate-lib/index.js +0 -68
- package/scripts/generate-test/index.js +0 -137
- package/scripts/generate-verblet/README.md +0 -17
- package/scripts/generate-verblet/index.js +0 -110
- package/scripts/run.sh +0 -15
- package/scripts/runner/index.js +0 -56
- package/scripts/simple-editor/README.md +0 -34
- package/scripts/simple-editor/index.js +0 -79
- package/scripts/summarize-files/index.js +0 -70
- package/src/chains/README.md +0 -30
- package/src/chains/anonymize/README.md +0 -21
- package/src/chains/anonymize/index.examples.js +0 -75
- package/src/chains/anonymize/index.js +0 -121
- package/src/chains/anonymize/index.spec.js +0 -78
- package/src/chains/bulk-central-tendency/index.examples.js +0 -138
- package/src/chains/bulk-central-tendency/index.js +0 -91
- package/src/chains/bulk-filter/README.md +0 -21
- package/src/chains/bulk-filter/index.examples.js +0 -22
- package/src/chains/bulk-filter/index.js +0 -58
- package/src/chains/bulk-filter/index.spec.js +0 -38
- package/src/chains/bulk-find/README.md +0 -16
- package/src/chains/bulk-find/index.examples.js +0 -20
- package/src/chains/bulk-find/index.js +0 -30
- package/src/chains/bulk-find/index.spec.js +0 -26
- package/src/chains/bulk-group/README.md +0 -23
- package/src/chains/bulk-group/index.examples.js +0 -18
- package/src/chains/bulk-group/index.js +0 -34
- package/src/chains/bulk-group/index.spec.js +0 -41
- package/src/chains/bulk-map/README.md +0 -43
- package/src/chains/bulk-map/index.examples.js +0 -17
- package/src/chains/bulk-map/index.js +0 -86
- package/src/chains/bulk-map/index.spec.js +0 -44
- package/src/chains/bulk-reduce/README.md +0 -12
- package/src/chains/bulk-reduce/index.examples.js +0 -15
- package/src/chains/bulk-reduce/index.js +0 -13
- package/src/chains/bulk-reduce/index.spec.js +0 -25
- package/src/chains/bulk-score/README.md +0 -16
- package/src/chains/bulk-score/bulk-score-result.json +0 -18
- package/src/chains/bulk-score/index.examples.js +0 -22
- package/src/chains/bulk-score/index.js +0 -133
- package/src/chains/bulk-score/index.spec.js +0 -30
- package/src/chains/category-samples/README.md +0 -61
- package/src/chains/category-samples/index.examples.js +0 -103
- package/src/chains/category-samples/index.js +0 -134
- package/src/chains/collect-terms/README.md +0 -12
- package/src/chains/collect-terms/index.examples.js +0 -16
- package/src/chains/collect-terms/index.js +0 -44
- package/src/chains/collect-terms/index.spec.js +0 -25
- package/src/chains/date/README.md +0 -12
- package/src/chains/date/index.examples.js +0 -47
- package/src/chains/date/index.js +0 -74
- package/src/chains/date/index.spec.js +0 -62
- package/src/chains/disambiguate/README.md +0 -22
- package/src/chains/disambiguate/disambiguate-meanings-result.json +0 -16
- package/src/chains/disambiguate/index.examples.js +0 -18
- package/src/chains/disambiguate/index.js +0 -92
- package/src/chains/disambiguate/index.spec.js +0 -25
- package/src/chains/dismantle/README.md +0 -67
- package/src/chains/dismantle/dismantle.examples.js +0 -27
- package/src/chains/dismantle/index.examples.js +0 -30
- package/src/chains/dismantle/index.js +0 -303
- package/src/chains/dismantle/index.spec.js +0 -32
- package/src/chains/expect/README.md +0 -171
- package/src/chains/expect/index.examples.js +0 -146
- package/src/chains/expect/index.js +0 -173
- package/src/chains/expect/index.spec.js +0 -324
- package/src/chains/filter-ambiguous/README.md +0 -11
- package/src/chains/filter-ambiguous/index.examples.js +0 -20
- package/src/chains/filter-ambiguous/index.js +0 -49
- package/src/chains/filter-ambiguous/index.spec.js +0 -31
- package/src/chains/glossary/README.md +0 -19
- package/src/chains/glossary/index.examples.js +0 -386
- package/src/chains/glossary/index.js +0 -75
- package/src/chains/glossary/index.spec.js +0 -19
- package/src/chains/intersections/README.md +0 -152
- package/src/chains/intersections/index.examples.js +0 -279
- package/src/chains/intersections/index.js +0 -366
- package/src/chains/intersections/intersection-result.json +0 -38
- package/src/chains/list/index.examples.js +0 -68
- package/src/chains/list/index.js +0 -214
- package/src/chains/list/index.spec.js +0 -67
- package/src/chains/list/list-result.json +0 -16
- package/src/chains/list/schema.json +0 -24
- package/src/chains/llm-logger/README.md +0 -208
- package/src/chains/llm-logger/index.js +0 -205
- package/src/chains/llm-logger/index.spec.js +0 -330
- package/src/chains/questions/index.examples.js +0 -69
- package/src/chains/questions/index.js +0 -135
- package/src/chains/questions/index.spec.js +0 -29
- package/src/chains/scan-js/index.js +0 -116
- package/src/chains/set-interval/README.md +0 -81
- package/src/chains/set-interval/index.examples.js +0 -36
- package/src/chains/set-interval/index.js +0 -131
- package/src/chains/set-interval/index.spec.js +0 -70
- package/src/chains/socratic/README.md +0 -17
- package/src/chains/socratic/index.js +0 -64
- package/src/chains/socratic/index.spec.js +0 -24
- package/src/chains/sort/index.examples.js +0 -36
- package/src/chains/sort/index.js +0 -163
- package/src/chains/sort/index.spec.js +0 -112
- package/src/chains/sort/sort-result.json +0 -16
- package/src/chains/summary-map/README.md +0 -41
- package/src/chains/summary-map/index.examples.js +0 -64
- package/src/chains/summary-map/index.js +0 -226
- package/src/chains/summary-map/index.spec.js +0 -153
- package/src/chains/test/index.js +0 -114
- package/src/chains/test-advice/index.js +0 -35
- package/src/chains/themes/README.md +0 -20
- package/src/chains/themes/index.examples.js +0 -17
- package/src/chains/themes/index.js +0 -28
- package/src/chains/themes/index.spec.js +0 -19
- package/src/chains/veiled-variants/index.examples.js +0 -18
- package/src/chains/veiled-variants/index.js +0 -107
- package/src/chains/veiled-variants/index.spec.js +0 -40
- package/src/constants/common.js +0 -7
- package/src/constants/messages.js +0 -3
- package/src/constants/models.js +0 -183
- package/src/index.js +0 -193
- package/src/json-schemas/README.md +0 -13
- package/src/json-schemas/cars-test.json +0 -11
- package/src/json-schemas/index.js +0 -12
- package/src/json-schemas/intent.json +0 -38
- package/src/json-schemas/schema-dot-org-photograph.json +0 -133
- package/src/json-schemas/schema-dot-org-place.json +0 -129
- package/src/lib/README.md +0 -26
- package/src/lib/any-signal/index.js +0 -28
- package/src/lib/bulk-filter/README.md +0 -22
- package/src/lib/bulk-filter/index.examples.js +0 -27
- package/src/lib/bulk-filter/index.js +0 -63
- package/src/lib/bulk-filter/index.spec.js +0 -38
- package/src/lib/bulk-find/README.md +0 -18
- package/src/lib/bulk-find/index.examples.js +0 -19
- package/src/lib/bulk-find/index.js +0 -30
- package/src/lib/bulk-find/index.spec.js +0 -41
- package/src/lib/chatgpt/index.js +0 -163
- package/src/lib/combinations/index.js +0 -30
- package/src/lib/combinations/index.spec.js +0 -23
- package/src/lib/editor/index.js +0 -31
- package/src/lib/functional/index.js +0 -28
- package/src/lib/logger-service/index.js +0 -32
- package/src/lib/parse-js-parts/index.js +0 -321
- package/src/lib/parse-js-parts/index.spec.js +0 -156
- package/src/lib/parse-llm-list/README.md +0 -39
- package/src/lib/parse-llm-list/index.js +0 -54
- package/src/lib/parse-llm-list/index.spec.js +0 -59
- package/src/lib/path-aliases/index.js +0 -37
- package/src/lib/path-aliases/index.spec.js +0 -64
- package/src/lib/pave/index.js +0 -34
- package/src/lib/pave/index.spec.js +0 -76
- package/src/lib/prompt-cache/index.js +0 -50
- package/src/lib/retry/index.js +0 -66
- package/src/lib/retry/index.spec.js +0 -86
- package/src/lib/ring-buffer/README.md +0 -460
- package/src/lib/ring-buffer/index.js +0 -1074
- package/src/lib/search-best-first/city-walk.spec.js +0 -37
- package/src/lib/search-best-first/index.js +0 -97
- package/src/lib/search-best-first/index.spec.js +0 -35
- package/src/lib/search-js-files/code-features-property-definitions.json +0 -123
- package/src/lib/search-js-files/index.examples.js +0 -22
- package/src/lib/search-js-files/index.js +0 -155
- package/src/lib/search-js-files/index.spec.js +0 -34
- package/src/lib/search-js-files/scan-file.js +0 -242
- package/src/lib/shorten-text/index.js +0 -25
- package/src/lib/shorten-text/index.spec.js +0 -68
- package/src/lib/strip-numeric/index.js +0 -5
- package/src/lib/strip-response/index.js +0 -30
- package/src/lib/template-replace/index.js +0 -23
- package/src/lib/template-replace/index.spec.js +0 -60
- package/src/lib/timed-abort-controller/index.js +0 -41
- package/src/lib/to-bool/index.js +0 -8
- package/src/lib/to-date/index.js +0 -11
- package/src/lib/to-enum/index.js +0 -14
- package/src/lib/to-number/index.js +0 -12
- package/src/lib/to-number-with-units/index.js +0 -51
- package/src/lib/transcribe/index.js +0 -78
- package/src/prompts/README.md +0 -17
- package/src/prompts/as-enum.js +0 -5
- package/src/prompts/as-json-schema.js +0 -9
- package/src/prompts/as-object-with-schema.js +0 -26
- package/src/prompts/as-schema-org-text.js +0 -25
- package/src/prompts/as-schema-org-type.js +0 -1
- package/src/prompts/blog-post.js +0 -7
- package/src/prompts/code-features.js +0 -24
- package/src/prompts/constants.js +0 -101
- package/src/prompts/features-json-schema.js +0 -27
- package/src/prompts/generate-collection.js +0 -26
- package/src/prompts/generate-list.js +0 -48
- package/src/prompts/generate-questions.js +0 -19
- package/src/prompts/index.js +0 -20
- package/src/prompts/intent.js +0 -60
- package/src/prompts/output-succinct-names.js +0 -3
- package/src/prompts/select-from-threshold.js +0 -17
- package/src/prompts/sort.js +0 -31
- package/src/prompts/style.js +0 -38
- package/src/prompts/summarize.js +0 -13
- package/src/prompts/token-budget.js +0 -3
- package/src/prompts/wrap-list.js +0 -11
- package/src/prompts/wrap-variable.js +0 -36
- package/src/services/llm-model/global-overrides.spec.js +0 -432
- package/src/services/llm-model/index.js +0 -308
- package/src/services/llm-model/model.js +0 -21
- package/src/services/llm-model/negotiate.spec.js +0 -447
- package/src/services/redis/index.js +0 -147
- package/src/test/setup.js +0 -20
- package/src/verblets/README.md +0 -26
- package/src/verblets/auto/index.examples.js +0 -31
- package/src/verblets/auto/index.js +0 -28
- package/src/verblets/auto/index.spec.js +0 -32
- package/src/verblets/bool/README.md +0 -36
- package/src/verblets/bool/index.examples.js +0 -80
- package/src/verblets/bool/index.js +0 -25
- package/src/verblets/bool/index.schema.json +0 -14
- package/src/verblets/bool/index.spec.js +0 -33
- package/src/verblets/central-tendency/README.md +0 -166
- package/src/verblets/central-tendency/central-tendency-result.json +0 -24
- package/src/verblets/central-tendency/index.examples.js +0 -196
- package/src/verblets/central-tendency/index.js +0 -171
- package/src/verblets/central-tendency/index.spec.js +0 -148
- package/src/verblets/enum/index.examples.js +0 -30
- package/src/verblets/enum/index.js +0 -18
- package/src/verblets/enum/index.spec.js +0 -35
- package/src/verblets/expect/README.md +0 -64
- package/src/verblets/expect/index.examples.js +0 -109
- package/src/verblets/expect/index.js +0 -75
- package/src/verblets/expect/index.spec.js +0 -127
- package/src/verblets/intent/index.examples.js +0 -139
- package/src/verblets/intent/index.js +0 -60
- package/src/verblets/intent/index.spec.js +0 -31
- package/src/verblets/intersection/README.md +0 -16
- package/src/verblets/intersection/index.examples.js +0 -89
- package/src/verblets/intersection/index.js +0 -84
- package/src/verblets/intersection/index.spec.js +0 -60
- package/src/verblets/intersection/intersection-result.json +0 -16
- package/src/verblets/list-expand/README.md +0 -10
- package/src/verblets/list-expand/index.examples.js +0 -14
- package/src/verblets/list-expand/index.js +0 -104
- package/src/verblets/list-expand/index.spec.js +0 -18
- package/src/verblets/list-expand/list-expand-result.json +0 -16
- package/src/verblets/list-filter/README.md +0 -22
- package/src/verblets/list-filter/index.examples.js +0 -26
- package/src/verblets/list-filter/index.js +0 -18
- package/src/verblets/list-filter/index.spec.js +0 -19
- package/src/verblets/list-find/README.md +0 -11
- package/src/verblets/list-find/index.examples.js +0 -15
- package/src/verblets/list-find/index.js +0 -17
- package/src/verblets/list-find/index.spec.js +0 -19
- package/src/verblets/list-group/README.md +0 -16
- package/src/verblets/list-group/index.examples.js +0 -16
- package/src/verblets/list-group/index.js +0 -112
- package/src/verblets/list-group/index.spec.js +0 -35
- package/src/verblets/list-group/list-group-result.json +0 -16
- package/src/verblets/list-map/README.md +0 -11
- package/src/verblets/list-map/index.examples.js +0 -15
- package/src/verblets/list-map/index.js +0 -26
- package/src/verblets/list-map/index.spec.js +0 -17
- package/src/verblets/list-reduce/README.md +0 -10
- package/src/verblets/list-reduce/index.examples.js +0 -14
- package/src/verblets/list-reduce/index.js +0 -21
- package/src/verblets/list-reduce/index.spec.js +0 -27
- package/src/verblets/list-reduce/index.spec.jsx +0 -27
- package/src/verblets/name/README.md +0 -15
- package/src/verblets/name/index.examples.js +0 -28
- package/src/verblets/name/index.js +0 -19
- package/src/verblets/name/index.spec.js +0 -33
- package/src/verblets/name-similar-to/README.md +0 -26
- package/src/verblets/name-similar-to/index.examples.js +0 -18
- package/src/verblets/name-similar-to/index.js +0 -20
- package/src/verblets/name-similar-to/index.spec.js +0 -13
- package/src/verblets/number/index.examples.js +0 -199
- package/src/verblets/number/index.js +0 -25
- package/src/verblets/number/index.spec.js +0 -33
- package/src/verblets/number-with-units/index.examples.js +0 -38
- package/src/verblets/number-with-units/index.js +0 -84
- package/src/verblets/number-with-units/index.spec.js +0 -46
- package/src/verblets/number-with-units/number-with-units-result.json +0 -23
- package/src/verblets/schema-org/index.examples.js +0 -51
- package/src/verblets/schema-org/index.js +0 -37
- package/src/verblets/schema-org/index.spec.js +0 -39
- package/src/verblets/sentiment/README.md +0 -10
- package/src/verblets/sentiment/index.examples.js +0 -20
- package/src/verblets/sentiment/index.js +0 -9
- package/src/verblets/sentiment/index.spec.js +0 -20
- package/src/verblets/to-object/README.md +0 -38
- package/src/verblets/to-object/index.examples.js +0 -29
- package/src/verblets/to-object/index.js +0 -131
- package/src/verblets/to-object/index.spec.js +0 -71
|
@@ -1,460 +0,0 @@
|
|
|
1
|
-
# Ring Buffer
|
|
2
|
-
|
|
3
|
-
A memory-efficient circular buffer designed for high-throughput logging, batch processing, and LLM operations. Automatically evicts oldest entries when full, making it ideal for streaming data scenarios where memory efficiency is critical.
|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
|
|
7
|
-
- **Automatic Memory Management**: Configurable size limits with automatic eviction of oldest entries
|
|
8
|
-
- **Multiple Cursor Support**: Track multiple processing positions concurrently
|
|
9
|
-
- **Batch Operations**: Optimized for LLM workflows with parallel and sequential processing
|
|
10
|
-
- **Flexible Access Patterns**: ID-based, index-based, and time-based slicing
|
|
11
|
-
- **Rich Query Interface**: Filter, find, map, and reduce operations
|
|
12
|
-
- **Iterator Support**: Works with for...of loops and spread operator
|
|
13
|
-
- **Statistics Tracking**: Monitor buffer usage and performance metrics
|
|
14
|
-
|
|
15
|
-
## Basic Usage
|
|
16
|
-
|
|
17
|
-
```javascript
|
|
18
|
-
import RingBuffer from '../lib/ring-buffer/index.js';
|
|
19
|
-
|
|
20
|
-
// Create buffer with capacity of 1000 entries
|
|
21
|
-
const buffer = new RingBuffer(1000);
|
|
22
|
-
|
|
23
|
-
// Add entries
|
|
24
|
-
const entry1 = buffer.push('Hello world');
|
|
25
|
-
const entry2 = buffer.push({ user: 'alice', action: 'login' });
|
|
26
|
-
|
|
27
|
-
// Get all entries
|
|
28
|
-
const allEntries = buffer.all();
|
|
29
|
-
console.log(`Buffer contains ${allEntries.length} entries`);
|
|
30
|
-
|
|
31
|
-
// Add metadata
|
|
32
|
-
const meta = new Map([['source', 'api'], ['priority', 'high']]);
|
|
33
|
-
buffer.push('Important message', meta);
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
## Batch Operations
|
|
37
|
-
|
|
38
|
-
Perfect for processing large datasets in manageable chunks:
|
|
39
|
-
|
|
40
|
-
```javascript
|
|
41
|
-
// Add multiple entries at once
|
|
42
|
-
const logData = ['error 1', 'error 2', 'error 3'];
|
|
43
|
-
const entries = buffer.pushBatch(logData);
|
|
44
|
-
|
|
45
|
-
// Process in batches
|
|
46
|
-
await buffer.processBatches(50, async (batch, batchIndex) => {
|
|
47
|
-
console.log(`Processing batch ${batchIndex} with ${batch.length} entries`);
|
|
48
|
-
|
|
49
|
-
// Your processing logic here
|
|
50
|
-
const results = await processLogBatch(batch);
|
|
51
|
-
return results;
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
// Parallel processing for better performance
|
|
55
|
-
await buffer.processBatches(25, processBatch, { parallel: true });
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
## Cursor Operations
|
|
59
|
-
|
|
60
|
-
Track multiple processing positions for concurrent operations:
|
|
61
|
-
|
|
62
|
-
```javascript
|
|
63
|
-
// Create cursors for different processors
|
|
64
|
-
buffer.setCursor('error-processor', 0);
|
|
65
|
-
buffer.setCursor('audit-processor', 0);
|
|
66
|
-
buffer.setCursor('analytics-processor', 0);
|
|
67
|
-
|
|
68
|
-
// Process new entries since last cursor position
|
|
69
|
-
const newErrors = buffer.getSinceCursor('error-processor');
|
|
70
|
-
console.log(`Found ${newErrors.length} new entries to process`);
|
|
71
|
-
|
|
72
|
-
// Cursor automatically moves to latest processed position
|
|
73
|
-
// Or control cursor movement manually
|
|
74
|
-
const entries = buffer.getSinceCursor('audit-processor', false); // Don't move cursor
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
## Flexible Querying
|
|
78
|
-
|
|
79
|
-
Rich query interface for finding and analyzing data:
|
|
80
|
-
|
|
81
|
-
```javascript
|
|
82
|
-
// Find entries matching criteria
|
|
83
|
-
const errors = buffer.filter(entry =>
|
|
84
|
-
typeof entry.data === 'string' && entry.data.includes('ERROR')
|
|
85
|
-
);
|
|
86
|
-
|
|
87
|
-
// Find first match
|
|
88
|
-
const criticalError = buffer.find(entry =>
|
|
89
|
-
entry.meta.get('priority') === 'critical'
|
|
90
|
-
);
|
|
91
|
-
|
|
92
|
-
// Transform data
|
|
93
|
-
const timestamps = buffer.map(entry => entry.timestamp);
|
|
94
|
-
|
|
95
|
-
// Aggregate data
|
|
96
|
-
const totalSize = buffer.reduce((sum, entry) =>
|
|
97
|
-
sum + JSON.stringify(entry.data).length, 0
|
|
98
|
-
);
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
## Slicing Operations
|
|
102
|
-
|
|
103
|
-
Access data using different strategies:
|
|
104
|
-
|
|
105
|
-
```javascript
|
|
106
|
-
// Get entries by ID range
|
|
107
|
-
const recentEntries = buffer.slice(1000, 1100);
|
|
108
|
-
|
|
109
|
-
// Get entries by index (like Array.slice)
|
|
110
|
-
const firstTen = buffer.sliceByIndex(0, 10);
|
|
111
|
-
const lastTen = buffer.tail(10);
|
|
112
|
-
|
|
113
|
-
// Get entries by time range
|
|
114
|
-
const lastHour = new Date(Date.now() - 3600000);
|
|
115
|
-
const recentLogs = buffer.sliceByTime(lastHour);
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
## Memory Management
|
|
119
|
-
|
|
120
|
-
Automatic memory management with detailed statistics:
|
|
121
|
-
|
|
122
|
-
```javascript
|
|
123
|
-
// Check buffer status
|
|
124
|
-
console.log(`Buffer is ${buffer.isFull() ? 'full' : 'not full'}`);
|
|
125
|
-
console.log(`Current size: ${buffer.size()}/${buffer.capacity()}`);
|
|
126
|
-
|
|
127
|
-
// Get detailed statistics
|
|
128
|
-
const stats = buffer.getStats();
|
|
129
|
-
console.log(`Total added: ${stats.totalAdded}`);
|
|
130
|
-
console.log(`Total evicted: ${stats.totalEvicted}`);
|
|
131
|
-
console.log(`Active cursors: ${stats.cursors}`);
|
|
132
|
-
|
|
133
|
-
// Clear buffer when needed
|
|
134
|
-
buffer.clear(); // Removes all entries and cursors
|
|
135
|
-
buffer.clear(true); // Keeps cursors, removes entries
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
## LLM Chain Integration
|
|
139
|
-
|
|
140
|
-
Designed specifically for LLM workflows:
|
|
141
|
-
|
|
142
|
-
```javascript
|
|
143
|
-
// Log processing pipeline
|
|
144
|
-
const logBuffer = new RingBuffer(5000);
|
|
145
|
-
|
|
146
|
-
// Add logs from various sources
|
|
147
|
-
logBuffer.push('User query: "What is the weather?"');
|
|
148
|
-
logBuffer.push({ type: 'llm-request', model: 'gpt-4', tokens: 150 });
|
|
149
|
-
logBuffer.push('LLM response: "The weather is sunny..."');
|
|
150
|
-
|
|
151
|
-
// Process logs in batches for LLM analysis
|
|
152
|
-
await logBuffer.processBatches(100, async (batch) => {
|
|
153
|
-
// Send batch to LLM for analysis
|
|
154
|
-
const analysis = await analyzeLogs(batch);
|
|
155
|
-
return analysis;
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
// Track different processing stages
|
|
159
|
-
logBuffer.setCursor('preprocessing', 0);
|
|
160
|
-
logBuffer.setCursor('llm-analysis', 0);
|
|
161
|
-
logBuffer.setCursor('postprocessing', 0);
|
|
162
|
-
|
|
163
|
-
// Each stage processes from its cursor position
|
|
164
|
-
const toPreprocess = logBuffer.getSinceCursor('preprocessing');
|
|
165
|
-
const toAnalyze = logBuffer.getSinceCursor('llm-analysis');
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
## Advanced Features
|
|
169
|
-
|
|
170
|
-
### Iterator Support
|
|
171
|
-
|
|
172
|
-
```javascript
|
|
173
|
-
// Use with for...of loops
|
|
174
|
-
for (const entry of buffer) {
|
|
175
|
-
console.log(`Entry ${entry.id}: ${entry.data}`);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// Use with spread operator
|
|
179
|
-
const allEntries = [...buffer];
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
### Filtered Buffers
|
|
183
|
-
|
|
184
|
-
```javascript
|
|
185
|
-
// Create new buffer with filtered data
|
|
186
|
-
const errorBuffer = buffer.createFiltered(
|
|
187
|
-
entry => entry.data.includes('ERROR'),
|
|
188
|
-
500 // New buffer capacity
|
|
189
|
-
);
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
### Cursor Metadata
|
|
193
|
-
|
|
194
|
-
```javascript
|
|
195
|
-
const cursor = buffer.setCursor('processor-1');
|
|
196
|
-
cursor.meta.set('owner', 'error-handler');
|
|
197
|
-
cursor.meta.set('last-processed', new Date());
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
## Performance Characteristics
|
|
201
|
-
|
|
202
|
-
- **Memory**: O(n) where n is buffer capacity (not total entries added)
|
|
203
|
-
- **Push**: O(1) amortized
|
|
204
|
-
- **Slice by ID**: O(n) where n is buffer size
|
|
205
|
-
- **Slice by Index**: O(k) where k is slice size
|
|
206
|
-
- **Cursor Operations**: O(1) for cursor management, O(n) for getSinceCursor
|
|
207
|
-
|
|
208
|
-
## Use Cases
|
|
209
|
-
|
|
210
|
-
- **High-throughput Logging**: Capture logs without memory leaks
|
|
211
|
-
- **LLM Chain Processing**: Batch operations on conversation history
|
|
212
|
-
- **Stream Processing**: Process data streams with multiple consumers
|
|
213
|
-
- **Audit Trails**: Maintain recent activity with automatic cleanup
|
|
214
|
-
- **Performance Monitoring**: Track metrics with bounded memory usage
|
|
215
|
-
- **Event Sourcing**: Store recent events with cursor-based replay
|
|
216
|
-
|
|
217
|
-
The ring buffer is particularly valuable in LLM applications where you need to maintain context windows, process conversation history in batches, or implement streaming responses with memory constraints.
|
|
218
|
-
|
|
219
|
-
## Stable Batch Processing
|
|
220
|
-
|
|
221
|
-
The ring buffer provides advanced stable batch processing capabilities that maintain consistent batch boundaries even when the buffer window changes due to eviction. This is essential for reliable retry scenarios and parallel processing.
|
|
222
|
-
|
|
223
|
-
### Key Features
|
|
224
|
-
|
|
225
|
-
- **Globally Stable Batches**: Batch definitions based on entry IDs (not indices) remain consistent
|
|
226
|
-
- **Cursor-Based Iteration**: Multiple cursors can iterate over identical batch boundaries
|
|
227
|
-
- **Built-in Retry Logic**: Configurable retry with exponential backoff
|
|
228
|
-
- **Parallel Processing**: Process batches concurrently while maintaining stability
|
|
229
|
-
- **Resume Capability**: Resume processing from exact batch boundaries after interruption
|
|
230
|
-
|
|
231
|
-
### Basic Stable Batch Processing
|
|
232
|
-
|
|
233
|
-
```javascript
|
|
234
|
-
const buffer = new RingBuffer(1000);
|
|
235
|
-
|
|
236
|
-
// Add data
|
|
237
|
-
for (let i = 1; i <= 100; i++) {
|
|
238
|
-
buffer.push({ id: i, data: `item-${i}` });
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
// Process in stable batches with retry
|
|
242
|
-
const results = await buffer.processStableBatches(10, async (entries, batchDef, context) => {
|
|
243
|
-
console.log(`Processing ${batchDef.batchId}: ${entries.length} entries`);
|
|
244
|
-
|
|
245
|
-
// Your processing logic here
|
|
246
|
-
return entries.map(entry => entry.data.toUpperCase());
|
|
247
|
-
}, {
|
|
248
|
-
maxRetries: 3,
|
|
249
|
-
retryDelay: (attempt) => 1000 * Math.pow(2, attempt), // Exponential backoff
|
|
250
|
-
parallel: false, // Sequential processing
|
|
251
|
-
onBatchStart: (batchDef) => console.log(`Starting ${batchDef.batchId}`),
|
|
252
|
-
onBatchComplete: (batchDef, result) => console.log(`Completed ${batchDef.batchId}`),
|
|
253
|
-
onBatchError: (batchDef, error, attempt) => console.log(`Error in ${batchDef.batchId}: ${error.message}`)
|
|
254
|
-
});
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
### Resumable Processing with Cursors
|
|
258
|
-
|
|
259
|
-
```javascript
|
|
260
|
-
// First processing run
|
|
261
|
-
try {
|
|
262
|
-
await buffer.processStableBatches(5, processor, {
|
|
263
|
-
cursorName: 'main-processor',
|
|
264
|
-
maxRetries: 2
|
|
265
|
-
});
|
|
266
|
-
} catch (error) {
|
|
267
|
-
console.log('Processing interrupted:', error.message);
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
// Resume from where we left off
|
|
271
|
-
const resumeResults = await buffer.processStableBatches(5, processor, {
|
|
272
|
-
cursorName: 'main-processor' // Automatically resumes from cursor position
|
|
273
|
-
});
|
|
274
|
-
```
|
|
275
|
-
|
|
276
|
-
### Parallel Processing with Synchronized Cursors
|
|
277
|
-
|
|
278
|
-
```javascript
|
|
279
|
-
// Create synchronized cursors for multiple workers
|
|
280
|
-
const workers = buffer.createSynchronizedBatchCursors(
|
|
281
|
-
['worker-1', 'worker-2', 'worker-3'],
|
|
282
|
-
20 // batch size
|
|
283
|
-
);
|
|
284
|
-
|
|
285
|
-
// Each worker processes different batches but with identical boundaries
|
|
286
|
-
const results = await Promise.all([
|
|
287
|
-
processWorkerBatches(workers['worker-1']),
|
|
288
|
-
processWorkerBatches(workers['worker-2']),
|
|
289
|
-
processWorkerBatches(workers['worker-3'])
|
|
290
|
-
]);
|
|
291
|
-
|
|
292
|
-
async function processWorkerBatches(worker) {
|
|
293
|
-
const results = [];
|
|
294
|
-
while (true) {
|
|
295
|
-
const batch = worker.next();
|
|
296
|
-
if (batch.done) break;
|
|
297
|
-
|
|
298
|
-
// Process this batch
|
|
299
|
-
const result = await processBatch(batch.entries);
|
|
300
|
-
results.push({ batchId: batch.batchDef.batchId, result });
|
|
301
|
-
}
|
|
302
|
-
return results;
|
|
303
|
-
}
|
|
304
|
-
```
|
|
305
|
-
|
|
306
|
-
### Batch Cursor Iteration
|
|
307
|
-
|
|
308
|
-
```javascript
|
|
309
|
-
// Create a batch cursor for manual iteration
|
|
310
|
-
const cursor = buffer.createBatchCursor('manual-cursor', 15);
|
|
311
|
-
|
|
312
|
-
while (true) {
|
|
313
|
-
const batch = cursor.next();
|
|
314
|
-
if (batch.done) break;
|
|
315
|
-
|
|
316
|
-
console.log(`Processing batch ${batch.batchDef.batchId}`);
|
|
317
|
-
console.log(` Entries: ${batch.entries.length}`);
|
|
318
|
-
console.log(` ID range: ${batch.batchDef.startId}-${batch.batchDef.endId - 1}`);
|
|
319
|
-
|
|
320
|
-
// Process entries
|
|
321
|
-
await processEntries(batch.entries);
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
// Check cursor status
|
|
325
|
-
const status = cursor.getStatus();
|
|
326
|
-
console.log(`Processed batches, ${status.remainingEntries} entries remaining`);
|
|
327
|
-
```
|
|
328
|
-
|
|
329
|
-
### Integration with External Retry Libraries
|
|
330
|
-
|
|
331
|
-
```javascript
|
|
332
|
-
import retry from 'your-retry-library';
|
|
333
|
-
|
|
334
|
-
// Wrap your processor with external retry logic
|
|
335
|
-
const retryProcessor = async (entries, batchDef, context) => {
|
|
336
|
-
return await retry(async () => {
|
|
337
|
-
// Your processing logic that might fail
|
|
338
|
-
return await processEntries(entries);
|
|
339
|
-
}, {
|
|
340
|
-
retries: 3,
|
|
341
|
-
factor: 2
|
|
342
|
-
});
|
|
343
|
-
};
|
|
344
|
-
|
|
345
|
-
// Use with stable batch processing (no built-in retry needed)
|
|
346
|
-
const results = await buffer.processStableBatches(10, retryProcessor, {
|
|
347
|
-
maxRetries: 0 // Disable built-in retry since we're using external
|
|
348
|
-
});
|
|
349
|
-
```
|
|
350
|
-
|
|
351
|
-
### Handling Missing Entries (Eviction)
|
|
352
|
-
|
|
353
|
-
```javascript
|
|
354
|
-
// Small buffer that will evict entries
|
|
355
|
-
const smallBuffer = new RingBuffer(50);
|
|
356
|
-
|
|
357
|
-
// Add lots of data to force eviction
|
|
358
|
-
for (let i = 1; i <= 100; i++) {
|
|
359
|
-
smallBuffer.push(`item-${i}`);
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
// Process with missing entry handling
|
|
363
|
-
const results = await smallBuffer.processStableBatches(10, processor, {
|
|
364
|
-
startId: 1, // Some of these entries may be evicted
|
|
365
|
-
skipMissingEntries: true // Skip batches with no available entries
|
|
366
|
-
});
|
|
367
|
-
|
|
368
|
-
// Check which batches were skipped
|
|
369
|
-
results.forEach(result => {
|
|
370
|
-
if (result.skipped) {
|
|
371
|
-
console.log(`Batch ${result.batchId} was skipped (entries evicted)`);
|
|
372
|
-
}
|
|
373
|
-
});
|
|
374
|
-
```
|
|
375
|
-
|
|
376
|
-
### Advanced Configuration
|
|
377
|
-
|
|
378
|
-
```javascript
|
|
379
|
-
const results = await buffer.processStableBatches(batchSize, processor, {
|
|
380
|
-
// Cursor tracking
|
|
381
|
-
cursorName: 'my-processor', // Track progress with named cursor
|
|
382
|
-
|
|
383
|
-
// Range control
|
|
384
|
-
startId: 100, // Start from specific entry ID
|
|
385
|
-
endId: 500, // End at specific entry ID
|
|
386
|
-
|
|
387
|
-
// Processing mode
|
|
388
|
-
parallel: true, // Process batches in parallel
|
|
389
|
-
|
|
390
|
-
// Retry configuration
|
|
391
|
-
maxRetries: 5, // Maximum retry attempts per batch
|
|
392
|
-
retryDelay: (attempt) => 1000 * attempt, // Custom delay function
|
|
393
|
-
|
|
394
|
-
// Missing entry handling
|
|
395
|
-
skipMissingEntries: true, // Skip batches with evicted entries
|
|
396
|
-
|
|
397
|
-
// Event callbacks
|
|
398
|
-
onBatchStart: (batchDef) => {
|
|
399
|
-
console.log(`Starting ${batchDef.batchId}`);
|
|
400
|
-
},
|
|
401
|
-
onBatchComplete: (batchDef, result) => {
|
|
402
|
-
console.log(`Completed ${batchDef.batchId}`);
|
|
403
|
-
},
|
|
404
|
-
onBatchError: (batchDef, error, attempt) => {
|
|
405
|
-
console.log(`Error in ${batchDef.batchId} (attempt ${attempt}): ${error.message}`);
|
|
406
|
-
}
|
|
407
|
-
});
|
|
408
|
-
```
|
|
409
|
-
|
|
410
|
-
### Stable Batch Definitions
|
|
411
|
-
|
|
412
|
-
```javascript
|
|
413
|
-
// Create stable batch definitions without processing
|
|
414
|
-
const batchDefs = buffer.createStableBatches(10, {
|
|
415
|
-
startId: 50,
|
|
416
|
-
endId: 150,
|
|
417
|
-
batchIdPrefix: 'custom'
|
|
418
|
-
});
|
|
419
|
-
|
|
420
|
-
console.log(`Created ${batchDefs.length} stable batches`);
|
|
421
|
-
|
|
422
|
-
// Later, get entries for a specific batch
|
|
423
|
-
const entries = buffer.getBatchEntries(batchDefs[0]);
|
|
424
|
-
console.log(`Batch ${batchDefs[0].batchId} has ${entries.length} available entries`);
|
|
425
|
-
```
|
|
426
|
-
|
|
427
|
-
### Use Cases
|
|
428
|
-
|
|
429
|
-
**Data Pipeline Processing**: Process large datasets in reliable, resumable batches
|
|
430
|
-
```javascript
|
|
431
|
-
await buffer.processStableBatches(100, async (entries) => {
|
|
432
|
-
return await sendToAPI(entries);
|
|
433
|
-
}, { cursorName: 'pipeline', maxRetries: 3 });
|
|
434
|
-
```
|
|
435
|
-
|
|
436
|
-
**Parallel Worker Processing**: Multiple workers processing different batches
|
|
437
|
-
```javascript
|
|
438
|
-
const workers = buffer.createSynchronizedBatchCursors(['w1', 'w2', 'w3'], 50);
|
|
439
|
-
// Each worker gets identical batch boundaries for consistent processing
|
|
440
|
-
```
|
|
441
|
-
|
|
442
|
-
**Fault-Tolerant Batch Jobs**: Resume exactly where processing was interrupted
|
|
443
|
-
```javascript
|
|
444
|
-
// Job can be interrupted and resumed with identical batch boundaries
|
|
445
|
-
await buffer.processStableBatches(25, processor, {
|
|
446
|
-
cursorName: 'batch-job',
|
|
447
|
-
maxRetries: 5
|
|
448
|
-
});
|
|
449
|
-
```
|
|
450
|
-
|
|
451
|
-
**Memory-Efficient Stream Processing**: Process continuous data streams in batches
|
|
452
|
-
```javascript
|
|
453
|
-
const cursor = buffer.createBatchCursor('stream', 20);
|
|
454
|
-
setInterval(async () => {
|
|
455
|
-
const batch = cursor.next();
|
|
456
|
-
if (!batch.done) {
|
|
457
|
-
await processStreamBatch(batch.entries);
|
|
458
|
-
}
|
|
459
|
-
}, 1000);
|
|
460
|
-
```
|