s3db.js 10.0.16 → 10.0.18
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/s3db.cjs.js +1766 -1549
- package/dist/s3db.cjs.js.map +1 -1
- package/dist/s3db.es.js +1766 -1549
- package/dist/s3db.es.js.map +1 -1
- package/package.json +1 -1
- package/src/plugins/eventual-consistency/analytics.js +668 -0
- package/src/plugins/eventual-consistency/config.js +156 -0
- package/src/plugins/eventual-consistency/consolidation.js +770 -0
- package/src/plugins/eventual-consistency/garbage-collection.js +126 -0
- package/src/plugins/eventual-consistency/helpers.js +179 -0
- package/src/plugins/eventual-consistency/index.js +455 -0
- package/src/plugins/eventual-consistency/locks.js +77 -0
- package/src/plugins/eventual-consistency/partitions.js +45 -0
- package/src/plugins/eventual-consistency/setup.js +298 -0
- package/src/plugins/eventual-consistency/transactions.js +119 -0
- package/src/plugins/eventual-consistency/utils.js +172 -0
- package/src/plugins/eventual-consistency.plugin.js +195 -2
- package/src/plugins/index.js +1 -1
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration handling for EventualConsistencyPlugin
|
|
3
|
+
* @module eventual-consistency/config
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Create default configuration with options
|
|
8
|
+
* @param {Object} options - User-provided options (nested format)
|
|
9
|
+
* @param {string} detectedTimezone - Auto-detected timezone
|
|
10
|
+
* @returns {Object} Complete configuration object
|
|
11
|
+
*/
|
|
12
|
+
export function createConfig(options, detectedTimezone) {
|
|
13
|
+
// Extract nested configs with defaults
|
|
14
|
+
const consolidation = options.consolidation || {};
|
|
15
|
+
const locks = options.locks || {};
|
|
16
|
+
const gc = options.garbageCollection || {};
|
|
17
|
+
const analytics = options.analytics || {};
|
|
18
|
+
const batch = options.batch || {};
|
|
19
|
+
const lateArrivals = options.lateArrivals || {};
|
|
20
|
+
const checkpoints = options.checkpoints || {};
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
// Cohort (timezone)
|
|
24
|
+
cohort: {
|
|
25
|
+
timezone: options.cohort?.timezone || detectedTimezone
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
// Reducer function
|
|
29
|
+
reducer: options.reducer || ((transactions) => {
|
|
30
|
+
let baseValue = 0;
|
|
31
|
+
for (const t of transactions) {
|
|
32
|
+
if (t.operation === 'set') {
|
|
33
|
+
baseValue = t.value;
|
|
34
|
+
} else if (t.operation === 'add') {
|
|
35
|
+
baseValue += t.value;
|
|
36
|
+
} else if (t.operation === 'sub') {
|
|
37
|
+
baseValue -= t.value;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return baseValue;
|
|
41
|
+
}),
|
|
42
|
+
|
|
43
|
+
// Consolidation settings
|
|
44
|
+
consolidationInterval: consolidation.interval ?? 300,
|
|
45
|
+
consolidationConcurrency: consolidation.concurrency ?? 5,
|
|
46
|
+
consolidationWindow: consolidation.window ?? 24,
|
|
47
|
+
autoConsolidate: consolidation.auto !== false,
|
|
48
|
+
mode: consolidation.mode || 'async',
|
|
49
|
+
|
|
50
|
+
// Late arrivals
|
|
51
|
+
lateArrivalStrategy: lateArrivals.strategy || 'warn',
|
|
52
|
+
|
|
53
|
+
// Batch transactions
|
|
54
|
+
batchTransactions: batch.enabled || false,
|
|
55
|
+
batchSize: batch.size || 100,
|
|
56
|
+
|
|
57
|
+
// Locks
|
|
58
|
+
lockTimeout: locks.timeout || 300,
|
|
59
|
+
|
|
60
|
+
// Garbage collection
|
|
61
|
+
transactionRetention: gc.retention ?? 30,
|
|
62
|
+
gcInterval: gc.interval ?? 86400,
|
|
63
|
+
|
|
64
|
+
// Analytics
|
|
65
|
+
enableAnalytics: analytics.enabled || false,
|
|
66
|
+
analyticsConfig: {
|
|
67
|
+
periods: analytics.periods || ['hour', 'day', 'month'],
|
|
68
|
+
metrics: analytics.metrics || ['count', 'sum', 'avg', 'min', 'max'],
|
|
69
|
+
rollupStrategy: analytics.rollupStrategy || 'incremental',
|
|
70
|
+
retentionDays: analytics.retentionDays ?? 365
|
|
71
|
+
},
|
|
72
|
+
|
|
73
|
+
// Checkpoints
|
|
74
|
+
enableCheckpoints: checkpoints.enabled !== false,
|
|
75
|
+
checkpointStrategy: checkpoints.strategy || 'hourly',
|
|
76
|
+
checkpointRetention: checkpoints.retention ?? 90,
|
|
77
|
+
checkpointThreshold: checkpoints.threshold ?? 1000,
|
|
78
|
+
deleteConsolidatedTransactions: checkpoints.deleteConsolidated !== false,
|
|
79
|
+
autoCheckpoint: checkpoints.auto !== false,
|
|
80
|
+
|
|
81
|
+
// Debug
|
|
82
|
+
verbose: options.verbose || false
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Validate resources configuration
|
|
88
|
+
* @param {Object} resources - Resources configuration
|
|
89
|
+
* @throws {Error} If configuration is invalid
|
|
90
|
+
*/
|
|
91
|
+
export function validateResourcesConfig(resources) {
|
|
92
|
+
if (!resources || typeof resources !== 'object') {
|
|
93
|
+
throw new Error(
|
|
94
|
+
"EventualConsistencyPlugin requires 'resources' option.\n" +
|
|
95
|
+
"Example: { resources: { urls: ['clicks', 'views'], posts: ['likes'] } }"
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
for (const [resourceName, fields] of Object.entries(resources)) {
|
|
100
|
+
if (!Array.isArray(fields)) {
|
|
101
|
+
throw new Error(
|
|
102
|
+
`EventualConsistencyPlugin resources.${resourceName} must be an array of field names`
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Log configuration warnings
|
|
110
|
+
* @param {Object} config - Configuration object
|
|
111
|
+
*/
|
|
112
|
+
export function logConfigWarnings(config) {
|
|
113
|
+
// Warn about batching in distributed environments
|
|
114
|
+
if (config.batchTransactions && !config.verbose) {
|
|
115
|
+
console.warn(
|
|
116
|
+
`[EventualConsistency] WARNING: batch.enabled is true. ` +
|
|
117
|
+
`This stores transactions in memory and will lose data if container crashes. ` +
|
|
118
|
+
`Not recommended for distributed/production environments.`
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Warn if checkpoints are disabled in high-volume scenarios
|
|
123
|
+
if (!config.enableCheckpoints && !config.verbose) {
|
|
124
|
+
console.warn(
|
|
125
|
+
`[EventualConsistency] INFO: checkpoints.enabled is false. ` +
|
|
126
|
+
`Checkpoints improve performance in high-volume scenarios by creating snapshots. ` +
|
|
127
|
+
`Consider enabling for production use.`
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Log initialization information
|
|
134
|
+
* @param {Object} config - Configuration object
|
|
135
|
+
* @param {Map} fieldHandlers - Field handlers map
|
|
136
|
+
* @param {boolean} timezoneAutoDetected - Whether timezone was auto-detected
|
|
137
|
+
*/
|
|
138
|
+
export function logInitialization(config, fieldHandlers, timezoneAutoDetected) {
|
|
139
|
+
if (!config.verbose) return;
|
|
140
|
+
|
|
141
|
+
const totalFields = Array.from(fieldHandlers.values())
|
|
142
|
+
.reduce((sum, handlers) => sum + handlers.size, 0);
|
|
143
|
+
|
|
144
|
+
console.log(
|
|
145
|
+
`[EventualConsistency] Initialized with ${fieldHandlers.size} resource(s), ` +
|
|
146
|
+
`${totalFields} field(s) total`
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
// Log timezone if not explicitly set by user
|
|
150
|
+
if (timezoneAutoDetected) {
|
|
151
|
+
console.log(
|
|
152
|
+
`[EventualConsistency] Using timezone: ${config.cohort.timezone} ` +
|
|
153
|
+
`(${process.env.TZ ? 'from TZ env var' : 'default UTC'})`
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
}
|